21
OkAPI meets Symfony OkAPI meet symfony, symfony meet OkAPI Lukas ([email protected] ) | Jordi ([email protected] ) Symfony Live 2010 - Paris Feburary 15-17 Mittwoch, 17. Februar 2010

OkAPI meet symfony, symfony meet OkAPI

Embed Size (px)

DESCRIPTION

The Okapi framework was initially developed by the Liip AG together for use at local.ch as thin layer mainly handling XSLT transformation and request mapping between the Java backend and the PHP based frontend. It has evolved since then but has stayed true its heritage of being the thinnest possible layer that combines various open source libraries. In this spirit the sfYaml component was integrated in version 1.1 of the framework. Okapi 2 has integrated various additional symfony components to further reduce the amount of code that has to be maintained in house, while at the same time giving Okapi a very modern architecture having adopted the event dispatcher, request handler, service container components. This sessions explains why we choose to integrate these components and how we went about implementing them and more importantly what lessons we learned along the way.

Citation preview

Page 1: OkAPI meet symfony, symfony meet OkAPI

OkAPI meets Symfony

OkAPI meet symfony, symfony meet OkAPI

Lukas ([email protected]) | Jordi ([email protected])Symfony Live 2010 - Paris Feburary 15-17

Mittwoch, 17. Februar 2010

Page 2: OkAPI meet symfony, symfony meet OkAPI

OkAPI meets Symfony

Who are we?We have been doing PHP quite some timeInvolved in PEAR, Doctrine, Dwoo, Phergie, Arbit, core PHP development and a bit of symfony .. and a few other thingsLiip founded 3 years ago, winning awards doing SOTA PHP/Flash apps ever sinceDon’t worry we are happy staying in Switzerland :-)

Mittwoch, 17. Februar 2010

Page 3: OkAPI meet symfony, symfony meet OkAPI

OkAPI meets Symfony

Why OkAPI?Developed internally at Liip, released as OSS, but never tried to grow a communityOriginal code is quite old, written before current crop of frameworks were matureDesigned for fat Java backend, lightweight PHP/XSLT frontend architecturesSlowly turned into a lightweight PHP framework glueing together all sorts of libs

Mittwoch, 17. Februar 2010

Page 4: OkAPI meet symfony, symfony meet OkAPI

OkAPI meets Symfony

What is this about?We are not here to sell OkAPI. It works for us, but its not ready for the world in generalOkAPI2 uses most symfony components (*) and we want to share our experienceSymfony benefits by someone testing the concepts behind all the new shiny code

(*) OkAPI even uses a “non” component “ripped” from symfony, but currently we are not using the Templating component

Mittwoch, 17. Februar 2010

Page 5: OkAPI meet symfony, symfony meet OkAPI

OkAPI meets Symfony

YamlFirst component we added as a replacement for spyc into OkAPI 1.1Faster, much better error reporting, but missing a key feature: merge keySo we submitted patches, Fabien rewrote them, but we now have merge key :-)

Mittwoch, 17. Februar 2010

Page 6: OkAPI meet symfony, symfony meet OkAPI

OkAPI meets Symfony

Merge-key rocks!parameters: # declare &arguments as a source arguments: &arguments routing: @routing request: @request response: @response params: &params debug: trueservices: api_command_hello: class: api_command_hello # merge default parameters and change on the fly arguments: <<: *arguments routing: @overrides_work extra: "extra values are also allowed" shared: true

Mittwoch, 17. Februar 2010

Page 7: OkAPI meet symfony, symfony meet OkAPI

OkAPI meets Symfony

Step out, get burnedSomeone did a OkAPI branch with dependency injection supportWe decided it would be better to reduce the LOC to maintain/document ourselvesAfter a quick prototype integrating the Service Container we were happyFabien announced the jump to 5.3, great idea, but we still wanted pre 5.3 supportSo we are back to maintaining the code :-/

Mittwoch, 17. Februar 2010

Page 8: OkAPI meet symfony, symfony meet OkAPI

OkAPI meets Symfony

Service ContainerA “service” layer to assist in implementing dependency injectionServices and their dependencies can be configured via Yaml (or XML) config filesService Container generates a PHP class that can make instances of any of the servicesBig question: How does the controller get access to the services?

Mittwoch, 17. Februar 2010

Page 9: OkAPI meet symfony, symfony meet OkAPI

OkAPI meets Symfony

General commentsObject creation needs to be cheap, lazy load resources as much as possibleGet rid of the idea of a “flat config file”, instead pass everything to the constructorUse parameters to reuse settings across multiple servicesUse import to structure configsDo not pass around the SC, if necessary use multiple SC’s

Mittwoch, 17. Februar 2010

Page 10: OkAPI meet symfony, symfony meet OkAPI

OkAPI meets Symfony

DI Frontcontroller<?php

// load the init routinerequire_once dirname(__FILE__).'/../inc/api/init.php';$sc = api_init::createServiceContainer();

// load the controller$ctrl = $sc->controller;$ctrl->setServiceContainer($sc);

// let the controller load the modules// which in turn load the model and view$ctrl->run()->send();

Mittwoch, 17. Februar 2010

Page 11: OkAPI meet symfony, symfony meet OkAPI

OkAPI meets Symfony

