Skip to content

Latest commit

 

History

History
161 lines (122 loc) · 4.83 KB

index.md

File metadata and controls

161 lines (122 loc) · 4.83 KB

Documentation

This extension is here to provide an easy way to have objects in application request and consequently in parameters of presenters and components.

Installation

The best way to install Arachne/EntityLoader is using Composer.

$ composer require arachne/entity-loader arachne/event-dispatcher

Now you need to register the necessary extensions using your neon config file.

extensions:
    - Oops\CacheFactory\DI\CacheFactoryExtension
    - Arachne\EventDispatcher\DI\EventDispatcherExtension
    - Arachne\EntityLoader\DI\EntityLoaderExtension

Alternatively you can use kdyby/events instead of arachne/event-dispatcher.

Add the Arachne\EntityLoader\Application\EntityLoaderPresenterTrait to your BasePresenter. It overrides the storeRequest & restoreRequest methods to make them work with object parameters.

abstract class BasePresenter extends \Nette\Application\UI\Presenter
{
    use \Arachne\EntityLoader\Application\EntityLoaderPresenterTrait;
}

Finally you will need to change your routing a little. Instead of Nette\Application\Routers\Route use Arachne\EntityLoader\Routing\Route. Also you'll need to wrap your router using Arachne\EntityLoader\Routing\RouterWrapper (beware that it has a dependency on Arachne\EntityLoader\Application\RequestEntityUnloader). Below is an example what your RouterFactory could look like:

<?php

namespace App\Routing;

use Arachne\EntityLoader\Application\RequestEntityUnloader;
use Arachne\EntityLoader\Routing\Route;
use Arachne\EntityLoader\Routing\RouterWrapper;
use Nette\Application\IRouter;
use Nette\Application\Routers\RouteList;

/**
 * Router factory.
 */
class RouterFactory
{
    /**
     * @var RequestEntityUnloader
     */
    private $entityUnloader;

    public function __construct(RequestEntityUnloader $entityUnloader)
    {
        $this->entityUnloader = $entityUnloader;
    }

    /**
     * @return IRouter
     */
    public function create()
    {
        $router = new RouteList();

        $router[] = new Route('<presenter>/<action>[/<entity>]');

        return new RouterWrapper($router, $this->entityUnloader);
    }
}

Doctrine

For usage with Doctrine ORM entities use the Arachne/Doctrine package to your application.

Custom filters

To use objects of a certain class as parameters you will need a two services. One implementing Arachne\EntityLoader\FilterInInterface with arachne.entityLoader.filterIn tag and one implementing Arachne\EntityLoader\FilterOutInterface with arachne.entityLoader.filterOut tag. For both services pass the classes handled by these services as the tag attribute.

services:
    dateTimeFilterIn:
        class: DateTimeFilterIn
        tags:
            arachne.entityLoader.filterIn: DateTime
    dateTimeFilterOut:
        class: DateTimeFilterOut
        tags:
            arachne.entityLoader.filterOut: DateTime
class DateTimeFilterIn implements \Arachne\EntityLoader\FilterInInterface
{
    public function filterIn($value)
    {
        if (is_numeric($value)) { // timestamp
            return new \DateTime(date('Y-m-d H:i:s', $value));
        } else { // textual
            return new \DateTime($value);
        }
    }
}

class DateTimeFilterOut implements \Arachne\EntityLoader\FilterInInterface
{
    public function filterOut($entity)
    {
        // $entity instanceof DateTime
        return $entity->getTimestamp();
    }
}

You could argue that filterIn method should only handle timestamps and not other formats because filterOut always returns a timestamp. The point is that filterOut should always return an identifier from which the object can be recreated. Regardless how you wish to represent the parameter in the URL. You can change the URL representation in router (see the example below).

Presenter

Finally we can use DateTime parameters in presenter:

class FooPresenter extends \Nette\Application\UI\Presenter
{
    public function renderDefault(DateTime $date)
    {
        $this->template->date = $date;
    }
}

Persistent parameters are also supported. Use the @var annotation to specify the class.

Routers

Now what if we want to use different format than timestamp in URL? For example imagine that you don't need the time part in one case when you use a DateTime parameter and want to reptesent the date simply as 'Y-m-d' in the URL. This is supported and it can even be specific to the route in question. The solution uses filter out option and envelope object (EntityLoader creates them by default):

$router[] = new Route('/<date>', [
    'presenter' => 'Foo',
    'date' => [
        Route::FILTER_OUT => function (\Arachne\EntityLoader\Application\Envelope $value) {
            return $value->getEntity()->format('Y-m-d');
        },
    ],
]);