We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

REST API routes with Phalcon Micro

Using full Phalcon framework I can initialize my REST API routes using the following code:

    $router = new \Phalcon\Mvc\Router();

    $router->addGet('#^/api/?([\\w\\-]*)(/?.*)$#', [
    'controller' => 1,
    'action'     => 'read',
    'params'     => 2
    ]);

    $router->addPost('#^/api/?([\\w\\-]*)(/?.*)$#', [
    'controller' => 1,
    'action'     => 'create',
    'params'     => 2
    ]);

    $router->addPut('#^/api/?([\\w\\-]*)/([0-9]+)(/?.*)$#', [
    'controller' => 1,
    'id'         => 2,
    'action'     => 'update',
    'params'     => 3
    ]);

    $router->addDelete('#^/api/?([\\w\\-]*)/([0-9]+)(/?.*)$#', [
    'controller' => 1,
    'id'         => 2,
    'action'     => 'destroy',
    'params'     => 3
    ]);

Can I achieve the same behavior using Phalcon Micro (Phalcon\Mvc\Micro\Collection)? Basically I would like to automatically get controller and params from url.



43.9k

Hi,

yep collections are helpfull: https://docs.phalcon.io/en/latest/reference/micro.html#using-controllers-as-handlers

But, as is, you'll have to declare all the controllers and their given actions.

So, it's not possible to automatically get controller from url in Micro? I guess I would have to do something similar like it's done here if I want to use micro? I'll just stick with full framework if that's the case...



43.9k
Accepted
answer

You are right, the example you gave is a workaround for parsing url segments and make them match to controllers/actions/params.

Maybe (I've never tested it), you can just register the "mvc" router in your micro app bootstrap file.


<?php

use Phalcon\Mvc\Router;

// Create the router
$router = new Router();

//Define a route
$router->addGet
    "/admin/users/my-profile",
    array(
        "controller" => "users",
        "action"     => "profile",
    )
);

//Another route
$router->addPut
    "/admin/users/change-password",
    array(
        "controller" => "users",
        "action"     => "changePassword",
    )
);

$router->handle();

Maybe (I've never tested it), you can just register the "mvc" router in your micro app bootstrap file.

What would be the point of MicroCollection if we could just use the MvcRouter in Micro app and get the same effect? I don't think it's a valid solution. Anyway, thanks for confirming that what I want to do is not currently possible in Micro app.



43.9k

Again, you're right, I'm not sure at all if using roputer's facilities in micro app is a valid approach.



144

Hello, as the documentation states it is ok to use it if it is a medium app, I basically use micro when I don't need to serve views, just data, and controllers help to keep a better organization of the application.

Here I share my class to work with the routes, watch out that I also have implemented ACL and roles so it also takes care of security at the same time:

use Phalcon\DI\Injectable;
use Phalcon\Mvc\Micro\Collection as MicroCollection;

class RouteCollection extends Injectable {

    private $controller;
    private $collection;
    private $route;

    public function __construct($di, $controller) {
        $this->setDI($di);

        $this->controller = new $controller;

        $this->collection = new MicroCollection;
        $this->collection->setHandler($this->controller);

        $this->route = (object) [
            'url' => '',
            'method' => '',
            'action' => '',
            'roles' => [],
        ];
    }

    public function add($url) {
        $this->route->url = $url;

        return $this;
    }

    public function via($method) {
        $this->route->method = $method;

        return $this;
    }

    public function to($action) {
        $this->route->action = $action;

        return $this;
    }

    public function by() {
        $roles = func_get_args();

        $this->collection->{$this->route->method}($this->route->url, $this->route->action);
        $this->acl->addResource($this->route->url, strtoupper($this->route->method), $roles);

        return $this;
    }

    public function mount() {
        $this->application->mount($this->collection);
    }

}

Then to add routes is just like:

$routes = new RouteCollection($di, 'UsersController');

$routes->add('/users')
    ->via('get')->to('getAll')->by('admin')
    ->via('post')->to('create')->by('guest', 'admin');

$routes->add('/users/{id:[0-9]+}')
    ->via('get')->to('get')->by('guest', 'user', 'admin')
    ->via('put')->to('update')->by('user', 'admin')
    ->via('delete')->to('delete')->by('user', 'admin');

$routes->add('/users/login')
    ->via('post')->to('login')->by('guest', 'user', 'admin');

$routes->add('/users/logout')
    ->via('post')->to('logout')->by('user', 'admin');

$routes->add('/users/find/{alias}')
    ->via('get')->to('find')->by('guest', 'user', 'admin');

$routes->mount();