SlideShare a Scribd company logo
Design patterns… revisited for PHP 5.3
Fabien Potencier
http://www.flickr.com/photos/revivaling/4979552548
Serial entrepreneur
Developer by passion
Founder of Sensio
Creator and lead developer of Symfony
http://www.twitter.com/fabpot
http://www.github.com/fabpot
http://fabien.potencier.org/
How does PHP 5.3 change the implementation
of some well-known Design Patterns?
http://www.flickr.com/photos/revivaling/4978949121
http://en.wikipedia.org/wiki/Design_pattern_%28computer_science%29
« A design pattern
is a general reusable solution
to a commonly occurring problem »
http://en.wikipedia.org/wiki/Design_pattern_%28computer_science%29
« By definition, a pattern
must be programmed anew
into each application that uses it. »
Design patterns revisited with PHP 5.3
The Singleton
http://www.flickr.com/photos/revivaling/4979546114
The Singleton may cause
serious damage to your code!
http://www.flickr.com/photos/mattbell/1696868871
class Singleton
{
function &getInstance()
{
static $instance;
if (!$instance) {
$instance = new Singleton();
}
return $instance;
}
}
$obj =& Singleton::getInstance();
You can still
instantiate the class
directly
The Singleton and PHP 4
class Singleton
{
static private $instance;
private function __construct() {}
static public function getInstance()
{
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
final private function __clone() {}
}
$obj = Singleton::getInstance();
do not forget to
override __clone()
The Singleton and PHP 5.0/5.1/5.2
abstract class Singleton
{
private static $instances = array();
final private function __construct()
{
if (isset(self::$instances[get_called_class()])) {
throw new Exception("A ".get_called_class()." instance already exists.");
}
static::initialize();
}
protected function initialize() {}
final public static function getInstance()
{
$class = get_called_class();
if (!isset(self::$instances[$class])) {
self::$instances[$class] = new static();
}
return self::$instances[$class];
}
final private function __clone() {}
}
The Singleton and PHP 5.3
class Foo extends Singleton {}
class Bar extends Singleton {}
$a = Foo::getInstance();
$b = Bar::getInstance();
The Singleton and PHP 5.3
Active Record
…Late Static Binding
http://www.flickr.com/photos/revivaling/4979548952
$article = Article::findByPk(1);
$article = Article::findByTitleAndAuthorId('foo', 1);
class Model
{
static public function getMe()
{
return __CLASS__;
}
}
class Article extends Model {}
echo Article::getMe();
class Model
{
static public function getMe()
{
return get_called_class();
}
}
class Article extends Model {}
echo Article::getMe();
class Model
{
static public function findByPk($id)
{
$table = strtolower(get_called_class());
$sql = "SELECT * FROM $this->table WHERE id = ?";
return $this->db->get($sql, $id);
}
}
class Article extends Model {}
$article = Article::findByPk(1);
class Model
{
static public function __callStatic($method, $arguments)
{
$table = strtolower(get_called_class());
$column = strtolower(substr($method, 6));
$value = $arguments[0];
$sql = "SELECT * FROM $this->table WHERE $column = ?";
return $this->db->get($sql, $value);
}
}
class Article extends Model {}
$article = Article::findByTitle('foo');
This is pseudo code with no proper SQL Injection protection!
http://www.flickr.com/photos/zippy/22748510
The Observer Pattern
http://www.flickr.com/photos/revivaling/4978951341
The Observer pattern allows
to extend or change the behavior of classes
without having to change them
When a method is called
on an object (subject),
it notifies other objects (listeners)
of the event
A Dispatcher is an object
that manages connections
between subjects and listeners
class User
{
function setLanguage($language)
{
$this->language = $language;
}
}
class Translator
{
function setLanguage($language)
{
$this->language = $language;
}
}
Dispatcher Listeners
Translator listens
to  ’language_change’
User notifies
‘language_change’ 
Notifiers
1
2 Calls
all listeners
Translator callback
is called
Dispatcher Listeners
Translator listens
to  ’language_change’
User notifies
‘language_change’ 
Notifiers
1
2 Calls
all listeners
Translator callback
is called
Your class listens
to‘language_change’
Your class callback
is called
$dispatcher = new Dispatcher();
$translator = new Translator($dispatcher);
$user = new User($dispatcher);
$user->setLanguage('fr');
class Translator
{
public function __construct($dispatcher)
{
$listener = array($translator, 'listenLanguageChange');
$dispatcher->connect('language_change', $listener);
}
public function listenLanguageChangeEvent($arguments)
{
$this->setLanguage($arguments['language']);
}
}
A PHP callable
The Event name
class User
{
function setLanguage($language)
{
$this->language = $language;
$this->dispatcher->notify('language_change',
array('language' => $language));
}
}
// register the listener with the dispatcher
$dispatcher = new Dispatcher(array(
'foo' => $listener,
));
// notify the event anywhere
$dispatcher->notify(
'foo',
array('name' => 'Fabien')
);
A listener can be any PHP callable
class Dispatcher
{
function __construct($map)
{
$this->map = $map;
}
function notify($name, $args = array())
{
call_user_func($this->map[$name], $args);
}
}
A PHP callable
class Dispatcher
{
function __construct($map)
{
$this->map = $map;
}
function notify($name, $args = array())
{
$this->map[$name]($rags);
}
} An anonymous function
// a function
function foo($args)
{
echo "Hello {$args['name']}n";
};
$listener = 'foo';
// an anonymous function
$listener = function ($args)
{
echo "Hello {$args['name']}n";
};
// register the listener with the dispatcher
$dispatcher = new Dispatcher(array(
'foo' => function ($args)
{
echo "Hello {$args['name']}n";
},
));
// notify the event anywhere
$dispatcher->notify(
'foo',
array('name' => 'Fabien')
);
$dispatcher = new Dispatcher(array(
'foo' => $listener
));
class Dispatcher
{
function connect($name, $listener)
{
if (!isset($this->map[$name])) {
$this->map[$name] = array();
}
$this->map[$name][] = $listener;
}
}
$l1 = function ($args)
{
echo "Hello1 {$args['name']}?n";
};
$l2 = function ($args)
{
echo "Hello2 {$args['name']}?n";
};
$listener = new Listeners($l1, $l2);
$dispatcher = new Dispatcher(array(
'foo' => $listener
));
$dispatcher = new Dispatcher(array(
'foo' => new Listeners($l1, $l2)
));
$listener = new Listeners($l1, $l2);
$listeners($args);
class Listeners
{
function __construct()
{
$this->listeners = func_get_args();
}
function __invoke($args = array())
{
foreach ($this->listeners as $listener) {
$listener($args);
}
}
}
Makes the object callable
Template View
http://www.flickr.com/photos/revivaling/4979557230
Hello {{ name }}
echo render('Hello {{ name }}!', array('name' => 'Fabien'));
echo render(
file_get_contents(__DIR__.'/template.php'),
array('name' => 'Fabien')
);
function render($template, $arguments)
{
$evaluator = function ($match) use ($arguments)
{
if (isset($arguments[$match[1]])) {
return $arguments[$match[1]];
}
return $match[1];
};
return preg_replace_callback('/{{s*(.+?)s*}}/',
$evaluator, $template);
}
Dependency Injector
http://www.flickr.com/photos/revivaling/4978942907
http://www.picoinjector.org/injection.html
« Dependency Injection is where components
are given their dependencies
through their constructors, methods, or directly into fields »
In most web applications, you need to manage the user preferences
–  The user language
–  Whether the user is authenticated or not
–  …
This can be done with a User object
–  setLanguage(), getLanguage()
–  setAuthenticated(), isAuthenticated()
–  …
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()
{
$this->storage = new SessionStorage();
}
function setLanguage($language)
{
$this->storage->set('language', $language);
}
// ...
}
$user = new User();
Very easy
to use
Very hard to
customize
class User
{
protected $storage;
function __construct($storage)
{
$this->storage = $storage;
}
}
$storage = new SessionStorage();
$user = new User($storage);
Slightly more
difficult to use
Very easy to
customize
That’s Dependency Injection
Nothing more
Instead of harcoding
the Storage dependency
inside the User class constructor
Inject the Storage dependency
in the User object
A Dependency Injector
Describes objects
and their dependencies
Instantiates and configures
objects on-demand
An injector
SHOULD be able to manage
ANY PHP object (POPO)
The objects MUST not know
that they are managed
by the injector
•  Parameters
–  The SessionStorage implementation we want to use (the class name)
–  The session name
•  Objects
–  SessionStorage
–  User
•  Dependencies
–  User depends on a SessionStorage implementation
Let’s build a simple injector
with PHP 5.3
http://www.flickr.com/photos/22750018@N05/4531762220/
Dependency Injector: Parameters
http://www.flickr.com/photos/revivaling/4979546964
class Injector
{
protected $parameters = array();
public function setParameter($key, $value)
{
$this->parameters[$key] = $value;
}
public function getParameter($key)
{
return $this->parameters[$key];
}
}
$injector = new Injector();
$injector->setParameter('session_name', 'SESSION_ID');
$injector->setParameter('storage_class', 'SessionStorage');
$class = $injector->getParameter('storage_class');
$sessionStorage = new $class($injector->getParameter('session_name'));
$user = new User($sessionStorage);
Decoupling
Customization
Objects creation
class Injector
{
protected $parameters = array();
public function __set($key, $value)
{
$this->parameters[$key] = $value;
}
public function __get($key)
{
return $this->parameters[$key];
}
}
Using PHP
magic methods
$injector = new Injector();
$injector->session_name = 'SESSION_ID';
$injector->storage_class = 'SessionStorage';
$sessionStorage = new $injector->storage_class($injector->session_name);
$user = new User($sessionStorage);
Interface
is cleaner
Dependency Injector: Objects
http://www.flickr.com/photos/revivaling/4979547636
We need a way to describe how to create objects,
without actually instantiating anything!
Anonymous functions to the rescue!
class Injector
{
protected $parameters = array();
protected $objects = array();
public function __set($key, $value)
{
$this->parameters[$key] = $value;
}
public function __get($key)
{
return $this->parameters[$key];
}
public function setService($key, Closure $service)
{
$this->objects[$key] = $service;
}
public function getService($key)
{
return $this->objects[$key]($this);
}
}
Store a lambda
able to create the
object on-demand
Ask the closure to create
the object and pass the
current injector
$injector = new Injector();
$injector->session_name = 'SESSION_ID';
$injector->storage_class = 'SessionStorage';
$injector->setService('user', function ($c)
{
return new User($c->getService('storage'));
});
$injector->setService('storage', function ($c)
{
return new $c->storage_class($c->session_name);
});
$user = $injector->getService('user');
Creating the User
is now as easy as before
Description
class Injector
{
protected $values = array();
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];
}
}
}
Simplify the code
$injector = new Injector();
$injector->session_name = 'SESSION_ID';
$injector->storage_class = 'SessionStorage';
$injector->user = function ($c)
{
return new User($c->storage);
};
$injector->storage = function ($c)
{
return new $c->storage_class($c->session_name);
};
$user = $injector->user;
Unified interface
Dependency Injector: Scope
http://www.flickr.com/photos/revivaling/4979545016
For some objects, like the user,
the injector must always
return the same instance
spl_object_hash($injector->user)
!==
spl_object_hash($injector->user)
$injector->user = function ($c)
{
static $user;
if (is_null($user)) {
$user = new User($c->storage);
}
return $user;
};
spl_object_hash($injector->user)
===
spl_object_hash($injector->user)
$injector->user = $injector->asShared(function ($c)
{
return new User($c->storage);
});
function asShared(Closure $lambda)
{
return function ($injector) use ($lambda)
{
static $object;
if (is_null($object)) {
$object = $lambda($injector);
}
return $object;
};
}
class Injector
{
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];
}
}
}
Error management
class Injector
{
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)
{
return function ($c) use ($callable)
{
static $object;
if (is_null($object)) {
$object = $callable($c);
}
return $object;
};
}
}
40 LOC for a fully-
featured injector
Twittee: A Dependency Injection 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
Anonymous Functions
Closures
Late Static Binding
__invoke()
…
I’m NOT advocating
the usage of lambdas everywhere
This presentation was about
showing how they work
on practical examples
Questions?
Design patterns revisited with PHP 5.3
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/
Interlude
…Anonymous Functions
http://www.flickr.com/photos/gregory_bastien/2565132371
An anonymous function
is a function
defined on the fly (no name)
function () { echo 'Hello world!'; };
Can be stored in a variable
$hello = function () { echo 'Hello world!'; };
… to be used later on
$hello();
call_user_func($hello);
… or can be passed as a function argument
function foo(Closure $func)
{
$func();
}
foo($hello);
Fonctions anonymes
$hello = function ($name) { echo 'Hello '.$name; };
$hello('Fabien');
call_user_func($hello, 'Fabien');
Can take arguments
Fonctions anonymes
function foo(Closure $func, $name)
{
$func($name);
}
foo($hello, 'Fabien');
When is it useful?
array_*
Greatly simplify usage of some array_* functions
array_map()
array_reduce()
array_filter()
class Article
{
public function __construct($title)
{
$this->title = $title;
}
public function getTitle()
{
return $this->title;
}
}
How to get an array of all article titles?
$articles = array(
new Article('PHP UK - part 1'),
new Article('PHP UK - part 2'),
new Article('See you next year!'),
);
$titles = array();
foreach ($articles as $article)
{
$titles[] = $article->getTitle();
}
$titles = array_map(
create_function('$article', 'return $article->getTitle();'),
$articles
);
$titles = array_map(
function ($article) { return $article->getTitle(); },
$articles
);
$titles = array();
foreach ($articles as $article)
{
$titles[] = $article->getTitle();
}
100100
$titles = array_map(create_function('$article', 'return $article->getTitle();'), $articles);
1800300
$titles = array_map(function ($article) { return $article->getTitle(); }, $articles);
200100
memory speed
$mapper = function ($article) { return $article->getTitle(); };
$titles = array_map($mapper, $articles);
180100
$mapper = function ($article) {
return $article->getTitle();
};
$titles = array_map($mapper, $articles);
$mapper = function ($article) {
return $article->getAuthor();
};
$authors = array_map($mapper, $articles);
A closure is a lambda
that remembers the context
of its creation…
$mapper = function ($method)
{
return function ($article) use($method)
{
return $article->$method();
};
};
$method = 'getTitle';
$mapper = function ($article) use($method)
{
return $article->$method();
};
$method = 'getAuthor';
$titles = array_map($mapper, $articles);
$titleMapper = $mapper('getTitle');
$titles = array_map($titleMapper, $articles);
$authorMapper = $mapper('getAuthor');
$authors = array_map($authorMapper, $articles);
$titles = array_map($mapper('getTitle'), $articles);
$authors = array_map($mapper('getAuthor'), $articles);

