Slide 1

Slide 1 text

THE PHP INTEROPERABILITY THE PHP INTEROPERABILITY FRAMEWORK FRAMEWORK

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

FRAMEWORK POWER! FRAMEWORK POWER! Power is de ned by: Speed Flexibility Eco-system

Slide 6

Slide 6 text

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!!!

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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!

Slide 12

Slide 12 text

P.P.I.? P.P.I.? Hmm... what does PPI stand for? Not much, but let's try! PHP Phramework Interoperability

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

USING FRAMEWORKS DIRECTLY USING FRAMEWORKS DIRECTLY

Slide 16

Slide 16 text

USING FRAMEWORKS IN PPI USING FRAMEWORKS IN PPI

Slide 17

Slide 17 text

USING FRAMEWORKS IN PPI USING FRAMEWORKS IN PPI

Slide 18

Slide 18 text

OBJECT MEDIATION OBJECT MEDIATION NO ABSTRACTION! :-) NO ABSTRACTION! :-) No added abstraction on top of existing framework.

Slide 19

Slide 19 text

TECHNICAL PART BEGINS :-) TECHNICAL PART BEGINS :-)

Slide 20

Slide 20 text

POWERED BY SOLID COMPONENTS POWERED BY SOLID COMPONENTS

Slide 21

Slide 21 text

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" }

Slide 22

Slide 22 text

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"

Slide 23

Slide 23 text

PPI MODULE WITH ROUTERS PPI MODULE WITH ROUTERS

Slide 24

Slide 24 text

PPI MODULE WITH TEMPLATING ENGINES PPI MODULE WITH TEMPLATING ENGINES

Slide 25

Slide 25 text

MODULE1 REST API MODULE MODULE1 REST API MODULE

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

MODULE2 MVC FULL STACK APP MODULE2 MVC FULL STACK APP

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

MODULE3 MVC FULL STACK APP MODULE3 MVC FULL STACK APP

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

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.

Slide 32

Slide 32 text

PSR - WHAT'S IN // WHAT'S COMING? PSR - WHAT'S IN // WHAT'S COMING?

Slide 33

Slide 33 text

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.

Slide 34

Slide 34 text

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; } }

Slide 35

Slide 35 text

PSR-7: REQUEST INTERFACE IN PSR-7: REQUEST INTERFACE IN CONTROLLERS CONTROLLERS composer.json: getMethod()) { // do POST stuff } } }

Slide 36

Slide 36 text

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.

Slide 37

Slide 37 text

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); } }

Slide 38

Slide 38 text

ROUTER INTERFACE? ROUTER INTERFACE? In PPP 2.1, using a Chained Router Will push a interface in upcoming releases

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

PRACTICAL EXAMPLES PRACTICAL EXAMPLES USING PPI USING PPI

Slide 42

Slide 42 text

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...

Slide 43

Slide 43 text

SKELETON APP SKELETON APP

Slide 44

Slide 44 text

$ APP/CONSOLE $ APP/CONSOLE

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

ZF-LIKE CONFIGURATION ZF-LIKE CONFIGURATION app.php ['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;

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

FRONT CONTROLLER FRONT CONTROLLER public/index.php $env, 'debug' => $debug, 'rootDir' => realpath(__DIR__.'/../app') )); $app->loadConfig($app->getEnvironment().'/app.php'); // Just Boot, no HTTP $app->boot() // OR: Handle requests $app->run();

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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'); } }

Slide 51

Slide 51 text

PROGRESS PROGRESS PPI is ready for you to build projects in. Release 2.1 is in alpha now and your feedback is welcome.

Slide 52

Slide 52 text

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 ..

Slide 53

Slide 53 text

RECAP RECAP PPI prepares you for change. It's DESIGNED for change.

Slide 54

Slide 54 text

No content

Slide 55

Slide 55 text

No content

Slide 56

Slide 56 text

https://joind.in/15049 THANK YOU BOSTON. THANK YOU BOSTON. Questions?

Slide 57

Slide 57 text

| 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