SlideShare une entreprise Scribd logo
1  sur  105
Télécharger pour lire hors ligne
Dependency Injection
with PHP and PHP 5.3

Fabien Potencier
Fabien Potencier
•  Serial entrepreneur and developer by passion
•  Founder of Sensio (in 1998)
   –  A services and consulting company
      specialized in Web technologies
      and Internet marketing (France and USA)
   –  70 people
   –  Open-Source specialists
   –  Big corporate customers
   –  Consulting, training, development, web design, … and more
   –  Sponsor of a lot of Open-Source projects
      like symfony and Doctrine
Fabien Potencier
•  Creator and lead developer of symfony…
•  and creator and lead developer of some more OSS:
   –  symfony components
   –  Swift Mailer : Powerful component based mailing library for PHP
   –  Twig : Fexible, fast, and secure template language for PHP
   –  Pirum : Simple PEAR Channel Server Manager
   –  Sismo : PHP continuous integration server
   –  Lime : Easy to use unit testing library for PHP
   –  Twitto : A web framework in a tweet
   –  Twittee : A Dependency Injection Container in a tweet
   –  Pimple : A small PHP 5.3 dependency injection container
Fabien Potencier

•  Read my technical blog: http://fabien.potencier.org/

•  Follow me on Twitter: @fabpot

•  Fork my code on Github: http://github.com/fabpot/
Dependency Injection

A real world « web » example
In most web applications, you need to manage the user preferences

   –  The user language
   –  Whether the user is authenticated or not
   –  The user credentials
   –  …
This can be done with a User object

   –  setLanguage(), getLanguage()
   –  setAuthenticated(), isAuthenticated()
   –  addCredential(), hasCredential()
   –  ...
The User information
         need to be persisted
        between HTTP requests

We use the PHP session for the Storage
class SessionStorage
{
  function __construct($cookieName = 'PHP_SESS_ID')
  {
    session_name($cookieName);
    session_start();
  }

    function set($key, $value)
    {
      $_SESSION[$key] = $value;
    }

    // ...
}
class User
{
  protected $storage;

    function __construct()                      Very hard to
    {                                            customize
      $this->storage = new SessionStorage();
    }

    function setLanguage($language)
    {
      $this->storage->set('language', $language);
    }

    // ...
}                           Very easy
                              to use
$user = new User();
class User
{
  protected $storage;                  Very easy to
                                        customize
    function __construct($storage)
    {
      $this->storage = $storage;
    }
}

$storage = new SessionStorage();
$user = new User($storage);
                                     Slightly more
                                     difficult to use
That’s Dependency Injection

      Nothing more
Let’s understand why the first example
is not a good idea
I want to change the session cookie name
class User
{
  protected $storage;

    function __construct()
                                                    Hardcode it in the
    {                                                   User class
      $this->storage = new SessionStorage('SESSION_ID');
    }

    function setLanguage($language)
    {
      $this->storage->set('language', $language);
    }

    // ...
}

$user = new User();
class User
{
  protected $storage;

    function __construct()
    {
        $this->storage = new SessionStorage(STORAGE_SESSION_NAME);
    }
}
                                                              Add a global
                                                             configuration?
define('STORAGE_SESSION_NAME', 'SESSION_ID');

$user = new User();
class User
{
  protected $storage;

    function __construct($sessionName)
    {
      $this->storage = new SessionStorage($sessionName);
    }
}

$user = new User('SESSION_ID');
                                         Configure via
                                             User?
class User
{
  protected $storage;