Command (“action”)abstract class api_command { public function __construct($routing, $request, $response, $params) { $this->routing = $routing; $this->route = $routing->getRoute(); $this->request = $request; $this->response = $response; $this->params = $params; $this->response->command = $this; $this->response->getDataCallback = array($this, 'getData'); $this->command = api_helpers_class::getBaseName($this); } public function process() { $route = $this->route->getParams(); $method = isset($route['method']) ? $method = 'execute'.ucfirst($route['method']) : null;

if (empty($method) || !is_callable(array($this, $method)) ) { throw new api_exception('Incorrect method name’); }

$this->$method(); return $this->response;

Mittwoch, 17. Februar 2010

Page 12: OkAPI meet symfony, symfony meet OkAPI

OkAPI meets Symfony

Development Configimports: - { resource: default.yml, class: sfServiceContainerLoaderFileYaml }parameters: outputCaching: false debug: trueservices: writer: class: Zend_Log_Writer_apiFirebug arguments: [] shared: true logger: class: Zend_Log arguments: [@writer] shared: true log: class: api_log arguments: [@logger, DEBUG, true] shared: true solrClientSearch: class: api_solrClient arguments: options: hostname: localhost port: 8983 path: %solrPathSearch%# optional dependencies not yet supported in pre 5.3 log: @log shared: true

Mittwoch, 17. Februar 2010

Page 13: OkAPI meet symfony, symfony meet OkAPI

OkAPI meets Symfony

100 LOC class using the Event componentFires request, controller, view events to structure your request handlingFeatured in some of Fabien’s slide sets, it has not yet been officially releasedObviously Event component can also be used inside filters and commands to handle custom events

Request Handler

Mittwoch, 17. Februar 2010

Page 14: OkAPI meet symfony, symfony meet OkAPI

OkAPI meets Symfony

Filters using Eventservices: filter_language: class: api_filter_language arguments: [@request, @response] shared: true controller: class: api_controller arguments: # [...] events: application.request: controller: service: controller method: request language: service: @filter_language method: request

Mittwoch, 17. Februar 2010

Page 15: OkAPI meet symfony, symfony meet OkAPI

OkAPI meets Symfony

Example filterclass api_filter_language { public function __construct($request, $response) { $this->request = $request; $this->response = $response; }

public function request(sfEvent $event) { if ($this->request->getLangDefaultUsed() || $this->request->getParam('lang') ) { $url = $this->request->getUrl(); $host = $this->request->getHost(); $languages = $this->request->getLanguages(); // [...] $this->response->setCookie('lang', $lang, $_SERVER ['REQUEST_TIME'] + 86400*365*5, '/'); // [...] $this->response->redirect($url); } return true; }}

Mittwoch, 17. Februar 2010

Page 16: OkAPI meet symfony, symfony meet OkAPI

OkAPI meets Symfony

RoutingOur own routing component didn't have route generationIntegrating sfRouting took a couple hoursMore features, less maintenance, some docsWrapping it means our route definition didn't change much

Mittwoch, 17. Februar 2010

Page 17: OkAPI meet symfony, symfony meet OkAPI

OkAPI meets Symfony

Routing// before$m->route('/api/chk/*url')->config( array( 'command'=>'liipto', 'method' => 'checkCode', 'view' => array('class' => 'json') ));

// after$routing->route('chk', '/api/chk/:url', array( 'command'=>'liipto', 'method' => 'checkCode', 'view' => array('class' => 'json') ));

Mittwoch, 17. Februar 2010

Page 18: OkAPI meet symfony, symfony meet OkAPI

OkAPI meets Symfony

Classes loadedExample command:api_command_hello

OkAPI classes:api_commandapi_controllerapi_helpers_classapi_helpers_stringapi_initapi_requestapi_responseapi_routingapi_routing_routeapi_routingcontainerapi_views_commonapi_views_php

Symfony classes:sfEventDispatchersfPatternRoutingsfRequestHandlersfRoutesfRoutingsfServiceContainersfServiceContainerBuildersfServiceContainerDumpersfServiceContainerDumperInterfacesfServiceContainerDumperPhpsfServiceContainerInterfacesfServiceContainerLoadersfServiceContainerLoaderFilesfServiceContainerLoaderFileYamlsfServiceContainerLoaderInterfacesfServiceDefinitionsfServiceReferencesfYaml

Mittwoch, 17. Februar 2010

Page 19: OkAPI meet symfony, symfony meet OkAPI

OkAPI meets Symfony

Merci! Questions?Thank you for listening.

Lukas ([email protected]) | Jordi ([email protected])

http://joind.in/talk/view/1410

Mittwoch, 17. Februar 2010

Page 20: OkAPI meet symfony, symfony meet OkAPI

OkAPI meets Symfony

While you are listeningStructured database of UN resolutions:http://code.google.com/p/uninformed/

Google map app for DJ’s around the world:http://code.google.com/p/djtt/wiki/worldmap

Dwoo (at least as good as Twig):http://dwoo.org/

PHP Issue tracker with Continuous Integration:http://arbitracker.org

Mittwoch, 17. Februar 2010

Page 21: OkAPI meet symfony, symfony meet OkAPI

OkAPI meets Symfony

Resourceshttp://okapi.liip.ch/http://svn.liip.ch/repos/public/okapi2/http://components.symfony-project.org/

Mittwoch, 17. Februar 2010