SlideShare uma empresa Scribd logo
1 de 105
Baixar para ler offline
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. »
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?
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);

Mais conteúdo relacionado

Mais procurados

sekuensial sercing (data string) dalam C++
sekuensial sercing (data string) dalam C++sekuensial sercing (data string) dalam C++
sekuensial sercing (data string) dalam C++Sandy Suherman
 
Form penilaian teman sejawat
Form penilaian teman sejawatForm penilaian teman sejawat
Form penilaian teman sejawatBP4K
 
Modul belajar-spss-1
Modul belajar-spss-1Modul belajar-spss-1
Modul belajar-spss-1in_ndah
 
Konsep e learning
Konsep e learningKonsep e learning
Konsep e learningBungaCN
 
Materi bahan ajar e modul hakikat teknologi pendidikan
Materi bahan ajar e modul hakikat teknologi pendidikanMateri bahan ajar e modul hakikat teknologi pendidikan
Materi bahan ajar e modul hakikat teknologi pendidikanfachriadelisutia
 
Membuat Video Pembelajaran dengan Canva.pptx
Membuat Video Pembelajaran dengan Canva.pptxMembuat Video Pembelajaran dengan Canva.pptx
Membuat Video Pembelajaran dengan Canva.pptxAhmadNaufalUmam1
 
Eksitu insitu
Eksitu insituEksitu insitu
Eksitu insituIvho Stia
 
Sequential Search
Sequential SearchSequential Search
Sequential SearchPutra Andry
 
Mendesain Tujuan Pembelajaran (SK,KD, Indikator) menentukan media yg sesuai
Mendesain Tujuan Pembelajaran (SK,KD, Indikator) menentukan media yg sesuai Mendesain Tujuan Pembelajaran (SK,KD, Indikator) menentukan media yg sesuai
Mendesain Tujuan Pembelajaran (SK,KD, Indikator) menentukan media yg sesuai 4sharemidwifery
 
Metodologi penelitian.ppt (2)
Metodologi penelitian.ppt (2)Metodologi penelitian.ppt (2)
Metodologi penelitian.ppt (2)Budionno Abdulloh
 

Mais procurados (20)

sekuensial sercing (data string) dalam C++
sekuensial sercing (data string) dalam C++sekuensial sercing (data string) dalam C++
sekuensial sercing (data string) dalam C++
 
Ppt discovery learning
Ppt discovery learning Ppt discovery learning
Ppt discovery learning
 
PPT KOTLIN DASAR.pptx
PPT KOTLIN DASAR.pptxPPT KOTLIN DASAR.pptx
PPT KOTLIN DASAR.pptx
 
Ctf del upload
Ctf del uploadCtf del upload
Ctf del upload
 
Form penilaian teman sejawat
Form penilaian teman sejawatForm penilaian teman sejawat
Form penilaian teman sejawat
 
Modul belajar-spss-1
Modul belajar-spss-1Modul belajar-spss-1
Modul belajar-spss-1
 
Pembelajaran Multimedia
Pembelajaran MultimediaPembelajaran Multimedia
Pembelajaran Multimedia
 
Konsep e learning
Konsep e learningKonsep e learning
Konsep e learning
 
Kel2 PTK.pptx
Kel2 PTK.pptxKel2 PTK.pptx
Kel2 PTK.pptx
 
queue antrian
queue antrianqueue antrian
queue antrian
 
Materi bahan ajar e modul hakikat teknologi pendidikan
Materi bahan ajar e modul hakikat teknologi pendidikanMateri bahan ajar e modul hakikat teknologi pendidikan
Materi bahan ajar e modul hakikat teknologi pendidikan
 
Membuat Video Pembelajaran dengan Canva.pptx
Membuat Video Pembelajaran dengan Canva.pptxMembuat Video Pembelajaran dengan Canva.pptx
Membuat Video Pembelajaran dengan Canva.pptx
 
Eksitu insitu
Eksitu insituEksitu insitu
Eksitu insitu
 
Struktur Data Tree
Struktur Data TreeStruktur Data Tree
Struktur Data Tree
 
Sequential Search
Sequential SearchSequential Search
Sequential Search
 
