intermediate oop in php
DESCRIPTION
Intermediate OOP in PHP is for developers who have moved past the basics of OOP and want to start exploring what's available and the power that OOP brings.TRANSCRIPT
Intermediate OOP in PHP
PHP World - November 13, 2014 David Stockton
@dstockto
What we’ll cover
Magic Methods
Polymorphism
Collections
Filtering Collections
SPL Iterator
What we’ll cover
SPL Count
SPL ArrayAccess
Listener Pattern
Loose Coupling
High Cohesion
Magic Methods
Methods all start with __
__construct & __destruct
__construct is called when you new up an object
Initialize object properties
Don’t do work!
__destruct is called when an object goes out of scope
Shut down connections, cleanup work
__call
__call($name, array $arguments)
Method called when method is called that is not in scope
Method doesn’t exist
Method is private / protected and called from outside object
__call
__callStatic
Just like __call but for static calls out of scope
Foo::createFromThing()
__get, __set, __isset, __unset
In many cases, if you need one, you need them all
Weird bugs if you don’t implement them all
__get
__get($name)
Called when reading an object property that’s not in scope
!
$value = $foo->madeUpValue;
__get
__set
__set($name, $value)
!
!
So, why do we need them all?
$foo->bar = ‘baz’;
$value = $foo->bar; // Get baz
if (isset($foo->bar)) { $value = $foo->bar; // Never get here if no __isset }
__isset
__isset($name)
isset($object->variable)
!
!
__unset
__unset($name)
unset($object->variable);
!
!
What you can do with them
Implement a class that doesn’t allow dynamic values
Implement a class that only allows values with certain naming conventions
Automatic calling of accessors (getters and setters)
The downsides
Harder to follow, no “ctrl-click” in IDEs
No auto-complete for __call or __callStatic methods in IDEs
Can use @method doc block to help
@method int add() add(numeric $a, numeric $b) Add numbers
@method docblock
__sleep & __wakeup
Called on serialize() and unserialize() calls
__sleep: Use to close connections, cleanup
__wakeup: Use to re-establish connections, setup
Why?
Some things in PHP are not serializable
__toString()
Retrieve string representation of a class
Must return a string
Cannot throw an exception
__toString
__toString
__clone
Create a new object based on an existing object
Called when clone is used:
$foo = clone $bar;
__clone
By default, clone is shallow
!
!
!
$foo = new Foo();
Foo$foo
Foo $bar$foo Bar
$foo2 = clone $foo;
Foo $bar$foo Bar
Foo $bar$bar
Now with __clone
$foo = new Foo();
Foo$foo
Foo $bar$foo Bar
$foo2 = clone $foo;
Foo $bar$foo Bar
Foo $bar$bar
__clone called on the clone
$foo2 = clone $foo;
Foo $bar$foo Bar
Foo $bar$bar Bar
__invoke
Allows an object to be used like a function or callable
Object can be built configured and then “executed”
__invoke
__invoke
__autoload
Don’t use __autoload, use spl_autoload_register
Called when a class, interface, or trait is used that hasn’t been loaded
Allows just in time loading of classes, no more requires and includes at the top of files
__set_state
Used with var_export
Allows setting of object variables from an array of input
__debugInfo
New in PHP 5.6
Controls output of var_dump
__debugInfo
var_dump
Add __debugInfo
var_dump again
PolymorphismAllow code to use different objects in the same
way
Speakableinterface
Polymorphism
Polymorphism
Collections and Polymorphism
Silverware Drawer
SilverwareContainerinterface
Silverwareinterface
Abstract Utensil Class
A Forking Example
Silver Spoons
Knife
Put silverware away
How many utensils?
Add method getNumberOfItems
!
!
Implement SPL Countable
- OR -
SPL Countable
How to use?
Retrieve Specific Utensils
SPL to the Rescue
Implement SPL ArrayAccess
Make our object work like an array
SPL ArrayAccess
SPL ArrayAccess
What does that allow?
Use an iterator: !
• Implement iterator • Extend one of these: • AppendIterator • ArrayIterator • CachingIterator • CallbackFilterIterator • InfiniteIterator • …etc.
Loop Over Utensils in Drawer
Easy wayExtend ArrayIterator
Add some silverware
Now what? Iterate it!
A new iterator
Only get clean utensils
SPLSubject / SPLObserverMoving right along
Implement SplSubject
Email class continued
Validate uses our observers
Build some observersInvalid Emails don’t send
Limit Sends by domains?
Put it all together
Loose Coupling
Loose Coupling
Minimize number of hard-coded dependencies
Type hint interfaces, not classes
Dependency Injection / Inversion of Control
Dependency Injection Simply
High CohesionDo one thing well
High Cohesion
Do one thing well
Methods
Classes
Packages / Namespaces
Everything the class does is related to the goal
–David Stockton
“If you have to use ‘and’ to describe what your method or class does,
it’s probably doing too much.”
Prefer Composition over Inheritance
Prefer Composition over Inheritance
Inheritance is not the only way to expand functionality of a class
Often it’s not even the best way
Photo Credits
• Lego Magician - https://www.flickr.com/photos/evaysucamara/5438832695 • Silverware - https://www.flickr.com/photos/jenny-pics/4128947072 • Fork - https://www.flickr.com/photos/naturesdawn/2507321223 • Trailer hitch - https://www.flickr.com/photos/jeremybrooks/2476396242 • The Glue Side of the Force - https://www.flickr.com/photos/st3f4n/4085958000 • Last Will and Testament - https://www.flickr.com/photos/ken_mayer/5599532152 • Guest Composer - https://www.flickr.com/photos/tamuc/12843465194