More Related Content

What's hot (20)

PPTX
Laravel 5
Sudip Simkhada
 
PDF
Introduction To Django (Strange Loop 2011)
Jacob Kaplan-Moss
 
KEY
Mobile HTML, CSS, and JavaScript
franksvalli
 
PDF
Building Content Types with Dexterity
David Glick
 
PDF
Dexterity in the Wild
David Glick
 
PDF
Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...
Matt Raible
 
PDF
Developing Modern Java Web Applications with Java EE 7 and AngularJS
Shekhar Gulati
 
PPT
Apache Ant
Rajesh Kumar
 
PPTX
Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi
 
KEY
Overlays, Accordions & Tabs, Oh My
Steve McMahon
 
PPT
Apache Ant
hussulinux
 
PDF
Intro To JavaScript Unit Testing - Ran Mizrahi
Ran Mizrahi
 
PDF
Mobile Open Day: React Native: Crossplatform fast dive
epamspb
 
PPTX
The Django Web Application Framework 2
fishwarter
 
PDF
Twig: Friendly Curly Braces Invade Your Templates!
Ryan Weaver
 
PDF
Metaprogramming JavaScript
danwrong
 
PPTX
Creating a Plug-In Architecture
ondrejbalas
 
PDF
The Naked Bundle - Symfony Live London 2014
Matthias Noback
 