Mendesain Tujuan Pembelajaran (SK,KD, Indikator) menentukan media yg sesuai
Mendesain Tujuan Pembelajaran (SK,KD, Indikator) menentukan media yg sesuai Mendesain Tujuan Pembelajaran (SK,KD, Indikator) menentukan media yg sesuai
Mendesain Tujuan Pembelajaran (SK,KD, Indikator) menentukan media yg sesuai
 
Design Thinking
Design ThinkingDesign Thinking
Design Thinking
 
Metodologi penelitian.ppt (2)
Metodologi penelitian.ppt (2)Metodologi penelitian.ppt (2)
Metodologi penelitian.ppt (2)
 
Tugas imk hta
Tugas imk htaTugas imk hta
Tugas imk hta
 
Metodologi Penelitian Pertemuan 1
Metodologi Penelitian Pertemuan 1Metodologi Penelitian Pertemuan 1
Metodologi Penelitian Pertemuan 1
 

Destaque

Object Oriented Design Patterns for PHP
Object Oriented Design Patterns for PHPObject Oriented Design Patterns for PHP
Object Oriented Design Patterns for PHPRobertGonzalez
 
Common design patterns in php
Common design patterns in phpCommon design patterns in php
Common design patterns in phpDavid Stockton
 
Design patterns in PHP - PHP TEAM
Design patterns in PHP - PHP TEAMDesign patterns in PHP - PHP TEAM
Design patterns in PHP - PHP TEAMNishant Shrivastava
 
Your first 5 PHP design patterns - ThatConference 2012
Your first 5 PHP design patterns - ThatConference 2012Your first 5 PHP design patterns - ThatConference 2012
Your first 5 PHP design patterns - ThatConference 2012Aaron Saray
 
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
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010Fabien Potencier
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010Fabien Potencier
 
PHP security audits
PHP security auditsPHP security audits
PHP security auditsDamien Seguy
 
Continuous Improvement in PHP projects
Continuous Improvement in PHP projectsContinuous Improvement in PHP projects
Continuous Improvement in PHP projectsMayflower GmbH
 
Go OO! - Real-life Design Patterns in PHP 5
Go OO! - Real-life Design Patterns in PHP 5Go OO! - Real-life Design Patterns in PHP 5
Go OO! - Real-life Design Patterns in PHP 5Stephan Schmidt
 
Mondongo, un ODM para PHP y MongoDB
Mondongo, un ODM para PHP y MongoDBMondongo, un ODM para PHP y MongoDB
Mondongo, un ODM para PHP y MongoDBpablodip
 
Database version control without pain - the PHP Barcelona version
Database version control without pain - the PHP Barcelona versionDatabase version control without pain - the PHP Barcelona version
Database version control without pain - the PHP Barcelona versionHarrie Verveer
 
Introduction to Twitter's Bootstrap 2
Introduction to Twitter's Bootstrap 2Introduction to Twitter's Bootstrap 2
Introduction to Twitter's Bootstrap 2Julien Renaux
 
News of the Symfony2 World
News of the Symfony2 WorldNews of the Symfony2 World
News of the Symfony2 WorldFabien Potencier
 

Destaque (20)

Object Oriented Design Patterns for PHP
Object Oriented Design Patterns for PHPObject Oriented Design Patterns for PHP
Object Oriented Design Patterns for PHP
 
Common design patterns in php
Common design patterns in phpCommon design patterns in php
Common design patterns in php
 
PHP 5.3 in practice
PHP 5.3 in practicePHP 5.3 in practice
PHP 5.3 in practice
 
Design patterns in PHP - PHP TEAM
Design patterns in PHP - PHP TEAMDesign patterns in PHP - PHP TEAM
Design patterns in PHP - PHP TEAM
 
Your first 5 PHP design patterns - ThatConference 2012
Your first 5 PHP design patterns - ThatConference 2012Your first 5 PHP design patterns - ThatConference 2012
Your first 5 PHP design patterns - ThatConference 2012
 
Design patterns in PHP
Design patterns in PHPDesign patterns in PHP
Design patterns in PHP
 
Varnish
VarnishVarnish
Varnish
 
Object Oriented CSS
Object Oriented CSSObject Oriented CSS
Object Oriented CSS
 
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
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010
 
Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010
 
PHP security audits
PHP security auditsPHP security audits
PHP security audits
 
