SlideShare ist ein Scribd-Unternehmen logo
1 von 71
Downloaden Sie, um offline zu lesen
Dependency Injection for PHP
Mike Toppa
Boston PHP Meetup
September 9, 2015
@mtoppapokayoke.design
About me
@mtoppapokayoke.design
* I’ve been developing for the web since the days of HTML 1.0, when web pages were first painted on cave walls.
* I’ve been developing with PHP since 2004.
* Over the years I’ve worked at Ask Jeeves, E-Trade, Stanford, Georgetown, and I was the Director of the Web Applications Team at the U Penn School of
Medicine.
* Most of my work has been as a developer, but I’ve also done a good deal of project management and team management, and I’m a big believer in
Agile and Lean practices.
My new house near Boston…
@mtoppapokayoke.design
* I just moved to Boston from Philadelphia this summer

* and the is what my house looks like
@mtoppapokayoke.design
* My wife has a new job here in Boston, and I have a new job now too. I’m co-founder and CTO of Poka Yoke Design. Our primary development platforms are
WordPress and Ruby on Rails.

* I was an active member of the PHP, WordPress, and Ruby communities in Philly, and I look forward to becoming part of the communities here in Boston.

* We are not hiring currently, but we are looking for projects!
Overview
1. Crash course in classes and objects in PHP
2. The SOLID principles
• Single Responsibility Principle
• Dependency Inversion Principle
3. Class autoloading in PHP
4. Dependency injection
• DI containers
• Advanced dependency injection techniques
@mtoppapokayoke.design
1. Crash course in classes and
objects in PHP
@mtoppapokayoke.design
@mtoppapokayoke.design
Simple example
class Lamp {
// property declaration
private $maxSafeWatts = 100;
// method declaration
public function getMaxSafeWatts() {
return $this->maxSafeWatts;
}
}
---------------------------------------------------------------
// instantiate and assign
$myLamp = new Lamp();
echo $myLamp->getMaxSafeWatts();
A class consists of properties, and methods which perform actions, by manipulating those properties
Encapsulation of related methods and properties. This is what a class really is.
Properties and methods have a visibility (public, private, or protected)
An object is created by instantiating a class (calling new). Then you typically assign it to a variable, and call its methods as needed
Rule of thumb:

avoid public properties
class Lamp {
public $maxSafeWatts = 100;
}
---------------------------------------------
$myLamp = new Lamp();
// dangerous to allow this!
$myLamp->maxSafeWatts = 'a string to wreck your math';
Public properties can be used and abused by external code at any time.
Prefer private properties
class Lamp {
private $maxSafeWatts = 100;
public setMaxSafeWatts($watts) {
if (!is_numeric($watts) || $watts > 125 || $watts < 1) {
throw New Exception('invalid value for watts');
}
$this->maxSafeWatts = $watts;
return $this->maxSafeWatts;
}
}
-------------------------------------------------------------------
$myLamp = new Lamp();
$myLamp->setMaxSafeWatts(75);
By requiring them to be set through a method call, you can control what types of values are valid, and what ranges are valid.
Constructors
class Lamp {
private $bulb;
public function __construct($bulb) {
$this->bulb = $bulb;
}
}
---------------------------------------------
$myLamp = new Lamp('3 way');
The constructor is a special method, used for initializing a class.
It's optional – is called when you call “new”
A constructor does not return anything
It should be used for getting a class into a valid initial state
A common design mistake is to put a lot of complex logic in the constructor, or call it to execute the object's functionality.
Type Hinting
class Lamp {
private $bulb;
public function __construct(Bulb $bulb) {
$this->bulb = $bulb;
}
}
---------------------------------------------
$myBulb = new Bulb();
$myLamp = new Lamp($bulb);
Organizing your classes
One class per file, and the file name should match the class name
Give the class a meaningful name and its methods meaningful names
Class names and property names should be nouns or noun phrases
Method names should be verbs or verb phrases
Use an IDE that autocompletes variable names and method names
Abstract classes and inheritance
Lamp
DeskLampFloorLamp HangingLamp
Abstract classes and methods
abstract class Lamp {
protected $color;
protected $maxSafeWatts;
public function setColor($color) {
$this->color = $color;
return $this->color;
}
abstract public function setMaxSafeWatts($watts);
}
An abstract class cannot be implemented directly
It can also have abstract methods, which must be implemented by the child class
Protected methods and properties are essentially private, but can be used by child classes
Implementing abstract classes
class FloorLamp extends Lamp {
public function setMaxSafeWatts($watts) {
/* if numeric and less than 150... */
$this->maxSafeWatts = $watts;
return $this->maxSafeWatts;
}
}
------------------------------------------------------------------
class DeskLamp extends Lamp {
public function setMaxSafeWatts($watts) {
/* if numeric and less than 100... */
$this->maxSafeWatts = $watts;
return $this->maxSafeWatts;
}
}
Interfaces
An electrical outlet is a great example of an interface. It can power anything designed to plug into it. It doesn't need to know or care about exactly what it's connected to.
Interfaces define a set of methods a class must implement. It's similar to abstract classes in this way, but there is no inheritance.
I’ll provide an example and say more about interfaces when we get to dependency inversion
2. The SOLID Principles
● Single Responsibility (SRP)
● Open-Closed (OCP)
● Liskov Substitution (LSP)
● Interface Segregation (ISP)
● Dependency Inversion (DIP)
@mtoppapokayoke.design
Introduced by Bob Martin in his book “Agile Software Development”
From LosTechies.com
* Applied to classes and methods
* Do one thing, do it well, do it only
* For methods, this typically means changing the value of only one variable
* If you are passing more than 2 or 3 arguments into a method, you are probably doing more than one thing
* For classes, it means having a single conceptual responsibility
The purpose is to reduce the
complexity and fragility
of a class
@mtoppapokayoke.design
We want code that is flexible and easy to understand, not brittle and mind-numbing to read
When a method is manipulating multiple properties and invoking lots of other methods, it can be very hard to test, debug, and change. This is a common reason why developers feel fear
when making a change – they don't know what might break
When a class has many methods and multiple responsibilities, it can be hard to understand and difficult to refactor
But what does it mean to do “one thing”?
@mtoppapokayoke.design
Only one reason to change
@mtoppapokayoke.design
If you have a class that compiles and prints a report, it has 2 responsibilities, and 2 reasons to change. The content of the report could change, or the format of the report could change.
This class should be split into two classes.
Cohesion
@mtoppapokayoke.design
Uncle Bob says:

* “Classes should have a small number of instance variables. Each of the methods of a class should manipulate one or more of those variables. In general the more
variables a method manipulates the more cohesive that method is to its class.”