PPT
Ant - Another Neat Tool
Kanika2885
 
PPT
Intoduction to Play Framework
Knoldus Inc.
 
Laravel 5
Sudip Simkhada
 
Introduction To Django (Strange Loop 2011)
Jacob Kaplan-Moss
 
Mobile HTML, CSS, and JavaScript
franksvalli
 
Building Content Types with Dexterity
David Glick
 
Dexterity in the Wild
David Glick
 
Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...
Matt Raible
 
Developing Modern Java Web Applications with Java EE 7 and AngularJS
Shekhar Gulati
 
Apache Ant
Rajesh Kumar
 
Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi
 
Overlays, Accordions & Tabs, Oh My
Steve McMahon
 
Apache Ant
hussulinux
 
Intro To JavaScript Unit Testing - Ran Mizrahi
Ran Mizrahi
 
Mobile Open Day: React Native: Crossplatform fast dive
epamspb
 
The Django Web Application Framework 2
fishwarter
 
Twig: Friendly Curly Braces Invade Your Templates!
Ryan Weaver
 
Metaprogramming JavaScript
danwrong
 
Creating a Plug-In Architecture
ondrejbalas
 
The Naked Bundle - Symfony Live London 2014
Matthias Noback
 
Ant - Another Neat Tool
Kanika2885
 