  function __construct($storageOptions)
  {
    $this->storage = new SessionStorage($storageOptions
['session_name']);

$user = new User(
   array('session_name' => 'SESSION_ID')
);
                                      Configure with an
                                            array?
I want to change the session storage implementation

                   Filesystem
                     MySQL
                   Memcached
                       …
class User
{
  protected $storage;

    function __construct()                             Use a global
    {                                                 registry object?
      $this->storage = Registry::get('session_storage');
    }
}

$storage = new SessionStorage();
Registry::set('session_storage', $storage);
$user = new User();
Now, the User depends on the Registry
Instead of harcoding
    the Storage dependency
inside the User class constructor

Inject the Storage dependency
       in the User object
class User
{
  protected $storage;

    function __construct($storage)
    {
      $this->storage = $storage;
    }
}

$storage = new SessionStorage('SESSION_ID');
$user = new User($storage);
What are the advantages?
Use different Storage strategies
class User
{
  protected $storage;

    function __construct($storage)
    {
      $this->storage = $storage;
    }
}                                                   Use a different
                                                    Storage engine
$storage = new MySQLSessionStorage('SESSION_ID');
$user = new User($storage);
Configuration becomes natural
class User
{
  protected $storage;

    function __construct($storage)
    {
      $this->storage = $storage;
    }
}                                                   Configuration
                                                      is natural
$storage = new MySQLSessionStorage('SESSION_ID');
$user = new User($storage);
Wrap third-party classes (Interface / Adapter)
class User
{
  protected $storage;
                                                      Add an interface
    function __construct(SessionStorageInterface $storage)
    {
      $this->storage = $storage;
    }
}

interface SessionStorageInterface
{
  function get($key);

    function set($key, $value);
}
Mock the Storage object (for testing)
class User
{
  protected $storage;

    function __construct(SessionStorageInterface $storage)
    {
      $this->storage = $storage;
    }
}
                                                      Mock the Session
class SessionStorageForTests implements SessionStorageInterface
{
  protected $data = array();

    static function set($key, $value)
    {
      self::$data[$key] = $value;
    }
}
Use different Storage strategies
       Configuration becomes natural
Wrap third-party classes (Interface / Adapter)
    Mock the Storage object (for testing)


Easy without changing the User class
« Dependency Injection is where
   components are given their dependencies
    through their constructors, methods, or
             directly into fields. »
http://www.picocontainer.org/injection.html
$storage = new SessionStorage();

// constructor injection
$user = new User($storage);

// setter injection
$user = new User();
$user->setStorage($storage);

// property injection
$user = new User();
$user->storage = $storage;
A slightly more complex
web example
$request = new Request();
$response = new Response();

$storage = new FileSessionStorage('SESSION_ID');
$user = new User($storage);

$cache = new FileCache(
   array('dir' => dirname(__FILE__).'/cache')
);
$routing = new Routing($cache);
class Application
{
  function __construct()
  {
    $this->request = new WebRequest();
    $this->response = new WebResponse();

        $storage = new FileSessionStorage('SESSION_ID');
        $this->user = new User($storage);

        $cache = new FileCache(
           array('dir' => dirname(__FILE__).'/cache')
        );
        $this->routing = new Routing($cache);
    }
}

$application = new Application();
Back to square 1
class Application
{
  function __construct()
  {
    $this->request = new WebRequest();
    $this->response = new WebResponse();

        $storage = new FileSessionStorage('SESSION_ID');
        $this->user = new User($storage);

        $cache = new FileCache(
           array('dir' => dirname(__FILE__).'/cache')
        );
        $this->routing = new Routing($cache);
    }
}

$application = new Application();
We need a Container
     Describes objects
  and their dependencies

 Instantiates and configures
     objects on-demand
A container
SHOULD be able to manage
  any PHP object (POPO)


The objects MUST not know
  that they are managed
      by a container
•  Parameters
   –  The SessionStorageInterface implementation we want to use (the class name)
   –  The session name
•  Objects
   –  SessionStorage
   –  User
•  Dependencies
   –  User depends on a SessionStorageInterface implementation
Let’s build a simple container with PHP 5.3
DI Container

Managing parameters
class Container
{
  protected $parameters = array();

    public function setParameter($key, $value)
    {
      $this->parameters[$key] = $value;
    }

    public function getParameter($key)
    {
      return $this->parameters[$key];
    }
}
Decoupling


$container = new Container();                             Customization
$container->setParameter('session_name', 'SESSION_ID');
$container->setParameter('storage_class', 'SessionStorage');




$class = $container->getParameter('storage_class');
$sessionStorage = new $class($container->getParameter('session_name'));
$user = new User($sessionStorage);
                                                        Objects creation
class Container                            Using PHP
{                                         magic methods
  protected $parameters = array();

    public function __set($key, $value)
    {
      $this->parameters[$key] = $value;
    }

    public function __get($key)
    {
      return $this->parameters[$key];
    }
}
Interface
                                                          is cleaner


$container = new Container();
$container->session_name = 'SESSION_ID';
$container->storage_class = 'SessionStorage';

$sessionStorage = new $container->storage_class($container->session_name);
$user = new User($sessionStorage);
DI Container

Managing objects
We need a way to describe how to create objects,
    without actually instantiating anything!

      Anonymous functions to the rescue!
Anonymous Functions / Lambdas


               A lambda is a function
                   defined on the fly
                    with no name

function () { echo 'Hello world!'; };
Anonymous Functions / Lambdas

                A lambda can be stored
                      in a variable

$hello = function () { echo 'Hello world!'; };
Anonymous Functions / Lambdas

                And then it can be used
                as any other PHP callable

$hello();


call_user_func($hello);
Anonymous Functions / Lambdas

                    You can also pass a lambda
               as an argument to a function or method

function foo(Closure $func)
{
  $func();
}

foo($hello);
Fonctions anonymes
$hello = function ($name) { echo 'Hello '.$name; };

$hello('Fabien');

call_user_func($hello, 'Fabien');

function foo(Closure $func, $name)
{
  $func($name);
}

foo($hello, 'Fabien');
DI Container

Managing objects
class Container
{
  protected $parameters = array();
  protected $objects = array();

    public function __set($key, $value)
    {
      $this->parameters[$key] = $value;
    }

    public function __get($key)                           Store a lambda
    {
      return $this->parameters[$key];                    able to create the
                                                         object on-demand
    }

    public function setService($key, Closure $service)
    {
      $this->objects[$key] = $service;
    }

    public function getService($key)            Ask the closure to create
    {
      return $this->objects[$key]($this);        th e object and pass the
}
    }                                                current Container
$container = new Container();
$container->session_name = 'SESSION_ID';               Description
$container->storage_class = 'SessionStorage';
$container->setService('user', function ($c)
{
  return new User($c->getService('storage'));
});
$container->setService('storage', function ($c)
{
  return new $c->storage_class($c->session_name);
});


                                              Creating the User
                                          is now as easy as before
$user = $container->getService('user');
class Container
{
  protected $values = array();               Simplify the code
    function __set($id, $value)
    {
      $this->values[$id] = $value;
    }

    function __get($id)
    {
      if (is_callable($this->values[$id]))
      {
        return $this->values[$id]($this);
      }
      else
      {
        return $this->values[$id];
      }
    }
}
$container = new Container();
                                            Unified interface
$container->session_name = 'SESSION_ID';
$container->storage_class = 'SessionStorage';
$container->user = function ($c)
{
   return new User($c->storage);
};
$container->storage = function ($c)
{
   return new $c->storage_class($c->session_name);
};




$user = $container->user;
DI Container

Scope
For some objects, like the user,
   the container must always
    return the same instance
spl_object_hash($container->user)



            !==
spl_object_hash($container->user)
$container->user = function ($c)
{
  static $user;

  if (is_null($user))
  {
    $user = new User($c->storage);
  }

  return $user;
};
spl_object_hash($container->user)



            ===
spl_object_hash($container->user)
$container->user = $container->asShared(function ($c)
{
  return new User($c->storage);
});
A closure is a lambda
that remembers the context
      of its creation…
class Article
{
  public function __construct($title)
  {
    $this->title = $title;
  }

    public function getTitle()
    {
      return $this->title;
    }
}

$articles = array(
   new Article('Title 1'),
   new Article('Title 2'),
);
$mapper = function ($article)
{
   return $article->getTitle();
};

$titles = array_map($mapper, $articles);
$method = 'getTitle';

$mapper = function ($article) use($method)
{
   return $article->$method();
};

$method = 'getAuthor';

$titles = array_map($mapper, $articles);
$mapper = function ($method)
{
   return function ($article) use($method)
   {
      return $article->$method();
   };
};
$titles = array_map($mapper('getTitle'), $articles);


$authors = array_map($mapper('getAuthor'), $articles);
$container->user = $container->asShared(function ($c)
{
  return new User($c->storage);
});
function asShared(Closure $lambda)
{
  return function ($container) use ($lambda)
  {
    static $object;

      if (is_null($object))
      {
        $object = $lambda($container);
      }
      return $object;
    };
}
class Container
{
  protected $values = array();

    function __set($id, $value)
    {
      $this->values[$id] = $value;
    }

    function __get($id)
    {                                                            Error management
      if (!isset($this->values[$id]))
      {
        throw new InvalidArgumentException(sprintf('Value "%s" is not defined.', $id));
      }

        if (is_callable($this->values[$id]))
        {
          return $this->values[$id]($this);
        }
        else
        {
          return $this->values[$id];
        }
    }
}
class Container
{
  protected $values = array();

    function __set($id, $value)
    {
      $this->values[$id] = $value;
    }

    function __get($id)
    {
      if (!isset($this->values[$id]))
      {
        throw new InvalidArgumentException(sprintf('Value "%s" is not defined.', $id));
      }

        if (is_callable($this->values[$id]))
        {
          return $this->values[$id]($this);
        }
        else
        {
          return $this->values[$id];
        }
    }

    function asShared($callable)
    {


                                                                                          40 LOC for a fully-
      return function ($c) use ($callable)
      {
        static $object;

          if (is_null($object))
          {
            $object = $callable($c);
                                                                                          featured container
          }
          return $object;
        };
    }
}
More about Dependency Injection

http://fabien.potencier.org/article/17/on-php-5-3-lambda-functions-and-closures


http://components.symfony-project.org/dependency-injection/



http://github.com/fabpot/pimple


http://twittee.org/
Twittee: A Container in a tweet
•  Implementation does not use PHP 5.3
•  Its usage needs PHP 5.3


class Container {
  protected $s=array();
  function __set($k, $c) { $this->s[$k]=$c; }
  function __get($k) { return $this->s[$k]($this); }
}
                                         twittee.org
Remember, most of the time,
 you don’t need a Container
to use Dependency Injection
You can start to use and benefit from
    Dependency Injection today
by implementing it
        in your projects

  by using externals libraries
      that already use DI
without the need of a container
Symfony
Zend Framework
 ezComponents
    Doctrine
  Swift Mailer
      …
Questions?

My slides will be available on
slideshare.com/fabpot
symfony-live.com
              with Matthew Weier O’Pheinney




    I will reveal the first alpha release of Symfony 2.0!
symfony-live.com
             with Matthew Weier O’Pheinney




   … with Matthew Weier O'Phinney as a special guest
Sensio S.A.
    92-98, boulevard Victor Hugo
        92 115 Clichy Cedex
              FRANCE
       Tél. : +33 1 40 99 80 80

               Contact
           Fabien Potencier
    fabien.potencier at sensio.com




  http://www.sensiolabs.com/
http://www.symfony-project.org/
 http://fabien.potencier.org/
BONUS
Symfony Components
Dependency Injection
SymfonyComponentsDependencyInjection
DI Container Hello World example

use SymfonyComponentsDependencyInjectionBuilder;
use SymfonyComponentsDependencyInjectionReference;

$container = new Builder();

$container->register('output', 'FancyOutput');

$container->
  register('message', 'Message')->
  setArguments(array(new Reference('output'), array('with_newline' => true)))
;

$container->message->say('Hello World!');
$message = $container->message;

          Get the configuration for the message service

    The Message constructor must be given an output service

            Get the output object from the container

  Create a Message object by passing the constructor arguments
$message = $container->message;


                    is roughly equivalent to

                  $output = new FancyOutput();
$message = new Message($output, array('with_newline' => true));!
$container = new Builder();

$container->register('output', 'FancyOutput');
$container->
  register('message', 'Message')->
  setArguments(array(new Reference('output'), array('with_newline' => true)))
;

$container->message->say('Hello World!');                                        PHP
<container xmlns="http://symfony-project.org/2.0/container">
  <services>                                                                     XML
    <service id="output" class="FancyOutput" />

    <service id="message" class="Message">                    XML is validated
      <argument type="service" id="output" />                 against an XSD
      <argument type="collection">
        <argument key="with_newline">true</argument>
      </argument>
    </service>
  </services>
</container>

$container = new Builder();
$loader = new XmlFileLoader($container);
$loader->load('services.xml');
$container = new Builder();

$container->register('output', 'FancyOutput');
$container->
  register('message', 'Message')->
  setArguments(array(new sfServiceReference('output'), array('with_newline' => true)))
;

$container->message->say('Hello World!');                                          PHP
services:
  output: { class: FancyOutput }
  message:                                                                         YAML
    class: Message
    arguments:
      - @output
      - { with_newline: true }

$container = new Builder();
$loader = new YamlFileLoader($container);
$loader->load('services.yml');
<container xmlns="http://symfony-project.org/2.0/container">
  <parameters>
    <parameter key="output.class">FancyOutput</parameter>
    <parameter key="message.options" type="collection">
      <parameter key="with_newline">true</parameter>
    </parameter>
  </parameters>

  <services>
    <service id="output" class="%output.class%" />

    <service id="message" class="Message">
      <argument type="service" id="output" />
      <argument>%message.options%</argument>
    </service>
  </services>
</container>

$container = new Builder();
$loader = new XmlFileLoader($container);
$loader->load('services.xml');
<container xmlns="http://symfony-project.org/2.0/container">
  <imports>
    <import resource="config.xml" />
  </imports>

  <services>
    <service id="output" class="%output.class%" />
    <service id="message" class="Message">
      <argument type="service" id="output" />
      <argument>%message.options%</argument>
    </service>
  </services>
</container>

<container xmlns="http://symfony-project.org/2.0/container">
  <parameters>
    <parameter key="output.class">FancyOutput</parameter>
    <parameter key="message.options" type="collection">
      <parameter key="with_newline">true</parameter>
    </parameter>
  </parameters>
</container>

$container = new Builder();
$loader = new FileXmlFileLoader($container);
$loader->load('services.xml');
<services>
 <import resource="config.yml" class="SymfonyComponentsDependencyInjection
LoaderYamlFileLoader" />

  <service id="output" class="%output.class%" />
  <service id="message" class="Message">
    <argument type="service" id="output" />
    <argument>%message.options%</argument>
  </service>
</services>

parameters:
  output.class: FancyOutput

  message.options: { with_newline: true }

$container = new Builder();
$loader = new XmlFileLoader($container);
$loader->load('services.xml');
Loaders & Dumpers
•  IniFileLoader
•  XmlFileLoader
•  YamlFileLoader

•    XmlDumper
•    YamlDumper
                    Make your container
•    PhpDumper      VERY fast
•    GraphvizDumper
use   SymfonyComponentsDependencyInjectionBuilder;
use   SymfonyComponentsDependencyInjectionReference;
use   SymfonyComponentsDependencyInjectionDumperXmlDumper;
use   SymfonyComponentsDependencyInjectionDumperYamlDumper;
use   SymfonyComponentsDependencyInjectionDumperPhpDumper;
use   SymfonyComponentsDependencyInjectionLoaderXmlFileLoader;
use   SymfonyComponentsDependencyInjectionLoaderYamlFileLoader;

$container = new Builder();

$container->register('output', 'FancyOutput');

$container->
  register('message', 'Message')->
  setArguments(array(new Reference('output'), array('with_newline' => true)))
;
$dumper = new XmlDumper($container);
file_put_contents(__DIR__.'/container.xml', $dumper->dump());

$loader = new XmlFileLoader($container);
$loader->load(__DIR__.'/container.xml');

$dumper = new YamlDumper($container);
file_put_contents(__DIR__.'/container.yml', $dumper->dump());

$loader = new YamlFileLoader($container);
$loader->load(__DIR__.'/container.yml');

$dumper = new PhpDumper($container);
echo $dumper->dump();
use SymfonyComponentsDependencyInjectionContainer;
use SymfonyComponentsDependencyInjectionReference;
use SymfonyComponentsDependencyInjectionParameter;

class ProjectServiceContainer extends Container
{
  protected $shared = array();

    protected function getOutputService()
    {
      if (isset($this->shared['output'])) return $this->shared['output'];

        $instance = new FancyOutput();

        return $this->shared['output'] = $instance;
    }

    protected function getMessageService()
    {
      if (isset($this->shared['message'])) return $this->shared['message'];

        $instance = new Message($this->getService('output'), array('with_newline' => true));

        return $this->shared['message'] = $instance;
    }
}
use SymfonyComponentsDependencyInjectionDumperGraphvizDumper;

$dumper = new GraphvizDumper($container);
echo $dumper->dump();
digraph sc {
  ratio="compress"
  node [fontsize="11" fontname="Arial" shape="record"];
  edge [fontsize="9" fontname="Arial" color="grey" arrowhead="open" arrowsize="0.5"];

  node_output [label="outputnFancyOutputn", shape=record, fillcolor="#eeeeee", style="filled"];
  node_message [label="messagenMessagen", shape=record, fillcolor="#eeeeee", style="filled"];
  node_service_container [label="service_containernSymfonyComponentsDependencyInjectionBuilder
n", shape=record, fillcolor="#9999ff", style="filled"];
  node_message -> node_output [label="" style="filled"];
}
Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3

Contenu connexe

Tendances

Istio : Service Mesh
Istio : Service MeshIstio : Service Mesh
Istio : Service MeshKnoldus Inc.
 
Data Warehouses in Kubernetes Visualized: the ClickHouse Kubernetes Operator UI
Data Warehouses in Kubernetes Visualized: the ClickHouse Kubernetes Operator UIData Warehouses in Kubernetes Visualized: the ClickHouse Kubernetes Operator UI
Data Warehouses in Kubernetes Visualized: the ClickHouse Kubernetes Operator UIAltinity Ltd
 
Log analysis using elk
Log analysis using elkLog analysis using elk
Log analysis using elkRushika Shah
 
Using eBPF for High-Performance Networking in Cilium
Using eBPF for High-Performance Networking in CiliumUsing eBPF for High-Performance Networking in Cilium
Using eBPF for High-Performance Networking in CiliumScyllaDB
 
SpringBoot with MyBatis, Flyway, QueryDSL
SpringBoot with MyBatis, Flyway, QueryDSLSpringBoot with MyBatis, Flyway, QueryDSL
SpringBoot with MyBatis, Flyway, QueryDSLSunghyouk Bae
 
Jose portillo dev con presentation 1138
Jose portillo   dev con presentation 1138Jose portillo   dev con presentation 1138
Jose portillo dev con presentation 1138Jose Portillo
 
REST-API introduction for developers
REST-API introduction for developersREST-API introduction for developers
REST-API introduction for developersPatrick Savalle
 
MuleSoft Deployment Strategies (RTF vs Hybrid vs CloudHub)
MuleSoft Deployment Strategies (RTF vs Hybrid vs CloudHub)MuleSoft Deployment Strategies (RTF vs Hybrid vs CloudHub)
MuleSoft Deployment Strategies (RTF vs Hybrid vs CloudHub)Prashanth Kurimella
 
Design principles - SOLID
Design principles - SOLIDDesign principles - SOLID
Design principles - SOLIDPranalee Rokde
 
Clean architecture with asp.net core
Clean architecture with asp.net coreClean architecture with asp.net core
Clean architecture with asp.net coreSam Nasr, MCSA, MVP
 
[THR20007] WSL v2와 Rancher K3S로 빠르게 로컬 쿠버네티스 클러스터 만들기 / Quickly create a loca...
[THR20007] WSL v2와 Rancher K3S로 빠르게 로컬 쿠버네티스 클러스터 만들기 / Quickly create a loca...[THR20007] WSL v2와 Rancher K3S로 빠르게 로컬 쿠버네티스 클러스터 만들기 / Quickly create a loca...
[THR20007] WSL v2와 Rancher K3S로 빠르게 로컬 쿠버네티스 클러스터 만들기 / Quickly create a loca...Jung Hyun Nam
 
Clean Architecture
Clean ArchitectureClean Architecture
Clean ArchitectureFlavius Stef
 
Mulesoft with ELK (Elastic Search, Log stash, Kibana)
Mulesoft with ELK (Elastic Search, Log stash, Kibana)Mulesoft with ELK (Elastic Search, Log stash, Kibana)
Mulesoft with ELK (Elastic Search, Log stash, Kibana)Gaurav Sethi
 
Mini Curso Web Services com PHP
Mini Curso Web Services com PHPMini Curso Web Services com PHP
Mini Curso Web Services com PHPelliando dias
 
How to Build a Telegraf Plugin by Noah Crowley
How to Build a Telegraf Plugin by Noah CrowleyHow to Build a Telegraf Plugin by Noah Crowley
How to Build a Telegraf Plugin by Noah CrowleyInfluxData
 
Introduction to Apache ActiveMQ Artemis
Introduction to Apache ActiveMQ ArtemisIntroduction to Apache ActiveMQ Artemis
Introduction to Apache ActiveMQ ArtemisYoshimasa Tanabe
 

Tendances (20)

Istio : Service Mesh
Istio : Service MeshIstio : Service Mesh
Istio : Service Mesh
 
Data Warehouses in Kubernetes Visualized: the ClickHouse Kubernetes Operator UI
Data Warehouses in Kubernetes Visualized: the ClickHouse Kubernetes Operator UIData Warehouses in Kubernetes Visualized: the ClickHouse Kubernetes Operator UI
Data Warehouses in Kubernetes Visualized: the ClickHouse Kubernetes Operator UI
 
Log analysis using elk
Log analysis using elkLog analysis using elk
Log analysis using elk
 
Istio on Kubernetes
Istio on KubernetesIstio on Kubernetes
Istio on Kubernetes
 
Using eBPF for High-Performance Networking in Cilium
Using eBPF for High-Performance Networking in CiliumUsing eBPF for High-Performance Networking in Cilium
Using eBPF for High-Performance Networking in Cilium
 
WTF is Reactive Programming
WTF is Reactive ProgrammingWTF is Reactive Programming
WTF is Reactive Programming
 
SpringBoot with MyBatis, Flyway, QueryDSL
SpringBoot with MyBatis, Flyway, QueryDSLSpringBoot with MyBatis, Flyway, QueryDSL
SpringBoot with MyBatis, Flyway, QueryDSL
 
Jose portillo dev con presentation 1138
Jose portillo   dev con presentation 1138Jose portillo   dev con presentation 1138
Jose portillo dev con presentation 1138
 
REST-API introduction for developers
REST-API introduction for developersREST-API introduction for developers
REST-API introduction for developers
 
MuleSoft Deployment Strategies (RTF vs Hybrid vs CloudHub)
MuleSoft Deployment Strategies (RTF vs Hybrid vs CloudHub)MuleSoft Deployment Strategies (RTF vs Hybrid vs CloudHub)
MuleSoft Deployment Strategies (RTF vs Hybrid vs CloudHub)
 
Design principles - SOLID
Design principles - SOLIDDesign principles - SOLID
Design principles - SOLID
 
Clean architecture with asp.net core
Clean architecture with asp.net coreClean architecture with asp.net core
Clean architecture with asp.net core
 
Introdução APIs RESTful
Introdução APIs RESTfulIntrodução APIs RESTful
Introdução APIs RESTful
 
[THR20007] WSL v2와 Rancher K3S로 빠르게 로컬 쿠버네티스 클러스터 만들기 / Quickly create a loca...
[THR20007] WSL v2와 Rancher K3S로 빠르게 로컬 쿠버네티스 클러스터 만들기 / Quickly create a loca...[THR20007] WSL v2와 Rancher K3S로 빠르게 로컬 쿠버네티스 클러스터 만들기 / Quickly create a loca...
[THR20007] WSL v2와 Rancher K3S로 빠르게 로컬 쿠버네티스 클러스터 만들기 / Quickly create a loca...
 
Clean Architecture
Clean ArchitectureClean Architecture
Clean Architecture
 
Node.js Express Framework
Node.js Express FrameworkNode.js Express Framework
Node.js Express Framework
 
Mulesoft with ELK (Elastic Search, Log stash, Kibana)
Mulesoft with ELK (Elastic Search, Log stash, Kibana)Mulesoft with ELK (Elastic Search, Log stash, Kibana)
Mulesoft with ELK (Elastic Search, Log stash, Kibana)
 
Mini Curso Web Services com PHP
Mini Curso Web Services com PHPMini Curso Web Services com PHP
Mini Curso Web Services com PHP
 
How to Build a Telegraf Plugin by Noah Crowley
How to Build a Telegraf Plugin by Noah CrowleyHow to Build a Telegraf Plugin by Noah Crowley
How to Build a Telegraf Plugin by Noah Crowley
 
Introduction to Apache ActiveMQ Artemis
Introduction to Apache ActiveMQ ArtemisIntroduction to Apache ActiveMQ Artemis
Introduction to Apache ActiveMQ Artemis
 

En vedette

Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3Fabien Potencier
 
Dependency Injection in Laravel
Dependency Injection in LaravelDependency Injection in Laravel
Dependency Injection in LaravelHAO-WEN ZHANG
 
Inversion of Control and Dependency Injection
Inversion of Control and Dependency InjectionInversion of Control and Dependency Injection
Inversion of Control and Dependency InjectionDinesh Sharma
 
Functional Dependency Injection in C#
Functional Dependency Injection in C#Functional Dependency Injection in C#
Functional Dependency Injection in C#Thomas Jaskula
 
Dependency injection - the right way
Dependency injection - the right wayDependency injection - the right way
Dependency injection - the right wayThibaud Desodt
 
Inversion of Control - Introduction and Best Practice
Inversion of Control - Introduction and Best PracticeInversion of Control - Introduction and Best Practice
Inversion of Control - Introduction and Best PracticeLars-Erik Kindblad
 
Do you know Dependency Injection ?
Do you know Dependency Injection ?Do you know Dependency Injection ?
Do you know Dependency Injection ?Masayuki IZUMI
 
You're Still Doing It Wrong
You're Still Doing It WrongYou're Still Doing It Wrong
You're Still Doing It WrongPaul Armstrong
 

En vedette (10)

Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Dependency Injection in Laravel
Dependency Injection in LaravelDependency Injection in Laravel
Dependency Injection in Laravel
 
Inversion of Control and Dependency Injection
Inversion of Control and Dependency InjectionInversion of Control and Dependency Injection
Inversion of Control and Dependency Injection
 
Functional Dependency Injection in C#
Functional Dependency Injection in C#Functional Dependency Injection in C#
Functional Dependency Injection in C#
 
Dependency injection - the right way
Dependency injection - the right wayDependency injection - the right way
Dependency injection - the right way
 
Inversion of Control - Introduction and Best Practice
Inversion of Control - Introduction and Best PracticeInversion of Control - Introduction and Best Practice
Inversion of Control - Introduction and Best Practice
 
Do you know Dependency Injection ?
Do you know Dependency Injection ?Do you know Dependency Injection ?
Do you know Dependency Injection ?
 
You're Still Doing It Wrong
You're Still Doing It WrongYou're Still Doing It Wrong
You're Still Doing It Wrong
 
IoC and Mapper in C#
IoC and Mapper in C#IoC and Mapper in C#
IoC and Mapper in C#
 

Similaire à Dependency Injection with PHP and PHP 5.3

Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010Fabien Potencier
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201Fabien Potencier
 
Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Fabien Potencier
 
Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4Fabien Potencier
 
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)Fabien Potencier
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Fabien Potencier
 
Dependency injection in Drupal 8
Dependency injection in Drupal 8Dependency injection in Drupal 8
Dependency injection in Drupal 8Alexei Gorobets
 
Beyond symfony 1.2 (Symfony Camp 2008)
Beyond symfony 1.2 (Symfony Camp 2008)Beyond symfony 1.2 (Symfony Camp 2008)
Beyond symfony 1.2 (Symfony Camp 2008)Fabien Potencier
 
MUC - Moodle Universal Cache
MUC - Moodle Universal CacheMUC - Moodle Universal Cache
MUC - Moodle Universal CacheTim Hunt
 
Caching and Scaling WordPress using Fragment Caching
Caching and Scaling WordPress using Fragment CachingCaching and Scaling WordPress using Fragment Caching
Caching and Scaling WordPress using Fragment CachingErick Hitter
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency InjectionRifat Nabi
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodeSWIFTotter Solutions
 
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Lithium: The Framework for People Who Hate Frameworks, Tokyo EditionLithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Lithium: The Framework for People Who Hate Frameworks, Tokyo EditionNate Abele
 
The Origin of Lithium
The Origin of LithiumThe Origin of Lithium
The Origin of LithiumNate Abele
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf Conference
 
The Zen of Lithium
The Zen of LithiumThe Zen of Lithium
The Zen of LithiumNate Abele
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Jeff Carouth
 
Lithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksLithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksNate Abele
 

Similaire à Dependency Injection with PHP and PHP 5.3 (20)

Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
 
Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010
 
Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4
 
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010
 
Dependency injection in Drupal 8
Dependency injection in Drupal 8Dependency injection in Drupal 8
Dependency injection in Drupal 8
 
Beyond symfony 1.2 (Symfony Camp 2008)
Beyond symfony 1.2 (Symfony Camp 2008)Beyond symfony 1.2 (Symfony Camp 2008)
Beyond symfony 1.2 (Symfony Camp 2008)
 
BEAR DI
BEAR DIBEAR DI
BEAR DI
 
MUC - Moodle Universal Cache
MUC - Moodle Universal CacheMUC - Moodle Universal Cache
MUC - Moodle Universal Cache
 
Caching and Scaling WordPress using Fragment Caching
Caching and Scaling WordPress using Fragment CachingCaching and Scaling WordPress using Fragment Caching
Caching and Scaling WordPress using Fragment Caching
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better Code
 
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Lithium: The Framework for People Who Hate Frameworks, Tokyo EditionLithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
 
The Origin of Lithium
The Origin of LithiumThe Origin of Lithium
The Origin of Lithium
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
 
The Zen of Lithium
The Zen of LithiumThe Zen of Lithium
The Zen of Lithium
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4
 
Lithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksLithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate Frameworks
 

Plus de Fabien Potencier

Plus de Fabien Potencier (20)

Varnish
VarnishVarnish
Varnish
 
Look beyond PHP
Look beyond PHPLook beyond PHP
Look beyond PHP
 
Caching on the Edge
Caching on the EdgeCaching on the Edge
Caching on the Edge
 
Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010
 
PhpBB meets Symfony2
PhpBB meets Symfony2PhpBB meets Symfony2
PhpBB meets Symfony2
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 
Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010
 
Caching on the Edge with Symfony2
Caching on the Edge with Symfony2Caching on the Edge with Symfony2
Caching on the Edge with Symfony2
 
Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2
 
News of the Symfony2 World
News of the Symfony2 WorldNews of the Symfony2 World
News of the Symfony2 World
 
Symfony Components
Symfony ComponentsSymfony Components
Symfony Components
 
PHP 5.3 in practice
PHP 5.3 in practicePHP 5.3 in practice
PHP 5.3 in practice
 
Symfony2 revealed
Symfony2 revealedSymfony2 revealed
Symfony2 revealed
 
Symfony Components 2.0 on PHP 5.3
Symfony Components 2.0 on PHP 5.3Symfony Components 2.0 on PHP 5.3
Symfony Components 2.0 on PHP 5.3
 
Playing With PHP 5.3
Playing With PHP 5.3Playing With PHP 5.3
Playing With PHP 5.3
 
Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3
 
Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009
 
Symfony And Zend Framework Together 2009
Symfony And Zend Framework Together 2009Symfony And Zend Framework Together 2009
Symfony And Zend Framework Together 2009
 

Dernier

Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Orbitshub
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...Zilliz
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamUiPathCommunity
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Victor Rentea
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWERMadyBayot
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native ApplicationsWSO2
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...apidays
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Jeffrey Haguewood
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...apidays
 

Dernier (20)

Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 

Dependency Injection with PHP and PHP 5.3

  • 1. Dependency Injection with PHP and PHP 5.3 Fabien Potencier
  • 2. Fabien Potencier •  Serial entrepreneur and developer by passion •  Founder of Sensio (in 1998) –  A services and consulting company specialized in Web technologies and Internet marketing (France and USA) –  70 people –  Open-Source specialists –  Big corporate customers –  Consulting, training, development, web design, … and more –  Sponsor of a lot of Open-Source projects like symfony and Doctrine
  • 3. Fabien Potencier •  Creator and lead developer of symfony… •  and creator and lead developer of some more OSS: –  symfony components –  Swift Mailer : Powerful component based mailing library for PHP –  Twig : Fexible, fast, and secure template language for PHP –  Pirum : Simple PEAR Channel Server Manager –  Sismo : PHP continuous integration server –  Lime : Easy to use unit testing library for PHP –  Twitto : A web framework in a tweet –  Twittee : A Dependency Injection Container in a tweet –  Pimple : A small PHP 5.3 dependency injection container
  • 4. Fabien Potencier •  Read my technical blog: http://fabien.potencier.org/ •  Follow me on Twitter: @fabpot •  Fork my code on Github: http://github.com/fabpot/
  • 5. Dependency Injection A real world « web » example
  • 6. In most web applications, you need to manage the user preferences –  The user language –  Whether the user is authenticated or not –  The user credentials –  …
  • 7. This can be done with a User object –  setLanguage(), getLanguage() –  setAuthenticated(), isAuthenticated() –  addCredential(), hasCredential() –  ...
  • 8. The User information need to be persisted between HTTP requests We use the PHP session for the Storage
  • 9. class SessionStorage { function __construct($cookieName = 'PHP_SESS_ID') { session_name($cookieName); session_start(); } function set($key, $value) { $_SESSION[$key] = $value; } // ... }
  • 10. class User { protected $storage; function __construct() Very hard to { customize $this->storage = new SessionStorage(); } function setLanguage($language) { $this->storage->set('language', $language); } // ... } Very easy to use $user = new User();
  • 11. class User { protected $storage; Very easy to customize function __construct($storage) { $this->storage = $storage; } } $storage = new SessionStorage(); $user = new User($storage); Slightly more difficult to use
  • 13. Let’s understand why the first example is not a good idea
  • 14. I want to change the session cookie name
  • 15. class User { protected $storage; function __construct() Hardcode it in the { User class $this->storage = new SessionStorage('SESSION_ID'); } function setLanguage($language) { $this->storage->set('language', $language); } // ... } $user = new User();
  • 16. class User { protected $storage; function __construct() { $this->storage = new SessionStorage(STORAGE_SESSION_NAME); } } Add a global configuration? define('STORAGE_SESSION_NAME', 'SESSION_ID'); $user = new User();
  • 17. class User { protected $storage; function __construct($sessionName) { $this->storage = new SessionStorage($sessionName); } } $user = new User('SESSION_ID'); Configure via User?
  • 18. class User { protected $storage; function __construct($storageOptions) { $this->storage = new SessionStorage($storageOptions ['session_name']); $user = new User( array('session_name' => 'SESSION_ID') ); Configure with an array?
  • 19. I want to change the session storage implementation Filesystem MySQL Memcached …
  • 20. class User { protected $storage; function __construct() Use a global { registry object? $this->storage = Registry::get('session_storage'); } } $storage = new SessionStorage(); Registry::set('session_storage', $storage); $user = new User();
  • 21. Now, the User depends on the Registry
  • 22. Instead of harcoding the Storage dependency inside the User class constructor Inject the Storage dependency in the User object
  • 23. class User { protected $storage; function __construct($storage) { $this->storage = $storage; } } $storage = new SessionStorage('SESSION_ID'); $user = new User($storage);
  • 24. What are the advantages?
  • 26. class User { protected $storage; function __construct($storage) { $this->storage = $storage; } } Use a different Storage engine $storage = new MySQLSessionStorage('SESSION_ID'); $user = new User($storage);
  • 28. class User { protected $storage; function __construct($storage) { $this->storage = $storage; } } Configuration is natural $storage = new MySQLSessionStorage('SESSION_ID'); $user = new User($storage);
  • 29. Wrap third-party classes (Interface / Adapter)
  • 30. class User { protected $storage; Add an interface function __construct(SessionStorageInterface $storage) { $this->storage = $storage; } } interface SessionStorageInterface { function get($key); function set($key, $value); }
  • 31. Mock the Storage object (for testing)
  • 32. class User { protected $storage; function __construct(SessionStorageInterface $storage) { $this->storage = $storage; } } Mock the Session class SessionStorageForTests implements SessionStorageInterface { protected $data = array(); static function set($key, $value) { self::$data[$key] = $value; } }
  • 33. Use different Storage strategies Configuration becomes natural Wrap third-party classes (Interface / Adapter) Mock the Storage object (for testing) Easy without changing the User class
  • 34. « Dependency Injection is where components are given their dependencies through their constructors, methods, or directly into fields. » http://www.picocontainer.org/injection.html
  • 35. $storage = new SessionStorage(); // constructor injection $user = new User($storage); // setter injection $user = new User(); $user->setStorage($storage); // property injection $user = new User(); $user->storage = $storage;
  • 36. A slightly more complex web example
  • 37. $request = new Request(); $response = new Response(); $storage = new FileSessionStorage('SESSION_ID'); $user = new User($storage); $cache = new FileCache( array('dir' => dirname(__FILE__).'/cache') ); $routing = new Routing($cache);
  • 38. class Application { function __construct() { $this->request = new WebRequest(); $this->response = new WebResponse(); $storage = new FileSessionStorage('SESSION_ID'); $this->user = new User($storage); $cache = new FileCache( array('dir' => dirname(__FILE__).'/cache') ); $this->routing = new Routing($cache); } } $application = new Application();
  • 40. class Application { function __construct() { $this->request = new WebRequest(); $this->response = new WebResponse(); $storage = new FileSessionStorage('SESSION_ID'); $this->user = new User($storage); $cache = new FileCache( array('dir' => dirname(__FILE__).'/cache') ); $this->routing = new Routing($cache); } } $application = new Application();
  • 41. We need a Container Describes objects and their dependencies Instantiates and configures objects on-demand
  • 42. A container SHOULD be able to manage any PHP object (POPO) The objects MUST not know that they are managed by a container
  • 43. •  Parameters –  The SessionStorageInterface implementation we want to use (the class name) –  The session name •  Objects –  SessionStorage –  User •  Dependencies –  User depends on a SessionStorageInterface implementation
  • 44. Let’s build a simple container with PHP 5.3
  • 46. class Container { protected $parameters = array(); public function setParameter($key, $value) { $this->parameters[$key] = $value; } public function getParameter($key) { return $this->parameters[$key]; } }
  • 47. Decoupling $container = new Container(); Customization $container->setParameter('session_name', 'SESSION_ID'); $container->setParameter('storage_class', 'SessionStorage'); $class = $container->getParameter('storage_class'); $sessionStorage = new $class($container->getParameter('session_name')); $user = new User($sessionStorage); Objects creation
  • 48. class Container Using PHP { magic methods protected $parameters = array(); public function __set($key, $value) { $this->parameters[$key] = $value; } public function __get($key) { return $this->parameters[$key]; } }
  • 49. Interface is cleaner $container = new Container(); $container->session_name = 'SESSION_ID'; $container->storage_class = 'SessionStorage'; $sessionStorage = new $container->storage_class($container->session_name); $user = new User($sessionStorage);
  • 51. We need a way to describe how to create objects, without actually instantiating anything! Anonymous functions to the rescue!
  • 52. Anonymous Functions / Lambdas A lambda is a function defined on the fly with no name function () { echo 'Hello world!'; };
  • 53. Anonymous Functions / Lambdas A lambda can be stored in a variable $hello = function () { echo 'Hello world!'; };
  • 54. Anonymous Functions / Lambdas And then it can be used as any other PHP callable $hello(); call_user_func($hello);
  • 55. Anonymous Functions / Lambdas You can also pass a lambda as an argument to a function or method function foo(Closure $func) { $func(); } foo($hello);
  • 56. Fonctions anonymes $hello = function ($name) { echo 'Hello '.$name; }; $hello('Fabien'); call_user_func($hello, 'Fabien'); function foo(Closure $func, $name) { $func($name); } foo($hello, 'Fabien');
  • 58. class Container { protected $parameters = array(); protected $objects = array(); public function __set($key, $value) { $this->parameters[$key] = $value; } public function __get($key) Store a lambda { return $this->parameters[$key]; able to create the object on-demand } public function setService($key, Closure $service) { $this->objects[$key] = $service; } public function getService($key) Ask the closure to create { return $this->objects[$key]($this); th e object and pass the } } current Container
  • 59. $container = new Container(); $container->session_name = 'SESSION_ID'; Description $container->storage_class = 'SessionStorage'; $container->setService('user', function ($c) { return new User($c->getService('storage')); }); $container->setService('storage', function ($c) { return new $c->storage_class($c->session_name); }); Creating the User is now as easy as before $user = $container->getService('user');
  • 60. class Container { protected $values = array(); Simplify the code function __set($id, $value) { $this->values[$id] = $value; } function __get($id) { if (is_callable($this->values[$id])) { return $this->values[$id]($this); } else { return $this->values[$id]; } } }
  • 61. $container = new Container(); Unified interface $container->session_name = 'SESSION_ID'; $container->storage_class = 'SessionStorage'; $container->user = function ($c) { return new User($c->storage); }; $container->storage = function ($c) { return new $c->storage_class($c->session_name); }; $user = $container->user;
  • 63. For some objects, like the user, the container must always return the same instance
  • 64. spl_object_hash($container->user) !== spl_object_hash($container->user)
  • 65. $container->user = function ($c) { static $user; if (is_null($user)) { $user = new User($c->storage); } return $user; };
  • 66. spl_object_hash($container->user) === spl_object_hash($container->user)
  • 67. $container->user = $container->asShared(function ($c) { return new User($c->storage); });
  • 68. A closure is a lambda that remembers the context of its creation…
  • 69. class Article { public function __construct($title) { $this->title = $title; } public function getTitle() { return $this->title; } } $articles = array( new Article('Title 1'), new Article('Title 2'), );
  • 70. $mapper = function ($article) { return $article->getTitle(); }; $titles = array_map($mapper, $articles);
  • 71. $method = 'getTitle'; $mapper = function ($article) use($method) { return $article->$method(); }; $method = 'getAuthor'; $titles = array_map($mapper, $articles);
  • 72. $mapper = function ($method) { return function ($article) use($method) { return $article->$method(); }; };
  • 73. $titles = array_map($mapper('getTitle'), $articles); $authors = array_map($mapper('getAuthor'), $articles);
  • 74. $container->user = $container->asShared(function ($c) { return new User($c->storage); });
  • 75. function asShared(Closure $lambda) { return function ($container) use ($lambda) { static $object; if (is_null($object)) { $object = $lambda($container); } return $object; }; }
  • 76. class Container { protected $values = array(); function __set($id, $value) { $this->values[$id] = $value; } function __get($id) { Error management if (!isset($this->values[$id])) { throw new InvalidArgumentException(sprintf('Value "%s" is not defined.', $id)); } if (is_callable($this->values[$id])) { return $this->values[$id]($this); } else { return $this->values[$id]; } } }
  • 77. class Container { protected $values = array(); function __set($id, $value) { $this->values[$id] = $value; } function __get($id) { if (!isset($this->values[$id])) { throw new InvalidArgumentException(sprintf('Value "%s" is not defined.', $id)); } if (is_callable($this->values[$id])) { return $this->values[$id]($this); } else { return $this->values[$id]; } } function asShared($callable) { 40 LOC for a fully- return function ($c) use ($callable) { static $object; if (is_null($object)) { $object = $callable($c); featured container } return $object; }; } }
  • 78. More about Dependency Injection http://fabien.potencier.org/article/17/on-php-5-3-lambda-functions-and-closures http://components.symfony-project.org/dependency-injection/ http://github.com/fabpot/pimple http://twittee.org/
  • 79. Twittee: A Container in a tweet •  Implementation does not use PHP 5.3 •  Its usage needs PHP 5.3 class Container { protected $s=array(); function __set($k, $c) { $this->s[$k]=$c; } function __get($k) { return $this->s[$k]($this); } } twittee.org
  • 80. Remember, most of the time, you don’t need a Container to use Dependency Injection
  • 81. You can start to use and benefit from Dependency Injection today
  • 82. by implementing it in your projects by using externals libraries that already use DI without the need of a container
  • 83. Symfony Zend Framework ezComponents Doctrine Swift Mailer …
  • 84. Questions? My slides will be available on slideshare.com/fabpot
  • 85. symfony-live.com with Matthew Weier O’Pheinney I will reveal the first alpha release of Symfony 2.0!
  • 86. symfony-live.com with Matthew Weier O’Pheinney … with Matthew Weier O'Phinney as a special guest
  • 87. Sensio S.A. 92-98, boulevard Victor Hugo 92 115 Clichy Cedex FRANCE Tél. : +33 1 40 99 80 80 Contact Fabien Potencier fabien.potencier at sensio.com http://www.sensiolabs.com/ http://www.symfony-project.org/ http://fabien.potencier.org/
  • 90. DI Container Hello World example use SymfonyComponentsDependencyInjectionBuilder; use SymfonyComponentsDependencyInjectionReference; $container = new Builder(); $container->register('output', 'FancyOutput'); $container-> register('message', 'Message')-> setArguments(array(new Reference('output'), array('with_newline' => true))) ; $container->message->say('Hello World!');
  • 91. $message = $container->message; Get the configuration for the message service The Message constructor must be given an output service Get the output object from the container Create a Message object by passing the constructor arguments
  • 92. $message = $container->message; is roughly equivalent to $output = new FancyOutput(); $message = new Message($output, array('with_newline' => true));!
  • 93. $container = new Builder(); $container->register('output', 'FancyOutput'); $container-> register('message', 'Message')-> setArguments(array(new Reference('output'), array('with_newline' => true))) ; $container->message->say('Hello World!'); PHP <container xmlns="http://symfony-project.org/2.0/container"> <services> XML <service id="output" class="FancyOutput" /> <service id="message" class="Message"> XML is validated <argument type="service" id="output" /> against an XSD <argument type="collection"> <argument key="with_newline">true</argument> </argument> </service> </services> </container> $container = new Builder(); $loader = new XmlFileLoader($container); $loader->load('services.xml');
  • 94. $container = new Builder(); $container->register('output', 'FancyOutput'); $container-> register('message', 'Message')-> setArguments(array(new sfServiceReference('output'), array('with_newline' => true))) ; $container->message->say('Hello World!'); PHP services: output: { class: FancyOutput } message: YAML class: Message arguments: - @output - { with_newline: true } $container = new Builder(); $loader = new YamlFileLoader($container); $loader->load('services.yml');
  • 95. <container xmlns="http://symfony-project.org/2.0/container"> <parameters> <parameter key="output.class">FancyOutput</parameter> <parameter key="message.options" type="collection"> <parameter key="with_newline">true</parameter> </parameter> </parameters> <services> <service id="output" class="%output.class%" /> <service id="message" class="Message"> <argument type="service" id="output" /> <argument>%message.options%</argument> </service> </services> </container> $container = new Builder(); $loader = new XmlFileLoader($container); $loader->load('services.xml');
  • 96. <container xmlns="http://symfony-project.org/2.0/container"> <imports> <import resource="config.xml" /> </imports> <services> <service id="output" class="%output.class%" /> <service id="message" class="Message"> <argument type="service" id="output" /> <argument>%message.options%</argument> </service> </services> </container> <container xmlns="http://symfony-project.org/2.0/container"> <parameters> <parameter key="output.class">FancyOutput</parameter> <parameter key="message.options" type="collection"> <parameter key="with_newline">true</parameter> </parameter> </parameters> </container> $container = new Builder(); $loader = new FileXmlFileLoader($container); $loader->load('services.xml');
  • 97. <services> <import resource="config.yml" class="SymfonyComponentsDependencyInjection LoaderYamlFileLoader" /> <service id="output" class="%output.class%" /> <service id="message" class="Message"> <argument type="service" id="output" /> <argument>%message.options%</argument> </service> </services> parameters: output.class: FancyOutput message.options: { with_newline: true } $container = new Builder(); $loader = new XmlFileLoader($container); $loader->load('services.xml');
  • 98. Loaders & Dumpers •  IniFileLoader •  XmlFileLoader •  YamlFileLoader •  XmlDumper •  YamlDumper Make your container •  PhpDumper VERY fast •  GraphvizDumper
  • 99. use SymfonyComponentsDependencyInjectionBuilder; use SymfonyComponentsDependencyInjectionReference; use SymfonyComponentsDependencyInjectionDumperXmlDumper; use SymfonyComponentsDependencyInjectionDumperYamlDumper; use SymfonyComponentsDependencyInjectionDumperPhpDumper; use SymfonyComponentsDependencyInjectionLoaderXmlFileLoader; use SymfonyComponentsDependencyInjectionLoaderYamlFileLoader; $container = new Builder(); $container->register('output', 'FancyOutput'); $container-> register('message', 'Message')-> setArguments(array(new Reference('output'), array('with_newline' => true))) ;
  • 100. $dumper = new XmlDumper($container); file_put_contents(__DIR__.'/container.xml', $dumper->dump()); $loader = new XmlFileLoader($container); $loader->load(__DIR__.'/container.xml'); $dumper = new YamlDumper($container); file_put_contents(__DIR__.'/container.yml', $dumper->dump()); $loader = new YamlFileLoader($container); $loader->load(__DIR__.'/container.yml'); $dumper = new PhpDumper($container); echo $dumper->dump();
  • 101. use SymfonyComponentsDependencyInjectionContainer; use SymfonyComponentsDependencyInjectionReference; use SymfonyComponentsDependencyInjectionParameter; class ProjectServiceContainer extends Container { protected $shared = array(); protected function getOutputService() { if (isset($this->shared['output'])) return $this->shared['output']; $instance = new FancyOutput(); return $this->shared['output'] = $instance; } protected function getMessageService() { if (isset($this->shared['message'])) return $this->shared['message']; $instance = new Message($this->getService('output'), array('with_newline' => true)); return $this->shared['message'] = $instance; } }
  • 102. use SymfonyComponentsDependencyInjectionDumperGraphvizDumper; $dumper = new GraphvizDumper($container); echo $dumper->dump();
  • 103. digraph sc { ratio="compress" node [fontsize="11" fontname="Arial" shape="record"]; edge [fontsize="9" fontname="Arial" color="grey" arrowhead="open" arrowsize="0.5"]; node_output [label="outputnFancyOutputn", shape=record, fillcolor="#eeeeee", style="filled"]; node_message [label="messagenMessagen", shape=record, fillcolor="#eeeeee", style="filled"]; node_service_container [label="service_containernSymfonyComponentsDependencyInjectionBuilder n", shape=record, fillcolor="#9999ff", style="filled"]; node_message -> node_output [label="" style="filled"]; }