* “When cohesion is high, it means that the methods and variables of the class are co-dependent and hang together as a logical whole.”
SRP violation example
@mtoppapokayoke.design
Shashin
@mtoppapokayoke.design
My WordPress plugin for displaying albums,
photos, and videos from Picasa, Twitpic, and
YouTube
I'm going to show SRP and DIP examples of code from Shashin
Clean code books and articles all use other languages as examples – I wanted to try applying them to PHP and WordPress
Shashin supports multiple viewers
There's a lot going on here. A lot of different data sources and display possibilities to support. How do you keep the code from becoming a tangled mess?
@mtoppapokayoke.design
Shashin consists of 44 classes, each of which
has a meaningful name, follows the SRP, and
“does one thing”
PicasaPhotoDisplayer
SettingsMenu
YouTubeSynchronizer
Uninstall
etc.
Displayer.php
AlbumDisplayer.php
AlbumDisplayerPicasa.php
AlbumDisplayerTwitpic.php
AlbumDisplayerFlickr.php
PhotoDisplayer.php
PhotoDisplayerPicasa.php
PhotoDisplayerTwitpic.php
PhotoDisplayerFlickr.php
Shashin Classes Example
You can start to see the power of this approach here
I can add support for a new photos service by creating a new subclass, instead of having to touch code all over the place, adding a bunch of “if” statements
class Installer {
public function run() {
$this->createAlbumTable();
$this->verifyAlbumTable();
$this->createPhotoTable();
$this->verifyPhotoTable();
$this->updateSettings();
return true;
}
// ...
}
Methods Example
* The whole class is about 150 lines
*The run method calls the other methods (this is a simple use of the command pattern)
*It reads like a table of contents
*Breaking the functionality down into methods that do one thing makes the code easier to read and to unit test
*Installation is especially useful to break down into small methods that can have automated tests, as plugin activation is especially difficult to debug
From LosTechies.com
The next question is, how do we get all these objects working together?
It’s common to see code that hard-wires together all the parts, when those connections could be made more flexible and extensible
Some definitions of the DIP
● Abstractions should not depend on details
● Code should depend on things that are at the
same or higher level of abstraction
● High level policy should not depend on low level
details
● Capture low-level dependencies in domain-
relevant abstractions
● Uh, ok…?
Definitions from DIP in the wild
Naïve model of a button and lamp
Button
+ poll()
Lamp
+ turnOn()
+ turnOff()
class Button {
private $lamp;
public function __construct(Lamp $lamp) {
$this->lamp = $lamp;
}
public function poll() {
if (/* some condition */) {
$this->lamp->turnOn();
}
}
} Example from Bob Martin's book
“Agile Software Development”
This solution violates the DIP
● Button depends directly on Lamp
● Changes to Lamp may require changes to Button
● Button is not reusable
● It can't control, for example, a Motor
● The high level abstraction is missing
● “the truths that do not vary when the details are changed”
● “To detect an on/off gesture from a user and relay that gesture to a target object”
Dependency inversion applied
Button
+ poll()
<<interface>>
SwitchableDevice
+ turnOn()
+ turnOff()
Lamp
This is the Abstract Server pattern
What it means:
*Neither Button nor Lamp “own” the interface
*Buttons can now control any device that implements SwitchableDevice
*Lamps and other SwitchableDevices can now be controlled by any object that accepts a SwitchableDevice
interface SwitchableDevice {
public function turnOn();
public function turnOff();
}
class Lamp implements SwitchableDevice {
public function turnOn() {
// code
}
public function turnOff() {
// code
}
}
class Button {
private $switchableDevice;
public function __construct(SwitchableDevice $switchableDevice) {
$this->switchableDevice = $switchableDevice;
}
public function poll() {
if (/* some condition */) {
$this->switchableDevice->turnOn();
}
}
}
We’ve made only a small change to Button, but it’s a powerful one
A web of collaborating objects
● The SRP and DIP together drive a
“composition” approach to OO design
● From Growing Object Oriented Software,
Guided by Tests:
"An object oriented system is a web of
collaborating objects... The behavior of the
system is an emergent property of the
composition of the objects - the choice of objects
and how they are connected... Thinking of a
system in terms of its dynamic communication
structure is a significant mental shift from the
static classification that most of us learn when
being introduced to objects."
Author: Steve Freeman and Nat Pryce
@mtoppapokayoke.design
Composition
(“Has a...”)
vs.
Inheritance
(“Is a...”)
@mtoppapokayoke.design
The SRP is about objects that do one thing
The DIP is about how to wire them together
to create working, flexible software
@mtoppapokayoke.design
3. Class autoloading: the problem
● How do we include the class files we’ll need in our
project?
● PHP lacks an equivalent statement to “import” or “use”
for classes
● Having to hardcode a bunch of file paths for loading
classes is extra work, and makes code harder to
change
@mtoppapokayoke.design
Class autoloading: the solution
● PHP 5.1.2 and spl_autoload_register()
● PHP 5.3 and support for namespaces
● PHP Standards Working Group: PSR-4
● http://www.php-fig.org/psr/psr-4/
* spl_autoloader_register allows you to register a function that will be called when PHP encounters a “new” call, for finding and including the file containing the class.
*you can map namespaces to folders
*PSR-4 provides an agreed upon convention for how to do it
@mtoppapokayoke.design
when you type this:
new ShashinAdminInstaller;
the Shashin autoloader will load this:
/path/to/shashin/Admin/Installer.php
PSR-4 Example
@mtoppapokayoke.design
// simplified version of code in Shashin’s initialization script
require_once dirname(__FILE__) . '/lib/ShashinAutoLoader.php'
new ShashinAutoLoader();
// that's it! I can now call “new” on any Shashin class
// and its class file will be automatically loaded
Shashin Autoloader
@mtoppapokayoke.design
Dependency injection…
Dependency inversion…
What’s the difference?
4. Dependency Injection
Naïve button & lamp model revisited
Button
+ poll()
Lamp
+ turnOn()
+ turnOff()
class Button {
private $lamp;
public function __construct(Lamp $lamp) {
$this->lamp = $lamp;
}
public function poll() {
if (/* some condition */) {
$this->lamp->turnOn();
}
}
}
● This solution violates the DIP, but it’s still doing dependency injection
● You can apply the DIP using dependency injection
● There are also other techniques for applying the DIP: Factory pattern, adapter pattern, service locator pattern
class Button {
private $lamp;
public function __construct() {
$this->lamp = new Lamp();
}
//...
}
Never, ever do this
* There was one thing that was ok in the naïve example – we were at least passing in the lamp object
*Instantiating it directly in the class makes your code harder to unit test. When unit testing we want to test the method’s logic in isolation, and not get involved with the actual behavior of
other classes it uses.
*When we bury these references in our code, it becomes hard to see what our collaborators are.
public function __construct(SwitchableDevice $switchableDevice) {
$this->switchableDevice = $switchableDevice;
}
Constructor injection
public function setSwitchableDevice(SwitchableDevice $switchableDevice) {
$this->switchableDevice = $switchableDevice;
}
Setter injection
@mtoppapokayoke.design
Which to use?
It depends
● Constructor injection gives you a valid object, with all its dependencies, upon construction
● But constructor injection becomes hard to read and use when there are more than a few objects to inject
● More about this in an upcoming slide...
@mtoppapokayoke.design
If class A depends on class B,
and class B depends on class C,
class A should be blissfully unaware of class C
Dependency chains
We want loose coupling, not a rigid chain of dependencies that is hard to change
@mtoppapokayoke.design
To do this without going insane,
you need an injection container
class Container {
// …
public function getPhotoRefData() {
if (!isset($this->photoRefData)) {
$this->photoRefData = new ShashinLibPhotoRefData();
}
return $this->photoRefData;
}
public function getClonablePhoto() {
if (!isset($this->clonablePhoto)) {
$this->getPhotoRefData();
$this->clonablePhoto = new ShashinLibPhoto($this->photoRefData);
}
return $this->clonablePhoto;
}
Example from Shashin
I am making the objects properties of the container, because they happen to be immutable objects, so they are reusable
You can see I'm using constructor injection
I'll explain in a minute why I called it a “clonable” photo
public function getClonablePhotoCollection() {
if (!isset($this->photoCollection)) {
$this->getClonablePhoto();
$this->getSettings();
$this->clonablePhotoCollection = new Lib_ShashinPhotoCollection();
$this->clonablePhotoCollection->setClonableDataObject($this->clonablePhoto);
$this->clonablePhotoCollection->setSettings($this->settings);
}
return $this->clonablePhotoCollection;
}
Example continued
Start with constructor injection
As your design evolves, switch to setter injection once there are more than 2 objects to inject
If you rely on an injection container, you don't have to worry about forgetting to call a required setter
@mtoppapokayoke.design
Beyond the textbook examples
@mtoppapokayoke.design
What to do when you need
a new object inside a loop
One solution is cloning
class SynchronizerPicasa extends Synchronizer {
// setClonablePhoto method…
public function syncAlbumPhotos(array $decodedAlbumData) {
// …
foreach ($decodedAlbumData['feed']['entry'] as $entry) {
$photoData = $this->extractFieldsFromDecodedData(
$entry, $photoRefData, ‘picasa'
);
// ...
$photo = clone $this->clonablePhoto;
$photo->set($photoData);
$photo->flush();
}
Shashin Example
@mtoppapokayoke.design
What if you need a new object inside a loop,
but can't know the subtype you'll need
ahead of time?
Let the injection container figure it out
This was an interesting problem for me with Shashin. It supports multiple media sources (Picasa, etc), multiple viewers (Fancybox, etc), and we could be displaying a photo or an album
cover, each of which has different behaviors
class LayoutManager {
// setContainer method…
public function setTableBody() {
// …
for ($i = 0; $i < count($this->collection); $i++) {
// ...
$dataObjectDisplayer = $this->container->getDataObjectDisplayer(
$this->shortcode,
$this->collection[$i]
);
$this->tableBody .= $dataObjectDisplayer->run();
// ...
}
Shashin Example
Regardless of the type, the layout rules for the thumbnails is always the same
So here I've injected the container itself
getDataObjectDisplayer() uses the passed in
arguments to determine which subtype of
DataObjectDisplayer to return
class Container {
// …
public function getDataObjectDisplayer( //… ) {
// …
$dataObjectClassName = get_class($dataObject); // ShashinPhoto

$albumType = ucfirst($dataObject->albumType); // Picasa

$classToCall = $dataObjectClassName . 'Displayer' . $albumType;

$dataObjectDisplayer = new $classToCall();
// …
return $dataObjectDisplayer; // ShashinPhotoDisplayerPicasa

}
Shashin Example
Off-the-shelf injection containers
• PHP-DI
• SymfonyDependencyInjection
• ZendDi
• OrnoDi
• Dice
• Aura.Di
• Pimple
• More info and performance analyses
* If you want to try one, start with Dice. It’s lightweight and easy to understand. It does “auto-wiring” by using reflection. It relies on type hinting in your method
signatures.

* Others have you use configuration files, annotations, or PHP code to describe dependencies.
@mtoppapokayoke.design
Off-the-shelf or roll your own?
* Using reflection is great for simple cases

* Using configurations, you can end up with as much code as simply writing your own

* I prefer writing my own. It’s not hard, and I can customize the behavior however I like without having to fight against the conventions of a pre-built container (like the
getDataObjectDisplayer method)
@mtoppapokayoke.design
Dependency injection: key benefits
● Makes your objects flexible
● Can work with anything that supports the
expected interface
● Decreases coupling, which promotes
reusability, testability and maintainability
● With an injection container, simplifies managing
dependency chains
Button and lamp….
But don't overdo it:

avoid needless complexity
The complexity of having 44 classes in Shashin is justified by its need for flexibility
You can support a new viewer or a new photo service simply by creating a new subclass. This is much more maintainable and extensible than a single huge file with deeply nested
conditionals and unclear dependencies
But if I knew I would never need that kind of flexibility, there would be no justification for creating these layers of abstraction – they would just be needless complexity
Questions?

Weitere ähnliche Inhalte

Was ist angesagt?

JavaScript and EPUB: Making interactive ebooks - Christina Truong - ebookcraf...
JavaScript and EPUB: Making interactive ebooks - Christina Truong - ebookcraf...JavaScript and EPUB: Making interactive ebooks - Christina Truong - ebookcraf...
JavaScript and EPUB: Making interactive ebooks - Christina Truong - ebookcraf...BookNet Canada
 
"SOLID" Object Oriented Design Principles
"SOLID" Object Oriented Design Principles"SOLID" Object Oriented Design Principles
"SOLID" Object Oriented Design PrinciplesSerhiy Oplakanets
 
25 php interview questions – codementor
25 php interview questions – codementor25 php interview questions – codementor
25 php interview questions – codementorArc & Codementor
 
Stop wasting-time-by-applying-clean-code-principles
Stop wasting-time-by-applying-clean-code-principlesStop wasting-time-by-applying-clean-code-principles
Stop wasting-time-by-applying-clean-code-principlesEdorian
 
Introjs10.5.17SD
Introjs10.5.17SDIntrojs10.5.17SD
Introjs10.5.17SDThinkful
 
Writing Readable Code
Writing Readable CodeWriting Readable Code
Writing Readable Codeeddiehaber
 
What does OOP stand for?
What does OOP stand for?What does OOP stand for?
What does OOP stand for?Colin Riley
 
S.O.L.I.D. Principles for Software Architects
S.O.L.I.D. Principles for Software ArchitectsS.O.L.I.D. Principles for Software Architects
S.O.L.I.D. Principles for Software ArchitectsRicardo Wilkins
 
Going native with html5 web components
Going native with html5 web componentsGoing native with html5 web components
Going native with html5 web componentsJames York
 
Survey on Script-based languages to write a Chatbot
Survey on Script-based languages to write a ChatbotSurvey on Script-based languages to write a Chatbot
Survey on Script-based languages to write a ChatbotNguyen Giang
 
Ood and solid principles
Ood and solid principlesOod and solid principles
Ood and solid principlesAvinash Kadam
 
How I Learned to Stop Worrying and Love Legacy Code - Ox:Agile 2018
How I Learned to Stop Worrying and Love Legacy Code - Ox:Agile 2018How I Learned to Stop Worrying and Love Legacy Code - Ox:Agile 2018
How I Learned to Stop Worrying and Love Legacy Code - Ox:Agile 2018Mike Harris
 
C++ 11 Style : A Touch of Class
C++ 11 Style : A Touch of ClassC++ 11 Style : A Touch of Class
C++ 11 Style : A Touch of ClassYogendra Rampuria
 
Theming in WordPress - Where do I Start?
Theming in WordPress - Where do I Start?Theming in WordPress - Where do I Start?
Theming in WordPress - Where do I Start?Edmund Turbin
 
How to write good quality code
How to write good quality codeHow to write good quality code
How to write good quality codeHayden Bleasel
 
Clean Code I - Best Practices
Clean Code I - Best PracticesClean Code I - Best Practices
Clean Code I - Best PracticesTheo Jungeblut
 
Scalable front-end architecture with Bootstrap 3 + Atomic CSS
Scalable front-end architecture with Bootstrap 3 + Atomic CSSScalable front-end architecture with Bootstrap 3 + Atomic CSS
Scalable front-end architecture with Bootstrap 3 + Atomic CSSHayden Bleasel
 

Was ist angesagt? (19)

JavaScript and EPUB: Making interactive ebooks - Christina Truong - ebookcraf...
JavaScript and EPUB: Making interactive ebooks - Christina Truong - ebookcraf...JavaScript and EPUB: Making interactive ebooks - Christina Truong - ebookcraf...
JavaScript and EPUB: Making interactive ebooks - Christina Truong - ebookcraf...
 
"SOLID" Object Oriented Design Principles
"SOLID" Object Oriented Design Principles"SOLID" Object Oriented Design Principles
"SOLID" Object Oriented Design Principles
 
25 php interview questions – codementor
25 php interview questions – codementor25 php interview questions – codementor
25 php interview questions – codementor
 
Stop wasting-time-by-applying-clean-code-principles
Stop wasting-time-by-applying-clean-code-principlesStop wasting-time-by-applying-clean-code-principles
Stop wasting-time-by-applying-clean-code-principles
 
Introjs10.5.17SD
Introjs10.5.17SDIntrojs10.5.17SD
Introjs10.5.17SD
 
Writing Readable Code
Writing Readable CodeWriting Readable Code
Writing Readable Code
 
What does OOP stand for?
What does OOP stand for?What does OOP stand for?
What does OOP stand for?
 
S.O.L.I.D. Principles for Software Architects
S.O.L.I.D. Principles for Software ArchitectsS.O.L.I.D. Principles for Software Architects
S.O.L.I.D. Principles for Software Architects
 
Going native with html5 web components
Going native with html5 web componentsGoing native with html5 web components
Going native with html5 web components
 
Survey on Script-based languages to write a Chatbot
Survey on Script-based languages to write a ChatbotSurvey on Script-based languages to write a Chatbot
Survey on Script-based languages to write a Chatbot
 
Backend roadmap
Backend roadmapBackend roadmap
Backend roadmap
 
Ood and solid principles
Ood and solid principlesOod and solid principles
Ood and solid principles
 
Performance Tuning with XHProf
Performance Tuning with XHProfPerformance Tuning with XHProf
Performance Tuning with XHProf
 
How I Learned to Stop Worrying and Love Legacy Code - Ox:Agile 2018
How I Learned to Stop Worrying and Love Legacy Code - Ox:Agile 2018How I Learned to Stop Worrying and Love Legacy Code - Ox:Agile 2018
How I Learned to Stop Worrying and Love Legacy Code - Ox:Agile 2018
 
C++ 11 Style : A Touch of Class
C++ 11 Style : A Touch of ClassC++ 11 Style : A Touch of Class
C++ 11 Style : A Touch of Class
 
Theming in WordPress - Where do I Start?
Theming in WordPress - Where do I Start?Theming in WordPress - Where do I Start?
Theming in WordPress - Where do I Start?
 
How to write good quality code
How to write good quality codeHow to write good quality code
How to write good quality code
 
Clean Code I - Best Practices
Clean Code I - Best PracticesClean Code I - Best Practices
Clean Code I - Best Practices
 
Scalable front-end architecture with Bootstrap 3 + Atomic CSS
Scalable front-end architecture with Bootstrap 3 + Atomic CSSScalable front-end architecture with Bootstrap 3 + Atomic CSS
Scalable front-end architecture with Bootstrap 3 + Atomic CSS
 

Ähnlich wie Dependency Injection for PHP

Object oreinted php | OOPs
Object oreinted php | OOPsObject oreinted php | OOPs
Object oreinted php | OOPsRavi Bhadauria
 
Object Oriented Programming for WordPress Plugin Development
Object Oriented Programming for WordPress Plugin DevelopmentObject Oriented Programming for WordPress Plugin Development
Object Oriented Programming for WordPress Plugin Developmentmtoppa
 
Oops concepts in php
Oops concepts in phpOops concepts in php
Oops concepts in phpCPD INDIA
 
Lecture-10_PHP-OOP.pptx
Lecture-10_PHP-OOP.pptxLecture-10_PHP-OOP.pptx
Lecture-10_PHP-OOP.pptxShaownRoy1
 
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
 
Intro Java Rev010
Intro Java Rev010Intro Java Rev010
Intro Java Rev010Rich Helton
 
PHP OOP Lecture - 02.pptx
PHP OOP Lecture - 02.pptxPHP OOP Lecture - 02.pptx
PHP OOP Lecture - 02.pptxAtikur Rahman
 
Bring the fun back to java
Bring the fun back to javaBring the fun back to java
Bring the fun back to javaciklum_ods
 
Learn java
Learn javaLearn java
Learn javaPalahuja
 
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
 
Take the Plunge with OOP from #pnwphp
Take the Plunge with OOP from #pnwphpTake the Plunge with OOP from #pnwphp
Take the Plunge with OOP from #pnwphpAlena Holligan
 
Javascript for the c# developer
Javascript for the c# developerJavascript for the c# developer
Javascript for the c# developerSalvatore Fazio
 
Basic Oops concept of PHP
Basic Oops concept of PHPBasic Oops concept of PHP
Basic Oops concept of PHPRohan Sharma
 
OOPS IN PHP.pptx
OOPS IN PHP.pptxOOPS IN PHP.pptx
OOPS IN PHP.pptxrani marri
 
Demystifying Object-Oriented Programming #phpbnl18
Demystifying Object-Oriented Programming #phpbnl18Demystifying Object-Oriented Programming #phpbnl18
Demystifying Object-Oriented Programming #phpbnl18Alena Holligan
 

Ähnlich wie Dependency Injection for PHP (20)

Object oreinted php | OOPs
Object oreinted php | OOPsObject oreinted php | OOPs
Object oreinted php | OOPs
 
Object Oriented Programming for WordPress Plugin Development
Object Oriented Programming for WordPress Plugin DevelopmentObject Oriented Programming for WordPress Plugin Development
Object Oriented Programming for WordPress Plugin Development
 
Only oop
Only oopOnly oop
Only oop
 
Oop's in php
Oop's in php Oop's in php
Oop's in php
 
Oops concepts in php
Oops concepts in phpOops concepts in php
Oops concepts in php
 
Lecture-10_PHP-OOP.pptx
Lecture-10_PHP-OOP.pptxLecture-10_PHP-OOP.pptx
Lecture-10_PHP-OOP.pptx
 
Oops in PHP
Oops in PHPOops in PHP
Oops in PHP
 
Intro to OOP PHP and Github
Intro to OOP PHP and GithubIntro to OOP PHP and Github
Intro to OOP PHP and Github
 
Intro Java Rev010
Intro Java Rev010Intro Java Rev010
Intro Java Rev010
 
PHP OOP Lecture - 02.pptx
PHP OOP Lecture - 02.pptxPHP OOP Lecture - 02.pptx
PHP OOP Lecture - 02.pptx
 
Bring the fun back to java
Bring the fun back to javaBring the fun back to java
Bring the fun back to java
 
Oops in php
Oops in phpOops in php
Oops in php
 
Learn java
Learn javaLearn java
Learn java
 
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
 
Take the Plunge with OOP from #pnwphp
Take the Plunge with OOP from #pnwphpTake the Plunge with OOP from #pnwphp
Take the Plunge with OOP from #pnwphp
 
Javascript for the c# developer
Javascript for the c# developerJavascript for the c# developer
Javascript for the c# developer
 
Introduction Php
Introduction PhpIntroduction Php
Introduction Php
 
Basic Oops concept of PHP
Basic Oops concept of PHPBasic Oops concept of PHP
Basic Oops concept of PHP
 
OOPS IN PHP.pptx
OOPS IN PHP.pptxOOPS IN PHP.pptx
OOPS IN PHP.pptx
 
Demystifying Object-Oriented Programming #phpbnl18
Demystifying Object-Oriented Programming #phpbnl18Demystifying Object-Oriented Programming #phpbnl18
Demystifying Object-Oriented Programming #phpbnl18
 

Mehr von mtoppa

RubyConf 2022 - From beginner to expert, and back again
RubyConf 2022 - From beginner to expert, and back againRubyConf 2022 - From beginner to expert, and back again
RubyConf 2022 - From beginner to expert, and back againmtoppa
 
RailsConf 2022 - Upgrading Rails: The Dual Boot Way
RailsConf 2022 - Upgrading Rails: The Dual Boot WayRailsConf 2022 - Upgrading Rails: The Dual Boot Way
RailsConf 2022 - Upgrading Rails: The Dual Boot Waymtoppa
 
Applying Omotenashi (Japanese customer service) to your work
Applying Omotenashi (Japanese customer service) to your workApplying Omotenashi (Japanese customer service) to your work
Applying Omotenashi (Japanese customer service) to your workmtoppa
 
Talking to strangers causes train wrecks
Talking to strangers causes train wrecksTalking to strangers causes train wrecks
Talking to strangers causes train wrecksmtoppa
 
A11Y? I18N? L10N? UTF8? WTF? Understanding the connections between: accessib...
A11Y? I18N? L10N? UTF8? WTF? Understanding the connections between:  accessib...A11Y? I18N? L10N? UTF8? WTF? Understanding the connections between:  accessib...
A11Y? I18N? L10N? UTF8? WTF? Understanding the connections between: accessib...mtoppa
 
The promise and peril of Agile and Lean practices
The promise and peril of Agile and Lean practicesThe promise and peril of Agile and Lean practices
The promise and peril of Agile and Lean practicesmtoppa
 
Why do planes crash? Lessons for junior and senior developers
Why do planes crash? Lessons for junior and senior developersWhy do planes crash? Lessons for junior and senior developers
Why do planes crash? Lessons for junior and senior developersmtoppa
 
Boston Ruby Meetup: The promise and peril of Agile and Lean practices
Boston Ruby Meetup: The promise and peril of Agile and Lean practicesBoston Ruby Meetup: The promise and peril of Agile and Lean practices
Boston Ruby Meetup: The promise and peril of Agile and Lean practicesmtoppa
 
A real-life overview of Agile and Scrum
A real-life overview of Agile and ScrumA real-life overview of Agile and Scrum
A real-life overview of Agile and Scrummtoppa
 
WordCamp Nashville 2016: The promise and peril of Agile and Lean practices
WordCamp Nashville 2016: The promise and peril of Agile and Lean practicesWordCamp Nashville 2016: The promise and peril of Agile and Lean practices
WordCamp Nashville 2016: The promise and peril of Agile and Lean practicesmtoppa
 
WordCamp Boston 2015: Agile Contracts for WordPress Consultants
WordCamp Boston 2015: Agile Contracts for WordPress ConsultantsWordCamp Boston 2015: Agile Contracts for WordPress Consultants
WordCamp Boston 2015: Agile Contracts for WordPress Consultantsmtoppa
 
WordCamp Nashville 2015: Agile Contracts for WordPress Consultants
WordCamp Nashville 2015: Agile Contracts for WordPress ConsultantsWordCamp Nashville 2015: Agile Contracts for WordPress Consultants
WordCamp Nashville 2015: Agile Contracts for WordPress Consultantsmtoppa
 
Rails testing: factories or fixtures?
Rails testing: factories or fixtures?Rails testing: factories or fixtures?
Rails testing: factories or fixtures?mtoppa
 
WordCamp Lancaster 2014: A11Y? I18N? L10N? UTF8? WTF?
WordCamp Lancaster 2014: A11Y? I18N? L10N? UTF8? WTF?WordCamp Lancaster 2014: A11Y? I18N? L10N? UTF8? WTF?
WordCamp Lancaster 2014: A11Y? I18N? L10N? UTF8? WTF?mtoppa
 
WordCamp Nashville: Clean Code for WordPress
WordCamp Nashville: Clean Code for WordPressWordCamp Nashville: Clean Code for WordPress
WordCamp Nashville: Clean Code for WordPressmtoppa
 
A real-life overview of Agile workflow practices
A real-life overview of Agile workflow practicesA real-life overview of Agile workflow practices
A real-life overview of Agile workflow practicesmtoppa
 
Why Agile? Why Now?
Why Agile? Why Now?Why Agile? Why Now?
Why Agile? Why Now?mtoppa
 
Dependency Injection for Wordpress
Dependency Injection for WordpressDependency Injection for Wordpress
Dependency Injection for Wordpressmtoppa
 
Clean code for WordPress
Clean code for WordPressClean code for WordPress
Clean code for WordPressmtoppa
 
Dependency Inversion and Dependency Injection in PHP
Dependency Inversion and Dependency Injection in PHPDependency Inversion and Dependency Injection in PHP
Dependency Inversion and Dependency Injection in PHPmtoppa
 

Mehr von mtoppa (20)

RubyConf 2022 - From beginner to expert, and back again
RubyConf 2022 - From beginner to expert, and back againRubyConf 2022 - From beginner to expert, and back again
RubyConf 2022 - From beginner to expert, and back again
 
RailsConf 2022 - Upgrading Rails: The Dual Boot Way
RailsConf 2022 - Upgrading Rails: The Dual Boot WayRailsConf 2022 - Upgrading Rails: The Dual Boot Way
RailsConf 2022 - Upgrading Rails: The Dual Boot Way
 
Applying Omotenashi (Japanese customer service) to your work
Applying Omotenashi (Japanese customer service) to your workApplying Omotenashi (Japanese customer service) to your work
Applying Omotenashi (Japanese customer service) to your work
 
Talking to strangers causes train wrecks
Talking to strangers causes train wrecksTalking to strangers causes train wrecks
Talking to strangers causes train wrecks
 
A11Y? I18N? L10N? UTF8? WTF? Understanding the connections between: accessib...
A11Y? I18N? L10N? UTF8? WTF? Understanding the connections between:  accessib...A11Y? I18N? L10N? UTF8? WTF? Understanding the connections between:  accessib...
A11Y? I18N? L10N? UTF8? WTF? Understanding the connections between: accessib...
 
The promise and peril of Agile and Lean practices
The promise and peril of Agile and Lean practicesThe promise and peril of Agile and Lean practices
The promise and peril of Agile and Lean practices
 
Why do planes crash? Lessons for junior and senior developers
Why do planes crash? Lessons for junior and senior developersWhy do planes crash? Lessons for junior and senior developers
Why do planes crash? Lessons for junior and senior developers
 
Boston Ruby Meetup: The promise and peril of Agile and Lean practices
Boston Ruby Meetup: The promise and peril of Agile and Lean practicesBoston Ruby Meetup: The promise and peril of Agile and Lean practices
Boston Ruby Meetup: The promise and peril of Agile and Lean practices
 
A real-life overview of Agile and Scrum
A real-life overview of Agile and ScrumA real-life overview of Agile and Scrum
A real-life overview of Agile and Scrum
 
WordCamp Nashville 2016: The promise and peril of Agile and Lean practices
WordCamp Nashville 2016: The promise and peril of Agile and Lean practicesWordCamp Nashville 2016: The promise and peril of Agile and Lean practices
WordCamp Nashville 2016: The promise and peril of Agile and Lean practices
 
WordCamp Boston 2015: Agile Contracts for WordPress Consultants
WordCamp Boston 2015: Agile Contracts for WordPress ConsultantsWordCamp Boston 2015: Agile Contracts for WordPress Consultants
WordCamp Boston 2015: Agile Contracts for WordPress Consultants
 
WordCamp Nashville 2015: Agile Contracts for WordPress Consultants
WordCamp Nashville 2015: Agile Contracts for WordPress ConsultantsWordCamp Nashville 2015: Agile Contracts for WordPress Consultants
WordCamp Nashville 2015: Agile Contracts for WordPress Consultants
 
Rails testing: factories or fixtures?
Rails testing: factories or fixtures?Rails testing: factories or fixtures?
Rails testing: factories or fixtures?
 
WordCamp Lancaster 2014: A11Y? I18N? L10N? UTF8? WTF?
WordCamp Lancaster 2014: A11Y? I18N? L10N? UTF8? WTF?WordCamp Lancaster 2014: A11Y? I18N? L10N? UTF8? WTF?
WordCamp Lancaster 2014: A11Y? I18N? L10N? UTF8? WTF?
 
WordCamp Nashville: Clean Code for WordPress
WordCamp Nashville: Clean Code for WordPressWordCamp Nashville: Clean Code for WordPress
WordCamp Nashville: Clean Code for WordPress
 
A real-life overview of Agile workflow practices
A real-life overview of Agile workflow practicesA real-life overview of Agile workflow practices
A real-life overview of Agile workflow practices
 
Why Agile? Why Now?
Why Agile? Why Now?Why Agile? Why Now?
Why Agile? Why Now?
 
Dependency Injection for Wordpress
Dependency Injection for WordpressDependency Injection for Wordpress
Dependency Injection for Wordpress
 
Clean code for WordPress
Clean code for WordPressClean code for WordPress
Clean code for WordPress
 
Dependency Inversion and Dependency Injection in PHP
Dependency Inversion and Dependency Injection in PHPDependency Inversion and Dependency Injection in PHP
Dependency Inversion and Dependency Injection in PHP
 

Kürzlich hochgeladen

2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shardsChristopher Curtin
 
Mastering Project Planning with Microsoft Project 2016.pptx
Mastering Project Planning with Microsoft Project 2016.pptxMastering Project Planning with Microsoft Project 2016.pptx
Mastering Project Planning with Microsoft Project 2016.pptxAS Design & AST.
 
Effectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorEffectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorTier1 app
 
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...OnePlan Solutions
 
What’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 UpdatesWhat’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 UpdatesVictoriaMetrics
 
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...Bert Jan Schrijver
 
Advantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptxAdvantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptxRTS corp
 
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...kalichargn70th171
 
Zer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdfZer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdfmaor17
 
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdfSteve Caron
 
Ronisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited CatalogueRonisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited Catalogueitservices996
 
Osi security architecture in network.pptx
Osi security architecture in network.pptxOsi security architecture in network.pptx
Osi security architecture in network.pptxVinzoCenzo
 
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdfAndrey Devyatkin
 
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...OnePlan Solutions
 
Introduction to Firebase Workshop Slides
Introduction to Firebase Workshop SlidesIntroduction to Firebase Workshop Slides
Introduction to Firebase Workshop Slidesvaideheekore1
 
eSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration toolseSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration toolsosttopstonverter
 
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingOpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingShane Coughlan
 
Best Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh ITBest Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh ITmanoharjgpsolutions
 
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics
 
Strategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsStrategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsJean Silva
 

Kürzlich hochgeladen (20)

2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards
 
Mastering Project Planning with Microsoft Project 2016.pptx
Mastering Project Planning with Microsoft Project 2016.pptxMastering Project Planning with Microsoft Project 2016.pptx
Mastering Project Planning with Microsoft Project 2016.pptx
 
Effectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorEffectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryError
 
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
 
What’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 UpdatesWhat’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 Updates
 
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
 
Advantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptxAdvantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptx
 
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
 
Zer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdfZer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdf
 
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf
 
Ronisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited CatalogueRonisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited Catalogue
 
Osi security architecture in network.pptx
Osi security architecture in network.pptxOsi security architecture in network.pptx
Osi security architecture in network.pptx
 
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
 
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
 
Introduction to Firebase Workshop Slides
Introduction to Firebase Workshop SlidesIntroduction to Firebase Workshop Slides
Introduction to Firebase Workshop Slides
 
eSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration toolseSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration tools
 
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingOpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
 
Best Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh ITBest Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh IT
 
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
 
Strategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsStrategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero results
 

Dependency Injection for PHP

  • 1. Dependency Injection for PHP Mike Toppa Boston PHP Meetup September 9, 2015 @mtoppapokayoke.design
  • 2. About me @mtoppapokayoke.design * I’ve been developing for the web since the days of HTML 1.0, when web pages were first painted on cave walls. * I’ve been developing with PHP since 2004. * Over the years I’ve worked at Ask Jeeves, E-Trade, Stanford, Georgetown, and I was the Director of the Web Applications Team at the U Penn School of Medicine. * Most of my work has been as a developer, but I’ve also done a good deal of project management and team management, and I’m a big believer in Agile and Lean practices.
  • 3. My new house near Boston… @mtoppapokayoke.design * I just moved to Boston from Philadelphia this summer * and the is what my house looks like
  • 4. @mtoppapokayoke.design * My wife has a new job here in Boston, and I have a new job now too. I’m co-founder and CTO of Poka Yoke Design. Our primary development platforms are WordPress and Ruby on Rails. * I was an active member of the PHP, WordPress, and Ruby communities in Philly, and I look forward to becoming part of the communities here in Boston. * We are not hiring currently, but we are looking for projects!
  • 5. Overview 1. Crash course in classes and objects in PHP 2. The SOLID principles • Single Responsibility Principle • Dependency Inversion Principle 3. Class autoloading in PHP 4. Dependency injection • DI containers • Advanced dependency injection techniques @mtoppapokayoke.design
  • 6. 1. Crash course in classes and objects in PHP @mtoppapokayoke.design
  • 8. Simple example class Lamp { // property declaration private $maxSafeWatts = 100; // method declaration public function getMaxSafeWatts() { return $this->maxSafeWatts; } } --------------------------------------------------------------- // instantiate and assign $myLamp = new Lamp(); echo $myLamp->getMaxSafeWatts(); A class consists of properties, and methods which perform actions, by manipulating those properties Encapsulation of related methods and properties. This is what a class really is. Properties and methods have a visibility (public, private, or protected) An object is created by instantiating a class (calling new). Then you typically assign it to a variable, and call its methods as needed
  • 9. Rule of thumb:
 avoid public properties class Lamp { public $maxSafeWatts = 100; } --------------------------------------------- $myLamp = new Lamp(); // dangerous to allow this! $myLamp->maxSafeWatts = 'a string to wreck your math'; Public properties can be used and abused by external code at any time.
  • 10. Prefer private properties class Lamp { private $maxSafeWatts = 100; public setMaxSafeWatts($watts) { if (!is_numeric($watts) || $watts > 125 || $watts < 1) { throw New Exception('invalid value for watts'); } $this->maxSafeWatts = $watts; return $this->maxSafeWatts; } } ------------------------------------------------------------------- $myLamp = new Lamp(); $myLamp->setMaxSafeWatts(75); By requiring them to be set through a method call, you can control what types of values are valid, and what ranges are valid.
  • 11. Constructors class Lamp { private $bulb; public function __construct($bulb) { $this->bulb = $bulb; } } --------------------------------------------- $myLamp = new Lamp('3 way'); The constructor is a special method, used for initializing a class. It's optional – is called when you call “new” A constructor does not return anything It should be used for getting a class into a valid initial state A common design mistake is to put a lot of complex logic in the constructor, or call it to execute the object's functionality.
  • 12. Type Hinting class Lamp { private $bulb; public function __construct(Bulb $bulb) { $this->bulb = $bulb; } } --------------------------------------------- $myBulb = new Bulb(); $myLamp = new Lamp($bulb);
  • 13. Organizing your classes One class per file, and the file name should match the class name Give the class a meaningful name and its methods meaningful names Class names and property names should be nouns or noun phrases Method names should be verbs or verb phrases Use an IDE that autocompletes variable names and method names
  • 14. Abstract classes and inheritance Lamp DeskLampFloorLamp HangingLamp
  • 15. Abstract classes and methods abstract class Lamp { protected $color; protected $maxSafeWatts; public function setColor($color) { $this->color = $color; return $this->color; } abstract public function setMaxSafeWatts($watts); } An abstract class cannot be implemented directly It can also have abstract methods, which must be implemented by the child class Protected methods and properties are essentially private, but can be used by child classes
  • 16. Implementing abstract classes class FloorLamp extends Lamp { public function setMaxSafeWatts($watts) { /* if numeric and less than 150... */ $this->maxSafeWatts = $watts; return $this->maxSafeWatts; } } ------------------------------------------------------------------ class DeskLamp extends Lamp { public function setMaxSafeWatts($watts) { /* if numeric and less than 100... */ $this->maxSafeWatts = $watts; return $this->maxSafeWatts; } }
  • 17. Interfaces An electrical outlet is a great example of an interface. It can power anything designed to plug into it. It doesn't need to know or care about exactly what it's connected to. Interfaces define a set of methods a class must implement. It's similar to abstract classes in this way, but there is no inheritance. I’ll provide an example and say more about interfaces when we get to dependency inversion
  • 18. 2. The SOLID Principles ● Single Responsibility (SRP) ● Open-Closed (OCP) ● Liskov Substitution (LSP) ● Interface Segregation (ISP) ● Dependency Inversion (DIP) @mtoppapokayoke.design Introduced by Bob Martin in his book “Agile Software Development”
  • 19. From LosTechies.com * Applied to classes and methods * Do one thing, do it well, do it only * For methods, this typically means changing the value of only one variable * If you are passing more than 2 or 3 arguments into a method, you are probably doing more than one thing * For classes, it means having a single conceptual responsibility
  • 20. The purpose is to reduce the complexity and fragility of a class @mtoppapokayoke.design We want code that is flexible and easy to understand, not brittle and mind-numbing to read When a method is manipulating multiple properties and invoking lots of other methods, it can be very hard to test, debug, and change. This is a common reason why developers feel fear when making a change – they don't know what might break When a class has many methods and multiple responsibilities, it can be hard to understand and difficult to refactor
  • 21. But what does it mean to do “one thing”? @mtoppapokayoke.design
  • 22. Only one reason to change @mtoppapokayoke.design If you have a class that compiles and prints a report, it has 2 responsibilities, and 2 reasons to change. The content of the report could change, or the format of the report could change. This class should be split into two classes.
  • 23. Cohesion @mtoppapokayoke.design Uncle Bob says: * “Classes should have a small number of instance variables. Each of the methods of a class should manipulate one or more of those variables. In general the more variables a method manipulates the more cohesive that method is to its class.” * “When cohesion is high, it means that the methods and variables of the class are co-dependent and hang together as a logical whole.”
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30. Shashin @mtoppapokayoke.design My WordPress plugin for displaying albums, photos, and videos from Picasa, Twitpic, and YouTube I'm going to show SRP and DIP examples of code from Shashin Clean code books and articles all use other languages as examples – I wanted to try applying them to PHP and WordPress
  • 31.
  • 32.
  • 34. There's a lot going on here. A lot of different data sources and display possibilities to support. How do you keep the code from becoming a tangled mess?
  • 35. @mtoppapokayoke.design Shashin consists of 44 classes, each of which has a meaningful name, follows the SRP, and “does one thing” PicasaPhotoDisplayer SettingsMenu YouTubeSynchronizer Uninstall etc.
  • 36. Displayer.php AlbumDisplayer.php AlbumDisplayerPicasa.php AlbumDisplayerTwitpic.php AlbumDisplayerFlickr.php PhotoDisplayer.php PhotoDisplayerPicasa.php PhotoDisplayerTwitpic.php PhotoDisplayerFlickr.php Shashin Classes Example You can start to see the power of this approach here I can add support for a new photos service by creating a new subclass, instead of having to touch code all over the place, adding a bunch of “if” statements
  • 37. class Installer { public function run() { $this->createAlbumTable(); $this->verifyAlbumTable(); $this->createPhotoTable(); $this->verifyPhotoTable(); $this->updateSettings(); return true; } // ... } Methods Example * The whole class is about 150 lines *The run method calls the other methods (this is a simple use of the command pattern) *It reads like a table of contents *Breaking the functionality down into methods that do one thing makes the code easier to read and to unit test *Installation is especially useful to break down into small methods that can have automated tests, as plugin activation is especially difficult to debug
  • 38. From LosTechies.com The next question is, how do we get all these objects working together? It’s common to see code that hard-wires together all the parts, when those connections could be made more flexible and extensible
  • 39. Some definitions of the DIP ● Abstractions should not depend on details ● Code should depend on things that are at the same or higher level of abstraction ● High level policy should not depend on low level details ● Capture low-level dependencies in domain- relevant abstractions ● Uh, ok…? Definitions from DIP in the wild
  • 40. Naïve model of a button and lamp Button + poll() Lamp + turnOn() + turnOff() class Button { private $lamp; public function __construct(Lamp $lamp) { $this->lamp = $lamp; } public function poll() { if (/* some condition */) { $this->lamp->turnOn(); } } } Example from Bob Martin's book “Agile Software Development” This solution violates the DIP ● Button depends directly on Lamp ● Changes to Lamp may require changes to Button ● Button is not reusable ● It can't control, for example, a Motor ● The high level abstraction is missing ● “the truths that do not vary when the details are changed” ● “To detect an on/off gesture from a user and relay that gesture to a target object”
  • 41. Dependency inversion applied Button + poll() <<interface>> SwitchableDevice + turnOn() + turnOff() Lamp This is the Abstract Server pattern What it means: *Neither Button nor Lamp “own” the interface *Buttons can now control any device that implements SwitchableDevice *Lamps and other SwitchableDevices can now be controlled by any object that accepts a SwitchableDevice
  • 42. interface SwitchableDevice { public function turnOn(); public function turnOff(); } class Lamp implements SwitchableDevice { public function turnOn() { // code } public function turnOff() { // code } }
  • 43. class Button { private $switchableDevice; public function __construct(SwitchableDevice $switchableDevice) { $this->switchableDevice = $switchableDevice; } public function poll() { if (/* some condition */) { $this->switchableDevice->turnOn(); } } } We’ve made only a small change to Button, but it’s a powerful one
  • 44. A web of collaborating objects ● The SRP and DIP together drive a “composition” approach to OO design ● From Growing Object Oriented Software, Guided by Tests: "An object oriented system is a web of collaborating objects... The behavior of the system is an emergent property of the composition of the objects - the choice of objects and how they are connected... Thinking of a system in terms of its dynamic communication structure is a significant mental shift from the static classification that most of us learn when being introduced to objects." Author: Steve Freeman and Nat Pryce
  • 46. @mtoppapokayoke.design The SRP is about objects that do one thing The DIP is about how to wire them together to create working, flexible software
  • 47. @mtoppapokayoke.design 3. Class autoloading: the problem ● How do we include the class files we’ll need in our project? ● PHP lacks an equivalent statement to “import” or “use” for classes ● Having to hardcode a bunch of file paths for loading classes is extra work, and makes code harder to change
  • 48. @mtoppapokayoke.design Class autoloading: the solution ● PHP 5.1.2 and spl_autoload_register() ● PHP 5.3 and support for namespaces ● PHP Standards Working Group: PSR-4 ● http://www.php-fig.org/psr/psr-4/ * spl_autoloader_register allows you to register a function that will be called when PHP encounters a “new” call, for finding and including the file containing the class. *you can map namespaces to folders *PSR-4 provides an agreed upon convention for how to do it
  • 49. @mtoppapokayoke.design when you type this: new ShashinAdminInstaller; the Shashin autoloader will load this: /path/to/shashin/Admin/Installer.php PSR-4 Example
  • 50. @mtoppapokayoke.design // simplified version of code in Shashin’s initialization script require_once dirname(__FILE__) . '/lib/ShashinAutoLoader.php' new ShashinAutoLoader(); // that's it! I can now call “new” on any Shashin class // and its class file will be automatically loaded Shashin Autoloader
  • 52. Naïve button & lamp model revisited Button + poll() Lamp + turnOn() + turnOff() class Button { private $lamp; public function __construct(Lamp $lamp) { $this->lamp = $lamp; } public function poll() { if (/* some condition */) { $this->lamp->turnOn(); } } } ● This solution violates the DIP, but it’s still doing dependency injection ● You can apply the DIP using dependency injection ● There are also other techniques for applying the DIP: Factory pattern, adapter pattern, service locator pattern
  • 53. class Button { private $lamp; public function __construct() { $this->lamp = new Lamp(); } //... } Never, ever do this * There was one thing that was ok in the naïve example – we were at least passing in the lamp object *Instantiating it directly in the class makes your code harder to unit test. When unit testing we want to test the method’s logic in isolation, and not get involved with the actual behavior of other classes it uses. *When we bury these references in our code, it becomes hard to see what our collaborators are.
  • 54. public function __construct(SwitchableDevice $switchableDevice) { $this->switchableDevice = $switchableDevice; } Constructor injection
  • 55. public function setSwitchableDevice(SwitchableDevice $switchableDevice) { $this->switchableDevice = $switchableDevice; } Setter injection
  • 56. @mtoppapokayoke.design Which to use? It depends ● Constructor injection gives you a valid object, with all its dependencies, upon construction ● But constructor injection becomes hard to read and use when there are more than a few objects to inject ● More about this in an upcoming slide...
  • 57. @mtoppapokayoke.design If class A depends on class B, and class B depends on class C, class A should be blissfully unaware of class C Dependency chains We want loose coupling, not a rigid chain of dependencies that is hard to change
  • 58. @mtoppapokayoke.design To do this without going insane, you need an injection container
  • 59. class Container { // … public function getPhotoRefData() { if (!isset($this->photoRefData)) { $this->photoRefData = new ShashinLibPhotoRefData(); } return $this->photoRefData; } public function getClonablePhoto() { if (!isset($this->clonablePhoto)) { $this->getPhotoRefData(); $this->clonablePhoto = new ShashinLibPhoto($this->photoRefData); } return $this->clonablePhoto; } Example from Shashin I am making the objects properties of the container, because they happen to be immutable objects, so they are reusable You can see I'm using constructor injection I'll explain in a minute why I called it a “clonable” photo
  • 60. public function getClonablePhotoCollection() { if (!isset($this->photoCollection)) { $this->getClonablePhoto(); $this->getSettings(); $this->clonablePhotoCollection = new Lib_ShashinPhotoCollection(); $this->clonablePhotoCollection->setClonableDataObject($this->clonablePhoto); $this->clonablePhotoCollection->setSettings($this->settings); } return $this->clonablePhotoCollection; } Example continued Start with constructor injection As your design evolves, switch to setter injection once there are more than 2 objects to inject If you rely on an injection container, you don't have to worry about forgetting to call a required setter
  • 62. @mtoppapokayoke.design What to do when you need a new object inside a loop One solution is cloning
  • 63. class SynchronizerPicasa extends Synchronizer { // setClonablePhoto method… public function syncAlbumPhotos(array $decodedAlbumData) { // … foreach ($decodedAlbumData['feed']['entry'] as $entry) { $photoData = $this->extractFieldsFromDecodedData( $entry, $photoRefData, ‘picasa' ); // ... $photo = clone $this->clonablePhoto; $photo->set($photoData); $photo->flush(); } Shashin Example
  • 64. @mtoppapokayoke.design What if you need a new object inside a loop, but can't know the subtype you'll need ahead of time? Let the injection container figure it out This was an interesting problem for me with Shashin. It supports multiple media sources (Picasa, etc), multiple viewers (Fancybox, etc), and we could be displaying a photo or an album cover, each of which has different behaviors
  • 65. class LayoutManager { // setContainer method… public function setTableBody() { // … for ($i = 0; $i < count($this->collection); $i++) { // ... $dataObjectDisplayer = $this->container->getDataObjectDisplayer( $this->shortcode, $this->collection[$i] ); $this->tableBody .= $dataObjectDisplayer->run(); // ... } Shashin Example Regardless of the type, the layout rules for the thumbnails is always the same So here I've injected the container itself getDataObjectDisplayer() uses the passed in arguments to determine which subtype of DataObjectDisplayer to return
  • 66. class Container { // … public function getDataObjectDisplayer( //… ) { // … $dataObjectClassName = get_class($dataObject); // ShashinPhoto
 $albumType = ucfirst($dataObject->albumType); // Picasa
 $classToCall = $dataObjectClassName . 'Displayer' . $albumType;
 $dataObjectDisplayer = new $classToCall(); // … return $dataObjectDisplayer; // ShashinPhotoDisplayerPicasa
 } Shashin Example
  • 67. Off-the-shelf injection containers • PHP-DI • SymfonyDependencyInjection • ZendDi • OrnoDi • Dice • Aura.Di • Pimple • More info and performance analyses * If you want to try one, start with Dice. It’s lightweight and easy to understand. It does “auto-wiring” by using reflection. It relies on type hinting in your method signatures. * Others have you use configuration files, annotations, or PHP code to describe dependencies.
  • 68. @mtoppapokayoke.design Off-the-shelf or roll your own? * Using reflection is great for simple cases * Using configurations, you can end up with as much code as simply writing your own * I prefer writing my own. It’s not hard, and I can customize the behavior however I like without having to fight against the conventions of a pre-built container (like the getDataObjectDisplayer method)
  • 69. @mtoppapokayoke.design Dependency injection: key benefits ● Makes your objects flexible ● Can work with anything that supports the expected interface ● Decreases coupling, which promotes reusability, testability and maintainability ● With an injection container, simplifies managing dependency chains Button and lamp….
  • 70. But don't overdo it:
 avoid needless complexity The complexity of having 44 classes in Shashin is justified by its need for flexibility You can support a new viewer or a new photo service simply by creating a new subclass. This is much more maintainable and extensible than a single huge file with deeply nested conditionals and unclear dependencies But if I knew I would never need that kind of flexibility, there would be no justification for creating these layers of abstraction – they would just be needless complexity