Intoduction to Play Framework
Knoldus Inc.
 

Viewers also liked (20)

ODP
Object Oriented Design Patterns for PHP
RobertGonzalez
 
PDF
Common design patterns in php
David Stockton
 
PDF
PHP 5.3 in practice
Fabien Potencier
 
PDF
Design patterns in PHP - PHP TEAM
Nishant Shrivastava
 
PDF
Your first 5 PHP design patterns - ThatConference 2012
Aaron Saray
 
PDF
Design patterns in PHP
Jason Straughan
 
PDF
Varnish
Fabien Potencier
 
KEY
Object Oriented CSS
Nicole Sullivan
 
PDF
Dependency injection in PHP 5.3/5.4
Fabien Potencier
 
PDF
The state of Symfony2 - SymfonyDay 2010
Fabien Potencier
 
PDF
Symfony2 - OSIDays 2010
Fabien Potencier
 
PDF
Dependency injection - phpday 2010
Fabien Potencier
 
KEY
PHP security audits
Damien Seguy
 
PDF
Continuous Improvement in PHP projects
Mayflower GmbH
 
PPT
Go OO! - Real-life Design Patterns in PHP 5
Stephan Schmidt
 
PDF
Refactoring
Artem Tabalin
 
PDF
Mondongo, un ODM para PHP y MongoDB
pablodip
 