Continuous Improvement in PHP projects
Continuous Improvement in PHP projectsContinuous Improvement in PHP projects
Continuous Improvement in PHP projects
 
Go OO! - Real-life Design Patterns in PHP 5
Go OO! - Real-life Design Patterns in PHP 5Go OO! - Real-life Design Patterns in PHP 5
Go OO! - Real-life Design Patterns in PHP 5
 
Refactoring
RefactoringRefactoring
Refactoring
 
Mondongo, un ODM para PHP y MongoDB
Mondongo, un ODM para PHP y MongoDBMondongo, un ODM para PHP y MongoDB
Mondongo, un ODM para PHP y MongoDB
 
Database version control without pain - the PHP Barcelona version
Database version control without pain - the PHP Barcelona versionDatabase version control without pain - the PHP Barcelona version
Database version control without pain - the PHP Barcelona version
 
Introduction to Twitter's Bootstrap 2
Introduction to Twitter's Bootstrap 2Introduction to Twitter's Bootstrap 2
Introduction to Twitter's Bootstrap 2
 
News of the Symfony2 World
News of the Symfony2 WorldNews of the Symfony2 World
News of the Symfony2 World
 

Semelhante a Design patterns revisited with PHP 5.3

Demystifying Object-Oriented Programming #phpbnl18
Demystifying Object-Oriented Programming #phpbnl18Demystifying Object-Oriented Programming #phpbnl18
Demystifying Object-Oriented Programming #phpbnl18Alena Holligan
 
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur PurnamaEPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur PurnamaEnterprise PHP Center
 
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
 
What's New In Laravel 5
What's New In Laravel 5What's New In Laravel 5
What's New In Laravel 5Darren Craig
 
Intro to OOP PHP and Github
Intro to OOP PHP and GithubIntro to OOP PHP and Github
Intro to OOP PHP and GithubJo Erik San Jose
 
Osiąganie mądrej architektury z Symfony2
Osiąganie mądrej architektury z Symfony2 Osiąganie mądrej architektury z Symfony2
Osiąganie mądrej architektury z Symfony2 3camp
 
Demystifying Object-Oriented Programming - ZendCon 2016
Demystifying Object-Oriented Programming - ZendCon 2016Demystifying Object-Oriented Programming - ZendCon 2016
Demystifying Object-Oriented Programming - ZendCon 2016Alena Holligan
 
Drupaljam xl 2019 presentation multilingualism makes better programmers
Drupaljam xl 2019 presentation   multilingualism makes better programmersDrupaljam xl 2019 presentation   multilingualism makes better programmers
Drupaljam xl 2019 presentation multilingualism makes better programmersAlexander Varwijk
 
Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Michelangelo van Dam
 
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
 
Demystifying Object-Oriented Programming - PHP[tek] 2017
Demystifying Object-Oriented Programming - PHP[tek] 2017Demystifying Object-Oriented Programming - PHP[tek] 2017
Demystifying Object-Oriented Programming - PHP[tek] 2017Alena Holligan
 
CICON2010: Adam Griffiths - CodeIgniter 2
CICON2010: Adam Griffiths - CodeIgniter 2CICON2010: Adam Griffiths - CodeIgniter 2
CICON2010: Adam Griffiths - CodeIgniter 2CodeIgniter Conference
 
10 PHP Design Patterns #burningkeyboards
10 PHP Design Patterns #burningkeyboards10 PHP Design Patterns #burningkeyboards
10 PHP Design Patterns #burningkeyboardsDenis Ristic
 
Lean Php Presentation
Lean Php PresentationLean Php Presentation
Lean Php PresentationAlan Pinstein
 
TYPO3 Flow 2.0 (International PHP Conference 2013)
TYPO3 Flow 2.0 (International PHP Conference 2013)TYPO3 Flow 2.0 (International PHP Conference 2013)
TYPO3 Flow 2.0 (International PHP Conference 2013)Robert Lemke
 
Demystifying Object-Oriented Programming - Lone Star PHP
Demystifying Object-Oriented Programming - Lone Star PHPDemystifying Object-Oriented Programming - Lone Star PHP
Demystifying Object-Oriented Programming - Lone Star PHPAlena Holligan
 

