Symfony2: Custom ParamConverter für HTTP-Requests erstellen

Eines der vielen kleinen Goodies die Symfony2 zu bieten hat ist der ParamConverter. Die ParamConverter übersetzen die Parameter beim HTTP-Request nach den gewünschten Vorgaben. So können zum Beispiel Datenmodelle direkt geladen oder Datum-Strings als DateTime-Objekte genutzt werden. Wenn man mit einem Standardsetup arbeitet, sind diese Converter direkt dabei.

Aber auch eigene Converter sind schnell geschrieben und einsatzfähig. Sämtliche Möglichkeiten des ParamConverters stehen in der Dokumentation.

Als Ausgangspunkt haben wir in dem Beispiel eine Action, die mit einer ID aufgerufen wird.

<?php
namespace E7\DemoBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use E7\DemoBundle\Model\Post;

class DefaultController extends Controller {
    /**
     * @Route("/test/{postId}")
     * @ParamConverter()
     * @param   Post $post
     */
    public function testAction(Post $post) {
      // some usefull code
    }
}

Über die Annotation @ParamConverter weiß das System nun, dass der Parameter übersetzt werden soll. Die bereits zu Beginn erwähnten Converter sind bereits registriert. Um nun eine eigene Logik zu verwenden, brauchen wir einen eigenen Übersetzter. Die Klasse muss das Interface ParamConverterInterface implementieren.

Die Schnittstelle ist sehr einfach gehalten und bietet alls was man braucht. Die Methode supports() muss ein TRUE oder FALSE zurückgeben, ob die Klasse die Anfrage übersetzen kann und apply() mach dann den Rest.

<?php
namespace E7\DemoBundle\Request\ParamConverter;

use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

class ModelParamConverter implements ParamConverterInterface {
    function apply(Request $request, ConfigurationInterface $configuration) {
        $name = $configuration->getName();
        $idParam = $name . 'Id';
        $class = $configuration->getClass();

        if (!$request->attributes->has($idParam)) {
            return false;
        }

        $id = $request->attributes->get($idParam);

        $model = loadModelById($id);
        $request->attributes->set($param, $model);

        if (null === $model->getId()) {
            throw new NotFoundHttpException(sprintf('%s object not found.', $class));
        }

        return true;
    }

    function supports(ConfigurationInterface $configuration) {
        return modelClassExists($class);
    }
}

Die Klasse soll schematisch zeigen, wie ein Converter funktionieren könnte. Die beiden Funktionen loadModelById() und modelClassExists() stehen nur als Pseudocode da. Alle verfügbaren Werte können über die Annotation $configuration abgerufen werden. Über $configuration kommen wir an den Namen des Parameter und den TypeHint.

Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter Object
(
    [name:protected] => post
    [class:protected] => E7\DemoBundle\Model\Post
    [options:protected] => Array
        (
        )

    [optional:protected] =>
    [converter:protected] => model
)

Bevor unser Converter überhaupt beachtet wird, müssen wir ihn in der services.yml als Service registrieren.

services:
    request.param_converter:
        class: E7\DemoBundle\Request\ParamConverter\ModelParamConverter
        tags:
            - { name: request.param_converter, converter: model }

Ab jetzt sollte alles zusammenarbeiten und wir können nach belieben Requestparameter umformen. Viel Spaß!

Kommentare sind deaktiviert.

Schlagwörter: Adapter, Amazon, Animation, Annotations, Anonyme Klasse, Ant, Apache, API, Array, ArrayAccess, Attachment, AutoLoader, Bedienung, Bedingung, Benchmark, Bildbearbeitung, BOM, Bootstrap, Bot, Byte Order Mark, Callback, CamelCase, Canvas, Captcha, Cheatsheet, CLI, Closure, Cloud, CodeSniffer, Community, Comparator, Contest, Controller, Converter, CouchDB, Countable, Cronjob, CSV, CustomLibrary, Custom_Model, Data Mapper, Datei, Datenbank, Datenstruktur, Datentypen, Dating, Decorator, Dekorierer, Design Patterns, Dump, Duplikat, each, Eclipse, Entwicklung, Entwurfsmuster, Enum, Erweiterung, Eventhandling, Exception-Handling, Extension, Factory, Fehler, Flash, Foreach, Formatierung, Formular, Funktion, Futon, Header, HTML5, HTTP, IDE, If, Implementierung, InnoDB, Interceptor, Interface, isset, Iterator, Java, JavaScript, jQuery, Konfiguration, Konsole, Kontrollstruktur, kopieren, Late Static Binding, Layout, Linux, Listeners, Logging, Löschen, Magento, Magic Methods, Marketing, Methode, Model, MVC, MySQL, NetBeans, Objekt, Observable, Observer, OOP, Operator, Parameter, Partnersuche, Performance, PHP, phpMyAdmin, PHPUnit, Plugin, Proxy, Qualitätssicherung, Query, Reflection, Request, Response, Rest-API, Rockstar, Routing, S3, Samba, Scheifen, Schleife, Schutz, Secure Shell, Selbstreferenz, Shop, Sicherheit, Sicherung, Singleton Pattern, SOAP, Sortierung, Sourcecode, Spam, Speicherproblem, Spickzettel, SPL, SSH, Statement, Stellvertreter, Strategy Pattern, Stream, String, Sun VirtualBox, Support, Switch, Symfony, Symfony2, Symfony Live, Tag, Template, Template Method, Ternär Operator, Testing, Thumbnail, Tool, Tour, Twig, Type-Cast, Umwandlung, Underscore, unset, Vererbung, Verzweigung, Video, Videospiel, Virtualisierung, Visitor Pattern, Vorschaubild, walk, Webserver, Webservice, Weiterleitung, Wrapper, Youtube, Zeitsteuerung, Zend Framework, Zend_Cloud, Zend_CodeGenerator, Zend_Http_Client, Zend_Service, Zugriffsmethode