PDF
Database version control without pain - the PHP Barcelona version
Harrie Verveer
 
PPTX
Introduction to Twitter's Bootstrap 2
Julien Renaux
 
PDF
News of the Symfony2 World
Fabien Potencier
 
Object Oriented Design Patterns for PHP
RobertGonzalez
 
Common design patterns in php
David Stockton
 
PHP 5.3 in practice
Fabien Potencier
 
Design patterns in PHP - PHP TEAM
Nishant Shrivastava
 
Your first 5 PHP design patterns - ThatConference 2012
Aaron Saray
 
Design patterns in PHP
Jason Straughan
 
Object Oriented CSS
Nicole Sullivan
 
Dependency injection in PHP 5.3/5.4
Fabien Potencier
 
The state of Symfony2 - SymfonyDay 2010
Fabien Potencier
 
Symfony2 - OSIDays 2010
Fabien Potencier
 
Dependency injection - phpday 2010
Fabien Potencier
 
PHP security audits
Damien Seguy
 
Continuous Improvement in PHP projects
Mayflower GmbH
 
Go OO! - Real-life Design Patterns in PHP 5
Stephan Schmidt
 
Refactoring
Artem Tabalin
 
Mondongo, un ODM para PHP y MongoDB
pablodip
 
Database version control without pain - the PHP Barcelona version
Harrie Verveer
 