Semelhante a Design patterns revisited with PHP 5.3 (20)

Demystifying Object-Oriented Programming #phpbnl18
Demystifying Object-Oriented Programming #phpbnl18Demystifying Object-Oriented Programming #phpbnl18
Demystifying Object-Oriented Programming #phpbnl18
 
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur PurnamaEPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
 
Design attern in php
Design attern in phpDesign attern in php
Design attern in php
 
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
 
What's New In Laravel 5
What's New In Laravel 5What's New In Laravel 5
What's New In Laravel 5
 
Intro to OOP PHP and Github
Intro to OOP PHP and GithubIntro to OOP PHP and Github
Intro to OOP PHP and Github
 
Best practices tekx
Best practices tekxBest practices tekx
Best practices tekx
 
Osiąganie mądrej architektury z Symfony2
Osiąganie mądrej architektury z Symfony2 Osiąganie mądrej architektury z Symfony2
Osiąganie mądrej architektury z Symfony2
 
Demystifying Object-Oriented Programming - ZendCon 2016
Demystifying Object-Oriented Programming - ZendCon 2016Demystifying Object-Oriented Programming - ZendCon 2016
Demystifying Object-Oriented Programming - ZendCon 2016
 
Drupaljam xl 2019 presentation multilingualism makes better programmers
Drupaljam xl 2019 presentation   multilingualism makes better programmersDrupaljam xl 2019 presentation   multilingualism makes better programmers
Drupaljam xl 2019 presentation multilingualism makes better programmers
 
Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12
 
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)
 
Demystifying Object-Oriented Programming - PHP[tek] 2017
Demystifying Object-Oriented Programming - PHP[tek] 2017Demystifying Object-Oriented Programming - PHP[tek] 2017
Demystifying Object-Oriented Programming - PHP[tek] 2017
 
CICON2010: Adam Griffiths - CodeIgniter 2
CICON2010: Adam Griffiths - CodeIgniter 2CICON2010: Adam Griffiths - CodeIgniter 2
CICON2010: Adam Griffiths - CodeIgniter 2
 
10 PHP Design Patterns #burningkeyboards
10 PHP Design Patterns #burningkeyboards10 PHP Design Patterns #burningkeyboards
10 PHP Design Patterns #burningkeyboards
 
OOP in PHP
OOP in PHPOOP in PHP
OOP in PHP
 
Lean Php Presentation
Lean Php PresentationLean Php Presentation
Lean Php Presentation
 
Only oop
Only oopOnly oop
Only oop
 
TYPO3 Flow 2.0 (International PHP Conference 2013)
TYPO3 Flow 2.0 (International PHP Conference 2013)TYPO3 Flow 2.0 (International PHP Conference 2013)
TYPO3 Flow 2.0 (International PHP Conference 2013)
 
Demystifying Object-Oriented Programming - Lone Star PHP
Demystifying Object-Oriented Programming - Lone Star PHPDemystifying Object-Oriented Programming - Lone Star PHP
Demystifying Object-Oriented Programming - Lone Star PHP
 

Mais de Fabien Potencier

Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Fabien Potencier
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201Fabien Potencier
 
Caching on the Edge with Symfony2
Caching on the Edge with Symfony2Caching on the Edge with Symfony2
Caching on the Edge with Symfony2Fabien Potencier
 
Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Fabien Potencier
 
Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Fabien Potencier
 
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 with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3Fabien Potencier
 
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.3Fabien Potencier
 
Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009Fabien Potencier
 
Symfony And Zend Framework Together 2009
Symfony And Zend Framework Together 2009Symfony And Zend Framework Together 2009
Symfony And Zend Framework Together 2009Fabien Potencier
 

Mais de Fabien Potencier (20)

Look beyond PHP
Look beyond PHPLook beyond PHP
Look beyond PHP
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010
 
Caching on the Edge
Caching on the EdgeCaching on the Edge
Caching on the Edge
 
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
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
 
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
 
Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Symfony Components
Symfony ComponentsSymfony Components
Symfony Components
 
Symfony2 revealed
Symfony2 revealedSymfony2 revealed
Symfony2 revealed
 
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 with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3
 
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
 

Último

The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 

Último (20)

The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 

Design patterns revisited with PHP 5.3