Getting started
Routing and controllers
Command line
Databases (SQL)
Databases (NoSQL)
Security
Packages
Learn more
- Array helper
- Caching
- Collections
- Command, event and query buses
- Date and time
- File system
- HTML helper
- Humanizer
- Image manipulation
- Internationalization
- Logging
- Number helper
- Pagination
- Retry helper
- Sessions
- String helper
- URL builder
- UUID helper
- Validation
- Views
Official packages
Upgrading
This guide takes you through the steps needed to migrate from Mako 9.1.x
to 10.0.x
.
Mako 10.0
drops support for PHP version 8.0 and requires PHP version 8.1 or higher so make sure that your environment is up to date.
Application structure
Mako 10.0
comes with a new and improved directory strucute. Controllers and routing configuration has been moved to the app\http
namespace. You can move the app/controllers
and app/routing
directories to the app/http/(controllers|routing)
directory and update namespaces accordingly or you can continue to use the legacy structure.
If you choose to keep using the legacy structure then you'll have to override the HttpService
:
<?php
namespace app\services;
use mako\application\services\HTTPService as HttpBaseService;
class HttpService extends HttpBaseService
{
protected function getRoutingPath(): string
{
return "{$this->app->getPath()}/routing";
}
}
Routing
Constraints
The Router::registerConstraint()
and Router::setConstraintAsGlobal()
methods have been removed and all calls to the methods must be removed from your app/http/routing/constraints.php
configuration file.
If you want to register global constraints in Mako 10.0
then you'll have to use the new Router::registerGlobalConstraint()
method:
<?php
// Before
$router->setConstraintAsGlobal([ApiVersionConstraint::class]);
// Now
$router->registerGlobalConstraint(ApiVersionConstraint::class);
// You can now pass arguments to global constraints
$router->registerGlobalConstraint(ApiVersionConstraint::class, version: '2.0');
Assigning constraints to a route is still done using the Route::constraint()
method or Constraint
attribute. However the Route::constraint()
method will now have to be called multiple times when registering multiple constraints to a route:
<?php
// Before
$routes->get('/', fn () => 'Hello, world!')
->constraint([
FooConstraint::class,
BarConstraint::class,
]);
// Now
$routes->get('/', fn () => 'Hello, world!')
->constraint(FooConstraint::class)
->constraint(BarConstraint::class);
// You can now pass arguments to constraints
$routes->get('/', fn () => 'Hello, world!')
->constraint(FooConstraint::class, foo: 123)
->constraint(BarConstraint::class, bar: 456);
Read all about the new constraint features here.
Middleware
The Dispatcher::registerMiddleware()
and Dispatcher::setMiddlewareAsGlobal()
methods have been removed and all calls to the methods must be removed from your app/http/routing/middleware.php
configuration file.
If you want to register global middleware in Mako 10.0
then you'll have to use the new Dispatcher::registerGlobalMiddleware()
method:
<?php
// Before
$dispatcher->setMiddlewareAsGlobal([AccessControl::class]);
// Now
$dispatcher->registerGlobalMiddleware(AccessControl::class);
// You can now pass arguments to global middleware
$dispatcher->registerGlobalMiddleware(CacheMiddleware::class, minutes: 60);
Setting middleware priority is still done using the Dispatcher::setMiddlewarePriority()
method although instead of passing an array of middleware and priorities you make multiple calls to the method when registering multiple priorities:
<?php
// Before
$dispatcher->setMiddlewarePriority([
FooMiddleware::class => 1,
BarMiddleware::class => 2,
]);
// Now
$dispatcher->setMiddlewarePriority(FooMiddleware::class, 1);
$dispatcher->setMiddlewarePriority(BarMiddleware::class, 2);
Assigning middleware to a route is still done using the Route::middleware()
method or Middleware
attribute. However the Route::middleware()
method will now have to be called multiple times when registering multiple middleware to a route:
// Before
$routes->get('/', fn () => 'Hello, world!')
->middleware([
FooMiddleware::class,
BarMiddleware::class,
]);
// Now
$routes->get('/', fn () => 'Hello, world!')
->middleware(FooMiddleware::class)
->middleware(BarMiddleware::class);
// You can now pass arguments to middleware
$routes->get('/', fn () => 'Hello, world!')
->middleware(FooMiddleware::class, foo: 123)
->middleware(BarMiddleware::class, bar: 456);
The syntax for assigning middleware in route groups has also been sligtly changed:
<?php
// Without arguments
$options = [
'middleware' => [CacheMiddleware::class],
];
$routes->group($options, function ($routes) {
$routes->get('/', fn () => 'Hello, world!');
});
// With arguments
$options = [
'middleware' => [[CacheMiddleware::class, ['minutes' => 60]]],
];
$routes->group($options, function ($routes) {
$routes->get('/', fn () => 'Hello, world!');
});
Read all about the new middleware features here.
Typed properties
Mako 10.0
introduces typed properties in all of its core classes so you'll have to update any class that extend the core.
Built in middleware
The AccessControl
middleware properties must be updated to use typed properties:
<?php
namespace app\http\routing\middleware;
use mako\http\routing\middleware\AccessControl as AccessControlMiddleware;
class AccessControl extends AccessControlMiddleware
{
protected bool $allowCredentials = false;
protected bool $allowAllDomains = false;
protected array $allowedDomains = [];
protected array $allowedHeaders = [];
protected array $allowedMethods = [];
}
The ContentSecurityPolicy
middleware properties must be updated to use typed properties:
<?php
namespace app\http\routing\middleware;
use mako\http\routing\middleware\ContentSecurityPolicy as ContentSecurityPolicyMiddleware;
class ContentSecurityPolicy extends ContentSecurityPolicyMiddleware
{
protected array $reportTo = [];
protected bool $reportOnly = false;
protected array $directives = [
'base-uri' => ['self'],
'default-src' => ['self'],
'object-src' => ['none'],
];
}
The SecurityHeaders
middleware properties muse be updated to use typed properties:
<?php
namespace app\http\routing\middleware;
use mako\http\routing\middleware\SecurityHeaders as SecurityHeadersMiddleware;
class SecurityHeaders extends SecurityHeadersMiddleware
{
protected array $headers = [
'X-Content-Type-Options' => 'nosniff',
'X-Frame-Options' => 'sameorigin',
'X-XSS-Protection' => '1; mode=block',
];
}
Commands
Your commands might not need any changes at all but here are all the properites that will have to be updated:
<?php
namespace app\console\commands;
use mako\reactor\Command;
class MyCommand extends Command
{
protected string $command;
protected string $description;
}
Custom validation rules
If you have implemented custom validation rules that use the I18nAwareTrait
trait then you'll have to update the types of the $i18nParameters
and $i18nFieldNameParameters
properties.
<?php
namespace app\support\validation;
use mako\validator\rules\RuleInterface;
use mako\validator\rules\traits\I18nAwareTrait;
class MyRule implements RuleInterface
{
use I18nAwareTrait;
protected array $i18nParameters = [];
protected array $i18nFieldNameParameters = [];
// The rest of the validation rule implementation goes here ...
}
Migrations
If your application has migrations then you'll have to update the $description
property to be typed:
protected string $description = '...';
ORM
Your models might not need any changes at all but here are all the properites that will have to be updated:
<?php
namespace app\models;
use mako\database\midgard\ORM;
class Example extends ORM
{
protected null|string $connectionName = null;
protected string $tableName;
protected string $foreignKeyName;
protected string $primaryKey = 'id';
protected int $primaryKeyType = ORM::PRIMARY_KEY_TYPE_INCREMENTING;
protected array $including = [];
protected array $cast = [];
protected array $assignable = [];
protected array $protected = [];
protected string $dateOutputFormat = 'Y-m-d H:i:s';
protected string $lockingColumn = 'lock_version'; // Used with the OptimisticLockingTrait trait
protected array $nullable = []; // Used with the NullableTrait trait
protected string $createdAtColumn = 'created_at'; // Used with the TimestampedTrait trait
protected string $updatedAtColumn = 'updated_at'; // Used with the TimestampedTrait trait
protected array $touch = []; // Used with the TimestampedTrait trait
protected bool $shouldTouchOnInsert = true; // Used with the TimestampedTrait trait
protected bool $shouldTouchOnUpdate = true; // Used with the TimestampedTrait trait
protected bool $shouldTouchOnDelete = true; // Used with the TimestampedTrait trait
}
Packages
If you have created a custom Mako package then you'll have to update the package class to use typed properties:
<?php
namespace acme;
use mako\application\Package;
class MyPackage extends Package
{
protected string $packageName = 'acme/my-package';
protected array $commands = [];
}