Revision: Fri, 20 Dec 2024 23:34:21 GMT

Keeper — Routing

Keeper routes are accessible via global Spiral\Router\RouterInterface. You can register them directly in the router or via the keeper bootloader and annotations. The last options allow you to isolate all the routes in the given namespace.

Permissions

GuardInterceptor is added to the KeeperCore by default, use @GuardNamespace and @Guarded to create a permission. If @Guarded annotation is missed, KeeperCore will protect a method using namespace.controller.method permission as a fallback.

Register routes via bootloader or Router

New route should be declared after the parent::boot() call. Controllers must be declared before the route declaration:

php
use Spiral\Boot\BootloadManager;
use Spiral\Keeper\Bootloader;
use Spiral\Router\RouterInterface;

class AdminBootloader extends Bootloader\KeeperBootloader
{
    protected const NAMESPACE = 'admin';
    protected const PREFIX    = '/admin';

    public function boot(BootloadManager $bootloadManager, RouterInterface $appRouter): void
    {
        parent::boot($bootloadManager, $appRouter);

        // Controllers are used via aliases
        $this->addController('user', 'App\Admin\Controller\User');
        $this->addRoute('/users/new', 'user', 'new', ['GET'], 'createUser');
    }
}

The next routes will be created (see php app.php route:list output):

+-------------------+--------+------------------+---------------------------------- +
| Name:             | Verbs: | Pattern:         | Target:                           |
+-------------------+--------+------------------+---------------------------------- +
| admin[createUser] | POST   | /admin/users/new | App\Admin\Controller\User->create |
| admin[user.new]   | GET    | /admin/users/new | user->new                         |
+-------------------+--------+------------------+---------------------------------- +

Note
Routes will be duplicated by a generated name like controller.method.

Register routes via annotations

Attributes are a more convenient way because annotated routes allows you to use sitemaps - another powerful submodule for building menu navigation and breadcrumbs.

\Spiral\Keeper\Annotation\Action and \Spiral\Keeper\Annotation\Controller attributes are available. They should be used together.

Controller defines:

  • current namespace (optional, keeper by default)
  • internal name/alias (required)
  • prefix (optional), used for all actions within the controller
  • default action defaultAction (optional)

Action works pretty much the same as a basic Route annotation from the framework annotated routes. It defines:

  • route pattern (required)
  • name (optional, controller.action will be used as a fallback)
  • methods (optional)
  • defaults (optional)
  • group (not used for now)
  • middleware (optional)

Example:

php
use Spiral\Keeper\Annotation\Action;
use Spiral\Keeper\Annotation\Controller;
use Spiral\Views\ViewsInterface;

#[Controller(namespace: "admin", name: "user", prefix: "/users")]
class User
{

     #[Action(route: "/create", name: "createUser", methods: "GET")]
    public function create(ViewsInterface $views): string
    {
        return $views->render('admin:users/create');
    }
}

The next routes will be created (see php app.php route:list output):

+--------------------+--------+---------------------+--------------+
| Name:              | Verbs: | Pattern:            | Target:      |
+--------------------+--------+---------------------+--------------+
| admin[createUser]  | GET    | /admin/users/create | user->create |
| admin[user.create] | GET    | /admin/users/create | user->create |
+--------------------+--------+---------------------+--------------+

Note
Routes will be duplicated by a generated name like controller.method.

Namespace

You can either call a route by its name directly or using a RouteBuilder

php
/**
 * @var \Spiral\Router\RouterInterface     $router 
 * @var \Spiral\Keeper\Helper\RouteBuilder $routeBuilder
 */
 
$router->uri('admin[user.create]');
$routeBuilder->uri('admin', 'user.create');

The output will be the same: /admin/users/new

Note
RouteBuilder takes care about namespace isolation pattern.

Defaults

To enable default controller routing, it should be added explicitly to the config. Either via KeeperBootloader::DEFAULT_CONTROLLER value or via config file:

php
return [
     'routeDefaults' => ['controller' => 'App\Admin\Controller'],
];

Default controller action can be also defined either in the config:

php
return [
     'routeDefaults' => ['controller' => 'App\Admin\Controller', 'action' => 'list'],
];

or via defaultAction property in @Controller annotation.

Note
For default controller index method will be used as a fallback if no defaultAction provided in the default controller annotation.