Introduction to Twitter's Bootstrap 2
Julien Renaux
 
News of the Symfony2 World
Fabien Potencier
 
Ad

Similar to Design patterns revisited with PHP 5.3 (20)

PDF
Demystifying Object-Oriented Programming #phpbnl18
Alena Holligan
 
PDF
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
Enterprise PHP Center
 
PDF
Design attern in php
Filippo De Santis
 
PDF
PHP: 4 Design Patterns to Make Better Code
SWIFTotter Solutions
 
PDF
What's New In Laravel 5
Darren Craig
 
PPTX
Intro to OOP PHP and Github
Jo Erik San Jose
 
ODP
Best practices tekx
Lorna Mitchell
 
PDF
Osiąganie mądrej architektury z Symfony2
3camp
 
PDF
Demystifying Object-Oriented Programming - ZendCon 2016
Alena Holligan
 
PDF
Drupaljam xl 2019 presentation multilingualism makes better programmers
Alexander Varwijk
 
KEY
Workshop quality assurance for php projects tek12
Michelangelo van Dam
 
PDF
Beyond symfony 1.2 (Symfony Camp 2008)
Fabien Potencier
 
PDF
Demystifying Object-Oriented Programming - PHP[tek] 2017
Alena Holligan
 
PPT
CICON2010: Adam Griffiths - CodeIgniter 2
CodeIgniter Conference
 
PDF
10 PHP Design Patterns #burningkeyboards
Denis Ristic
 
PDF
OOP in PHP
Tarek Mahmud Apu
 
PDF
Lean Php Presentation
Alan Pinstein
 
PPTX
Only oop
anitarooge
 
PDF
TYPO3 Flow 2.0 (International PHP Conference 2013)
Robert Lemke
 
PDF
Demystifying Object-Oriented Programming - Lone Star PHP
Alena Holligan
 
Demystifying Object-Oriented Programming #phpbnl18
Alena Holligan
 
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
Enterprise PHP Center
 
Design attern in php
Filippo De Santis
 
PHP: 4 Design Patterns to Make Better Code
SWIFTotter Solutions
 
What's New In Laravel 5
Darren Craig
 
Intro to OOP PHP and Github
Jo Erik San Jose
 
Best practices tekx
Lorna Mitchell
 
Osiąganie mądrej architektury z Symfony2
3camp
 
Demystifying Object-Oriented Programming - ZendCon 2016
Alena Holligan
 
Drupaljam xl 2019 presentation multilingualism makes better programmers
Alexander Varwijk
 
Workshop quality assurance for php projects tek12
Michelangelo van Dam
 
Beyond symfony 1.2 (Symfony Camp 2008)
Fabien Potencier
 
Demystifying Object-Oriented Programming - PHP[tek] 2017
Alena Holligan
 
CICON2010: Adam Griffiths - CodeIgniter 2
CodeIgniter Conference
 
10 PHP Design Patterns #burningkeyboards
Denis Ristic
 
OOP in PHP
Tarek Mahmud Apu
 
Lean Php Presentation
Alan Pinstein
 
Only oop
anitarooge
 
TYPO3 Flow 2.0 (International PHP Conference 2013)
Robert Lemke
 
Demystifying Object-Oriented Programming - Lone Star PHP
Alena Holligan
 
Ad

More from Fabien Potencier (20)

PDF
Look beyond PHP
Fabien Potencier
 
PDF
Dependency injection-zendcon-2010
Fabien Potencier
 
PDF
Caching on the Edge
Fabien Potencier
 
PDF
PhpBB meets Symfony2
Fabien Potencier
 
PDF
Symfony2 - WebExpo 2010
Fabien Potencier
 
