Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PHP Interoperability with PPI Framework

PHP Interoperability with PPI Framework

Vítor Brandão

August 23, 2015
Tweet

More Decks by Vítor Brandão

Other Decks in Programming

Transcript

  1. PAUL DRAGOONIS PAUL DRAGOONIS Lead developer of PPI Software Consultant

    from Scotland Using PHP since 2001 PHP community guy, internals, and @dr4goonis php.net PHP- FIG VÍTOR BRANDÃO VÍTOR BRANDÃO PPI co-lead dev Born in ☼ Portugal, currently in ☂ England bundles, , 2PHP ports QA at @noiselabs NoiseLabs Consulting Ltd Sf2 ZF2 Python Gentoo Linux
  2. OUR MESSAGE OUR MESSAGE Frameworks are very powerful! but.. they

    come at a cost How you use them and depend on them. That's what's important
  3. TODAY TODAY Showing you how to unleash the power of

    not just 1 framework, but many! How that bene ts you, your team and your project
  4. POWER COMES AT A COST POWER COMES AT A COST

    WHAT IS THE COST? WHAT IS THE COST? Vendor lock-in! (technical debt) This means: Limited technology stack Limited team experience Limited POWER!!!
  5. COMMON PATH OF STARTING A PROJECT COMMON PATH OF STARTING

    A PROJECT Step 1: customer tells you what they want (kind of) Step 2: you choose a framework/toolkit that suits that project Step 3: you build it
  6. WHAT HAPPENS NEXT? WHAT HAPPENS NEXT? Step 4: customer changes

    their mind on what they want Step 5: the tool you chose in the beginning, is no longer the most relevant one Step 6: you can't switch because you're locked into that vendor Step 7: you stick with the tool because it's too di cult to switch to the correct tool
  7. CAN'T SWITCH? WHY? CAN'T SWITCH? WHY? Existing frameworks force a

    1-to-1 relationship between your app and the framework vendor. You are tightly coupled to the framework that your app was built on. You can't move your code between your Symfony apps and Laravel apps
  8. IT'S NOT YOUR FAULT! IT'S NOT YOUR FAULT! You're not

    psychic! You cannot predict the future but, you can prepare for it :-) PPI will help you with this
  9. IT DOESN'T HAVE TO BE THIS WAY IT DOESN'T HAVE

    TO BE THIS WAY PPI prepares you for change. It's DESIGNED for change. Why? Your app code belongs to you, not to your framework. You're in charge!
  10. P.P.I.? P.P.I.? Hmm... what does PPI stand for? Not much,

    but let's try! PHP Phramework Interoperability
  11. WHAT IS PPI? WHAT IS PPI? It's not a framework

    but, you can use it like a framework Really, it's a framework delivery engine It delivers core parts of frameworks to your app Individually, to the modules of your app
  12. WHAT YOU CAN USE PPI AS? WHAT YOU CAN USE

    PPI AS? An engine that you can boot() up. This engine can be called as middleware, or booted, from inside existing apps i.e: Wordpress, Drupal, Legacy App A command line app A full-stack framework to dispatch() HTTP requests
  13. OBJECT MEDIATION OBJECT MEDIATION NO ABSTRACTION! :-) NO ABSTRACTION! :-)

    No added abstraction on top of existing framework.
  14. WHAT'S INSIDE THE PPI ENGINE? WHAT'S INSIDE THE PPI ENGINE?

    composer.json: "require": { "psr/log": "~1.0", "symfony/class-loader": "~2.7", "symfony/dependency-injection": "~2.7", "symfony/config": "~2.7", "symfony/console": "~2.7", "symfony/debug": "~2.7", "symfony/finder": "~2.7", "symfony/yaml": "~2.7", "zendframework/zend-eventmanager": "~2.3", "zendframework/zend-modulemanager": "~2.3", "zendframework/zend-servicemanager": "~2.3", "zendframework/zend-loader": "~2.3", "symfony/templating": "~2.7", "symfony/framework-bundle": "~2.7", "psr/http-message": "^0.11", "symfony/http-foundation": "~2.7", "symfony/http-kernel": "~2.7", "symfony/routing": "~2.7", "symfony-cmf/routing": "1.3.0" }
  15. PPI IS MODULAR BY DESIGN PPI IS MODULAR BY DESIGN

    You only need to add what you need composer.json "ppi/smarty-module": "~1.0", "ppi/twig-module": "~1.0", "ppi/mustache-module": "~1.0" "ppi/laravel-routing": "~1.0" "ppi/aura-routing": "~1.0" "ppi/symfony-routing": "~1.0" "ppi/datasource-module": "~1.0", // LaravelDB, Eloquent, Doctrine ..etc "ppi/cache-module": "~1.0"
  16. PSR'S PSR'S Spearhead PHP-FIG concepts and ideas with a real-life

    usage for these standards. We built our own interop layers rst, then backport them to PHP-FIG. A friendly environment for swappable 3rd-party components.
  17. PPI IS A PSR-AWARE FRAMEWORK PPI IS A PSR-AWARE FRAMEWORK

    You can easily add more libraries into the mix when they implement a PSR. When consuming frameworks like (ZF2, SF2, Aura2) - that don't support PSR-X yet - PPI bridges the gap for you.
  18. PSR-7: REQUEST INTERFACE PSR-7: REQUEST INTERFACE composer.json: "require": { "psr/http-message":

    "~1.0" } PPI/Framework/Http/Request.php use Psr\Http\Message\RequestInterface; use Symfony\Component\HttpFoundation\Request as SymfonyHttpRequest; /** * HTTP messages consist of requests from a client to a server and * responses from a server to a client. This interface defines the * methods common to each. */ class Request extends SymfonyHttpRequest implements RequestInterface { public function withBody(StreamInterface $body) { $new = clone $this; $new->stream = $body; return $new; } }
  19. PSR-7: REQUEST INTERFACE IN PSR-7: REQUEST INTERFACE IN CONTROLLERS CONTROLLERS

    composer.json: <?php namespace Application\Controller; use PPI\Framework\Module\Controller as BaseController; use Psr\Http\Message\RequestInterface; class Mycontroller extends BaseController { public function indexAction(RequestInterface $request) { if ('POST' === $request->getMethod()) { // do POST stuff } } }
  20. PSR-6: CACHING INTERFACE PSR-6: CACHING INTERFACE In production for over

    2 years now. namespace PPI\CacheModule\Cache\Driver; use PPI\CacheModule\Cache\CacheItem; use PPI\CacheModule\Cache\CacheInterface; class RedisCache implements CacheInterface { // ... } Drivers: APC, Disk, Memcached, Memory, Xcache.
  21. CONTAINER INTERFACE CONTAINER INTERFACE namespace PPI\Framework\ServiceManager; use Symfony\Component\DependencyInjection\ContainerInterface; use Zend\ServiceManager\ServiceManager

    as BaseServiceManager; /** * ServiceManager implements the Service Locator design pattern. * * The Service Locator is a service/object locator, tasked with retrieving other * objects. We borrow this one from Zend Framework 2. */ class ServiceManager extends BaseServiceManager implements ContainerInterface { /** * Register a service with the locator. */ public function set($name, $service, $shared = true) { return $this->setService($name, $service, $shared); } }
  22. ROUTER INTERFACE? ROUTER INTERFACE? In PPP 2.1, using a Chained

    Router Will push a interface in upcoming releases
  23. PPI ROUTER PPI ROUTER We made a routing interoperability layer

    (Routing PSR?). Mediate routing and request information from PPI to Aura (for example). If a Routing PSR is created, we get to throw away a lot of code
  24. INSTALLATION INSTALLATION 21st century. Use composer: Step 1: $ composer

    create-project -sdev --no-interaction \ ppi/skeleton-app /var/www/skeleton and for your convenience: Step 2 $ vagrant up ppi-lamp and now...
  25. APP CONFIGURATION APP CONFIGURATION app/ ├── FrameworkRequirements.php ├── check ├──

    config │ ├── base │ │ ├── app.php │ │ ├── app.yml │ │ ├── datasource.php │ │ └── datasource.yml │ ├── dev │ │ ├── app.php │ │ └── app.yml │ └── prod │ ├── app.php │ └── app.yml ├── console ├── init.php └── views ├── base.html.php ├── base.html.smarty └── base.html.twig
  26. ZF-LIKE CONFIGURATION ZF-LIKE CONFIGURATION app.php <?php $config = []; $config['framework']

    = [ 'templating' => ['engines' => ['php', 'smarty', 'twig')] , 'skeleton_module' => ['path' => './utils/skeleton_module'] ]; $config['datasource'] => [ 'connections' = require __DIR__ . '/datasource.php' ]; $config['modules'] = require __DIR__ . 'modules.php'; return $config;
  27. SYMFONY-LIKE YAML SYMFONY-LIKE YAML app.yml imports: - { resource: datasource.yml

    } - { resource: modules.yml } framework: templating: engines: ["php", "smarty", "twig"] skeleton_module: path: "./utils/skeleton_module" monolog: handlers: main: type: stream path: %app.logs_dir%/%app.environment%.log level: debug
  28. FRONT CONTROLLER FRONT CONTROLLER public/index.php <?php require_once 'app/init.php'; // Set

    the environment $env = getenv('PPI_ENV') ?: 'dev'; $debug = getenv('PPI_DEBUG') !== '0' && $env !== 'prod'; // Create and configure the Application $app = new PPI\Framework\App(array( 'environment' => $env, 'debug' => $debug, 'rootDir' => realpath(__DIR__.'/../app') )); $app->loadConfig($app->getEnvironment().'/app.php'); // Just Boot, no HTTP $app->boot() // OR: Handle requests $app->run();
  29. MODULE STRUCTURE MODULE STRUCTURE MyModule | ├── Module.php ├── resources

    │ ├── config │ │ └── config.yml │ ├── routes │ │ ├── aura.php │ │ └── symfony.yml │ │ └── laravel.php │ └── views │ └── index │ ├── index.html.mustache │ ├── index.html.php │ ├── index.html.smarty │ └── index.html.twig └── src ├── Services │ └── DomainClass.php ├── Controller │ ├── Index.php
  30. ROUTING DEFINED PER MODULE ROUTING DEFINED PER MODULE class Module

    extends AbstractModule implements ModuleInterface { public function getRoutes() { return $this->loadAuraRoutes(__DIR__ . '/resources/routes/aura.php'); return $this->loadSymfonyRoutes(__DIR__ . '/resources/routes/symfony.yml'); return $this->loadLaravelRoutes(__DIR__ . '/resources/routes/laravel.php'); } }
  31. PROGRESS PROGRESS PPI is ready for you to build projects

    in. Release 2.1 is in alpha now and your feedback is welcome.
  32. PPI HELPS YOUR PROJECT & YOUR TEAMS PPI HELPS YOUR

    PROJECT & YOUR TEAMS You no longer need a narrow skillset, but nd good developers You become exposed to new frameworks and new toolsets You are exible and not bound to one single stack You take your code from project to project with ease .. so much more ..
  33. | Northeast PHP 2015 @ppi_framework Please Rate Our Talk! Documentation:

    Gitter: Twitter: Email: or IRC: https://joind.in/15049 http://docs.ppi.io gitter.im/ppi/framework @ppi_framework [email protected] [email protected] #ppi at freenode