Home | Github

Extending Exedra

Table of Contents



Introduction

There might comes a point where you need to use your own ServerRequest, Application, Context, and so on. Fear no longer.

Application

Most cases are done through factory registry, except the Application, since it's the first.

Exedra\Application

<?php
namespace CoolApp;

class Application extends \Exedra\Application
{
}

Usage

$app = new \CoolApp\Application(__DIR__);

Services

Exedra\Http\ServerRequest

$app->set('request', function(){
    return \CoolApp\ServerRequest::createFromGlobals();
})

Exedra\Config

$app->set('config', \CoolApp\Config::class);

Factories

Exedra\Url\UrlFactory

$app->factory('url.factory', \CoolApp\Url\Factory);

Exedra\Runtime\Context

All created Context will use this one instead.

$app->factory('runtime.context', \CoolApp\Context::class);

Or if you even rather want to have much contextual Context

$app->factory('runtime.context', function($app, \Exedra\Routing\Finding $finding, $response) {
    if($context = $finding->getAttribute('context'))
        return new $context($app, $finding, $response);

    return new \CoolApp\Context($app, $finding, $response);
});

Exedra\Runtime\Response

$app->factory('runtime.response', \CoolApp\Response::class);

Routing classes

You can define your own routing classes through this way

$app->routingFactory->register(array(
    'finding' => \CoolApp\Routing\Finding::class,
    'route' => \CoolApp\Routing\Route::class,
    'group' => \CoolApp\Routing\Group::class
));

Routing Handling

Group Handler

You can design the way your routing group is resolved. First create an handler that implements Exedra\Contracts\Routing\GroupHandler.

Implementation example :

use Exedra\Contracts\Routing\GroupHandler;
use Exedra\Routing\Group;

class CollectionHandler implements GroupHandler
{
     /**
     * @param mixed $pattern
     * @param Route|null $route
     * @return boolean
     */
    public function validateGroup($pattern, Route $route = null)
    {
        return strpos('resources=', $pattern) === 0;
    }

    /**
     * @param Factory $factory
     * @param mixed $pattern
     * @param Route|null $parentRoute
     * @return Group
     */
    public function resolveGroup(Factory $factory, $pattern, Route $parentRoute = null)
    {
        $group = new Group($factory, $parentRoute);

        // do something with the pattern, and add a routing.

        return $group;
    }
}

Then add the handler this way :

use CollectionHandler;

$app->routingFactory->addGroupHandler(new CollectionHandler());

Usage example :

$app->map['apis']->any('/apis')->group('resources=user');

Execute Handler

You can also design the way the execute call is invoked/handled. Implements Exedra\Contracts\Routing\ExecuteHandler.

The implementation is similar to group handling where you just need to validate the pattern, and but this time, resolve into \Closure or callable.

Then add the handler this way :

$app->routingFactory->addExecuteHandler(new MyExecuteHandler());

Usage example :

$app->map['web']->get('/index')->execute('template=twig');

Routing Handler

Or you can do both using only a single implementation. Create a class that implements Exedra\Contracts\Routing\RoutingHandler.

$app->routingFactory->addRoutingHandler(new MyRoutingHandler());

Note

the $pattern for both group handler or execute handler, is not necessarily a string. It can be anything, and up to you to validate and resolve based on the pattern.