Setting up your routes using the Phalcon\Mvc\Micro applications verb methods (get, post, etc.) is much easier than setting up a router object with relevant routes and then injecting it in the application.

Each method has its advantages and disadvantages. It all depends on the design and needs of your application.

Rewrite Rules

In order for routes to work, certain configuration changes need to be made in your web server’s configuration for your particular site.

Handlers

Handlers are callable pieces of code that get attached to a route. When the route is matched, the handler is executed with all the defined parameters. A handler is any callable piece of code that exists in PHP.

Definitions

Phalcon offers several ways to attach a handler to a route. Your application needs and design as well as coding style will be the factors influencing your choice of implementation.

Anonymous Function

Finally we can use an anonymous function (as seen above) to handle the request

Controllers

With the Phalcon\Mvc\Micro you can create micro or medium applications. Medium applications use the micro architecture but expand on it to utilize more than the Micro but less than the Full application.

In medium applications you can organize handlers in controllers.

<?phpusePhalcon\Mvc\Micro\CollectionasMicroCollection;$orders=newMicroCollection();// Set the main handler. ie. a controller instance$orders->setHandler(newOrdersController());// Set a common prefix for all routes$orders->setPrefix('/orders');// Use the method 'index' in OrdersController$orders->get('/','index');// Use the method 'show' in OrdersController$orders->get('/display/{slug}','show');$app->mount($orders);

Use case

We are developing an API for an online store. The endpoints are /users, /orders and /products. Each of those endpoints are registered using handlers, and each handler is a controller with relevant actions.

This implementation loads each handler in turn and mounts it in our application object. The issue with this approach is that each request will result to only one endpoint and therefore one class method executed. The remaining methods/handlers will just remain in memory without being used.

Using lazy loading we reduce the number of objects loaded in memory and as a result our application uses less memory.

The above implementation changes if we want to use lazy loading as follows:

Using this simple change in implementation, all handlers remain uninstantiated until requested by a caller. Therefore whenever a caller requests /orders/get/2, our application will instantiate the OrdersController and call the get method in it. Our application now uses less resources than before.

Not found (404)

Any route that has not been matched in our Phalcon\Mvc\Micro application will cause it to try and execute the handler defined with the notFound method. Similar to other methods/verbs (get, post etc.), you can register a handler in the notFound method which can be any callable PHP function.

We can also enforce certain rules for each parameter by using regular expressions. The regular expression is set after the name of the parameter, separating it with :.

// Match the order id$app->get('/orders/display/{id:[0-9]+}',function($id){echo"<h1>This is order: #{$id}!</h1>";});// Match a numeric (4) year and a title (alpha)$app->get('/posts/{year:[0-9][4]}/{title:[a-zA-Z\-]+}',function($year,$title){echo'<h1>Title: $title</h1>';echo'<h2>Year: $year</h2>';});

You can also create a Di container yourself, and assign it to the micro application, therefore manipulating the services depending on the needs of your application.