PDF
Symfony2 - WebExpo 2010
Fabien Potencier
 
PDF
Dependency Injection IPC 201
Fabien Potencier
 
PDF
Caching on the Edge with Symfony2
Fabien Potencier
 
PDF
Unit and Functional Testing with Symfony2
Fabien Potencier
 
PDF
Dependency Injection - ConFoo 2010
Fabien Potencier
 
PDF
Dependency Injection
Fabien Potencier
 
PDF
Symfony Components
Fabien Potencier
 
PDF
Symfony2 revealed
Fabien Potencier
 
PDF
Dependency Injection with PHP 5.3
Fabien Potencier
 
PDF
Dependency Injection with PHP and PHP 5.3
Fabien Potencier
 
PDF
Symfony Components 2.0 on PHP 5.3
Fabien Potencier
 
PDF
Playing With PHP 5.3
Fabien Potencier
 
PDF
Symfony 2.0 on PHP 5.3
Fabien Potencier
 
PDF
Symfony2 San Francisco Meetup 2009
Fabien Potencier
 
PDF
Symfony And Zend Framework Together 2009
Fabien Potencier
 
Look beyond PHP
Fabien Potencier
 
Dependency injection-zendcon-2010
Fabien Potencier
 
Caching on the Edge
Fabien Potencier
 
PhpBB meets Symfony2
Fabien Potencier
 
Symfony2 - WebExpo 2010
Fabien Potencier
 
Symfony2 - WebExpo 2010
Fabien Potencier
 
Dependency Injection IPC 201
Fabien Potencier
 
Caching on the Edge with Symfony2
Fabien Potencier
 
Unit and Functional Testing with Symfony2
Fabien Potencier
 
Dependency Injection - ConFoo 2010
Fabien Potencier
 
Dependency Injection
Fabien Potencier
 
Symfony Components
Fabien Potencier
 
Symfony2 revealed
Fabien Potencier
 
Dependency Injection with PHP 5.3
Fabien Potencier
 
Dependency Injection with PHP and PHP 5.3
Fabien Potencier
 
Symfony Components 2.0 on PHP 5.3
Fabien Potencier
 
Playing With PHP 5.3
Fabien Potencier
 
Symfony 2.0 on PHP 5.3
Fabien Potencier
 
Symfony2 San Francisco Meetup 2009
Fabien Potencier
 
Symfony And Zend Framework Together 2009
Fabien Potencier
 

Recently uploaded (20)

PPTX
OpenID AuthZEN - Analyst Briefing July 2025
David Brossard
 
PPTX
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
DOCX
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
PDF
What Makes Contify’s News API Stand Out: Key Features at a Glance
Contify
 
PPTX
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
PDF
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
PDF
Transforming Utility Networks: Large-scale Data Migrations with FME
Safe Software
 
PDF
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
PDF
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
PDF
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
PDF
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
PDF
“NPU IP Hardware Shaped Through Software and Use-case Analysis,” a Presentati...
Edge AI and Vision Alliance
 
PDF
Advancing WebDriver BiDi support in WebKit
Igalia
 
PDF
LOOPS in C Programming Language - Technology
RishabhDwivedi43
 
PPTX
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 
PPTX
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
PDF
Transcript: New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
DOCX
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
PDF
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
PDF
"AI Transformation: Directions and Challenges", Pavlo Shaternik
Fwdays
 
OpenID AuthZEN - Analyst Briefing July 2025
David Brossard
 
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
What Makes Contify’s News API Stand Out: Key Features at a Glance
Contify
 
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
Transforming Utility Networks: Large-scale Data Migrations with FME
Safe Software
 
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
“NPU IP Hardware Shaped Through Software and Use-case Analysis,” a Presentati...
Edge AI and Vision Alliance
 
Advancing WebDriver BiDi support in WebKit
Igalia
 
LOOPS in C Programming Language - Technology
RishabhDwivedi43
 
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
Transcript: New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
"AI Transformation: Directions and Challenges", Pavlo Shaternik
Fwdays
 

Design patterns revisited with PHP 5.3