<?phpusePhalcon\Mvc\Micro;usePhalcon\Di\FactoryDefault;usePhalcon\Config\Adapter\IniasIniConfig;$di=newFactoryDefault();$di->set('config',function(){returnnewIniConfig('config.ini');});$app=newMicro();$app->setDI($di);$app->get('/',function()use($app){// Read a setting from the configecho$app->config->app_name;});$app->post('/contact',function()use($app){$app->flash->success('What are you doing Dave?');});

You can also use the array syntax to register services in the dependency injection container from the application object:

Including another file

Direct output JSON

New Response object

You can use the setContent method of the response object to return the response back:

$app->get('/show/data',function(){// Create a response$response=newPhalcon\Http\Response();// Set the Content-Type header$response->setContentType('text/plain');// Pass the content of a file$response->setContent(file_get_contents('data.txt'));// Return the responsereturn$response;});

Application Response

You can also use the Phalcon\Http\Response object to return responses to the caller. The response object has a lot of useful methods that make returning respones much easier.

$app->get('/show/data',function()use($app){// Set the Content-Type header$app->response->setContentType('text/plain');$app->response->sendHeaders();// Print a filereadfile('data.txt');});

Return Application Response

A different approach returning data back to the caller is to return the response object directly from the application. When responses are returned by handlers they are automatically sent by the application.

<?phpusePhalcon\Mvc\Micro;usePhalcon\Http\Response;$app=newMicro();// Return a response$app->get('/welcome/index',function(){$response=newResponse();$response->setStatusCode(401,'Unauthorized');$response->setContent('Access is not authorized');return$response;});

Events

A Phalcon\Mvc\Micro application works closely with a Phalcon\Events\Manager if it is present, to trigger events that can be used throughout our application. The type of those events is micro. These events trigger in our application and can be attached to relevant handlers that will perform actions needed by our application.

Available events

The following events are supported:

Event Name

Triggered

Can stop operation?

beforeHandleRoute

Main method called; Routes have not been checked yet

Yes

beforeExecuteRoute

Route matched, Handler valid, Handler has not been executed yet

Yes

afterExecuteRoute

Handler just finished running

No

beforeNotFound

Route has not been found

Yes

afterHandleRoute

Route just finished executing

Yes

afterBinding

Triggered after models are bound but before executing the handler

Yes

Authentication example

You can easily check whether a user has been authenticated or not using the beforeExecuteRoute event.
In the following example, we explain how to control the application security using events:

Not found example

You can easily check whether a user has been authenticated or not using the beforeExecuteRoute event.
In the following example, we explain how to control the application security using events:

<?phpusePhalcon\Mvc\Micro;usePhalcon\Events\Event;usePhalcon\Events\ManagerasEventsManager;// Create a events manager$eventsManager=newEventsManager();$eventsManager->attach('micro:beforeNotFound',function(Event$event,$app){$app->response->redirect('/404');$app->response->sendHeaders();return$app->response;});$app=newMicro();// Bind the events manager to the app$app->setEventsManager($eventsManager);

Middleware

Middleware are classes that can be attached to your application and introduce another layer where business logic can exist. They run sequentially, according to the order they are registered and not only improve mainainability, by encapsulating specific functionality, but also performance. A middleware class can stop execution when a particular business rule has not been satisfied, thus allowing the application to exit early without executing the full cycle of a request.

The presence of a Phalcon\Events\Manager is essential for middleware to operate, so it has to be registered in our Di container.

Attached events

Middleware can be attached to a micro application in 3 different events. Those are:

Event

Description

before

Before the handler has been executed

after

After the handler has been executed

final

After the response has been sent to the caller

You can attach as many middleware classes as you want in each of the above events. They will be executed sequentially when the relevant event fires.

before

This event is perfect for stopping execution of the application if certain criteria is not met. In the below example we are checking if the user has been authenticated and stop execution with the necessary redirect.

Setup

Attaching middleware to your application is very easy as shown above, with the before, after and finish method calls.

$app->before(function()use($app){if(false===$app['session']->get('auth')){$app['flashSession']->error("The user isn't authenticated");$app['response']->redirect('/error');// Return false stops the normal executionreturnfalse;}returntrue;});$app->after(function()use($app){// This is executed after the route is executedechojson_encode($app->getReturnedValue());});

Attaching middleware to your application as classes and having it listen to events from the events manager can be achieved as follows:

<?phpusePhalcon\Events\Manager;usePhalcon\Mvc\Micro;useWebsite\Middleware\CacheMiddleware;useWebsite\Middleware\NotFoundMiddleware;useWebsite\Middleware\ResponseMiddleware;/**
* Create a new Events Manager.
*/$eventsManager=newManager();$application=newMicro();/**
* Attach the middleware both to the events manager and the application
*/$eventsManager->attach('micro',newCacheMiddleware());$application->before(newCacheMiddleware());$eventsManager->attach('micro',newNotFoundMiddleware());$application->before(newNotFoundMiddleware());/**
* This one needs to listen on the `after` event
*/$eventsManager->attach('micro',newResponseMiddleware());$application->after(newResponseMiddleware());/**
* Make sure our events manager is in the DI container now
*/$application->setEventsManager($eventsManager);

We need a Phalcon\Events\Manager object. This can be a newly instantiated object or we can get the one that exists in our DI container (if you have used the FactoryDefault one).

We attach every middleware class in the micro hook in the Events Manager. We could also be a bit more specific and attach it to say the micro:beforeExecuteRoute event.

We then attach the middleware class in our application on one of the three listening events discussed above (before, after, finish).

Implementation

Middleware can be any kind of PHP callable functions. You can organize your code whichever way you like it to implement middleware. If you choose to use classes for your middleware, you will need them to implement the Phalcon\Mvc\Micro\MiddlewareInterface

Events in Middleware

The events that are triggered for our application also trigger inside a class that implements the Phalcon\Mvc\Micro\MiddlewareInterface. This offers great flexibility and power for developers since we can interact with the request process.

API example

Assume that we have an API that we have implemented with the Micro application. We will need to attach different Middleware classes in the application so that we can better control the execution of the application.

The middleware that we will use are:

Firewall

NotFound

Redirect

CORS

Request

Response

Firewall Middleware

This middleware is attached to the before event of our Micro application. The purpose of this middleware is to check who is calling our API and based on a whitelist, allow them to proceed or not

Not Found Middleware

When this middleware is processed, this means that the requesting IP is allowed to access our application. The application will try and match the route and if not found the beforeNotFound event will fire. We will stop the processing then and send back to the user the relevant 404 response. This middleware is attached to the before event of our Micro application

Inject model instances

<?php$loader=new\Phalcon\Loader();$loader->registerDirs([__DIR__.'/models/',])->register();$app=new\Phalcon\Mvc\Micro();$app->setModelBinder(new\Phalcon\Mvc\Model\Binder());$app->get("/products/{product:[0-9]+}",function(Products$product){// do anything with $product object});$app->handle();

Since Binder object is using internally Reflection Api which can be heavy, there is ability to set a cache so as to speed up the process. This can be done by using the second argument of setModelBinder() which can also accept a service name or just by passing a cache instance to the Binder constructor.

Currently the binder will only use the models primary key to perform a findFirst() on. An example route for the above would be /products/1.

The above example uses the Phalcon\Mvc\View\Simple component, which uses relative paths instead of controllers and actions. You can use the Phalcon\Mvc\View component instead, but to do so you will need to change the parameters passed to render()