Vous êtes sur la page 1sur 41

Introduction Starting with PHP 5, the object model was rewritten to allow for better performa nce and

more features. This was a major change from PHP 4. PHP 5 has a full obje ct model. Among the features in PHP 5 are the inclusions of visibility, abstract and final classes and methods, additional magic methods, interfaces, cloning an d typehinting. PHP treats objects in the same way as references or handles, mean ing that each variable contains an object reference rather than a copy of the en tire object. See Objects and References Classes and Objects Introduction The Basics Properties Class Constants Autoloadi ng Classes Constructors and Destructors Visibility Object Inheritance Scope Reso lution Operator (::) Static Keyword Class Abstraction Object Interfaces Overload ing Object Iteration Patterns Magic Methods Final Keyword Object Cloning Compari ng Objects Type Hinting Late Static Bindings Objects and references Object Seria lization

Class Every class definition begins with the keyword class, followed by a class name, followed by a pair of curly braces which enclose the definitions of the class's properties and methods. The class name can be any valid label which is a not a P HP reserved word. A valid class name starts with a letter or underscore, followe d by any number of letters, numbers, or underscores. As a regular expression, it would be expressed thus: [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*. A class may contain its own constants, variables (called "properties"), and functions (calle d "methods"). <?php class SimpleClass { // property declaration public $var = 'a default value'; // method declaration public function displayVar() { echo $this ->var; } } ?> The pseudo-variable $this is available when a method is called fro m within an object context. $this is a reference to the calling object (usually the object to which the method belongs, but possibly another object, if the meth od is called statically from the context of a secondary object). <?php class A { function foo() { if (isset($this)) { echo '$this is defined ('; echo get_class( $this); echo ")\n"; } else { echo "\$this is not defined.\n"; } } } class B { fu nction bar() { // Note: the next line will issue a warning if E_STRICT is en abl ed. A::foo(); }

} $a = new A(); $a->foo(); // Note: the next line will issue a warning if E_STRI CT is enabled. A::foo(); $b = new B(); $b->bar(); // Note: the next line will is sue a warning if E_STRICT is enabled. B::bar(); ?> New To create an instance of a class, a new object must be created and assigned to a variable. An object will always be assigned when creating a new object unless the object has a construct or defined that throws an exception on error. Classes should be defined before i nstantiation (and in some cases this is a requirement). In the class context, it is possible to create a new object by new self and new parent. When assigning a n already created instance of a class to a new variable, the new variable will a ccess the same instance as the object that was assigned. This behaviour is the s ame when passing instances to a function. A copy of an already created object ca n be made by cloning it. <?php $assigned $reference = $instance; =& $instance; $instance->var = '$assigned will have this value'; $instance = null; // $instanc e and $reference become null var_dump($instance); var_dump($reference); var_dump ($assigned); ?> Extends A class can inherit the methods and properties of anothe r class by using the keyword extends in the class declaration. It is not possibl e to extend multiple classes; a class can only inherit from one base class. The inherited methods and properties can be overridden by redeclaring them with the same name defined in the parent class. However, if the parent class has defined a method as final, that method may not be overridden. It is possible to access t he overridden methods or static properties by referencing them with parent:: <?p hp class ExtendClass extends SimpleClass

{ // Redefine the parent method function displayVar() { echo "Extending class\n" ; parent::displayVar(); } } $extended = new ExtendClass(); $extended->displayVar (); ?>

Properties Class member variables are called "properties". You may also see them referred t o using other terms such as "attributes" or "fields", but for the purposes of th is reference we will use "properties". They are defined by using one of the keyw ords public, protected, or private, followed by a normal variable declaration. T his declaration may include an initialization, but this initialization must be a constant value--that is, it must be able to be evaluated at compile time and mu st not depend on run-time information in order to be evaluated. See Visibility f or more information on the meanings of public, protected, and private. Note: In order to maintain backward compatibility with PHP 4, PHP 5 will still accept the use of the keyword var in property declarations instead of (or in addition to) public, protected, or private. However, var is no longer required. In versions o f PHP from 5.0 to 5.1.3, the use of var was considered deprecated and would issu e an E_STRICT warning, but since PHP 5.1.3 it is no longer deprecated and does n ot issue the warning. If you declare a property using var instead of one of publ ic, protected, or private, then PHP 5 will treat the property as if it had been declared as public. Within class methods the properties, constants, and methods may be accessed by using the form $this>property (where property is the name of the property) unless the access is to a static property within the context of a static class method, in which case it is accessed using the form self::$property . See Static Keyword for more information. The pseudo-variable $this is availabl e inside any class method when that method is called from within an object conte xt. $this is a reference to the calling object (usually the object to which the method belongs, but possibly another object, if the method is called statically from the context of a secondary object).

Class Constants It is possible to define constant values on a per-class basis remaining the same and unchangeable. Constants differ from normal variables in that you don't use the $ symbol to declare or use them. The value must be a constant expression, no t (for example) a variable, a property, a result of a mathematical operation, or a function call. Its also possible for interfaces to have constants. Look at th e interface documentation for examples. As of PHP 5.3.0, it's possible to refere nce the class using a variable. The variable's value can not be a keyword (e.g. self, parent and static). EXAMPLE := const constant = 'constant value'; <?php cl ass MyClass { const constant = 'constant value'; function showConstant() { echo self::constant . "\n"; } } echo MyClass::constant . "\n"; $classname = "MyClass" ; echo $classname::constant . "\n"; // As of PHP 5.3.0 $class = new MyClass(); $ class->showConstant(); echo $class::constant."\n"; // As of PHP 5.3.0 ?>

Autoloading Classes Many developers writing object-oriented applications create one PHP source file per-class definition. One of the biggest annoyances is having to write a long li st of needed includes at the beginning of each script (one for each class). In P HP 5, this is no longer necessary. You may define an __autoload function which i s automatically called in case you are trying to use a class/interface which has n't been defined yet. By calling this function the scripting engine is given a l ast chance to load the class before PHP fails with an error. Note: Exceptions th rown in __autoload function cannot be caught in the catch block and results in a fatal error. Note: Autoloading is not available if using PHP in CLI interactive mode. Note: If the class name is used e.g. in call_user_func() then it can cont ain some dangerous characters such as ../. It is recommended to not use the user -input in such functions or at least verify the input in __autoload(). ?php func tion __autoload($class_name) { require_once $class_name . '.php'; } $obj = new M yClass1(); $obj2 = new MyClass2(); ?>

Constructors and Destructors Constructor void __construct ([ mixed $args [, $... ]] ) PHP 5 allows developers to declare constructor methods for classes. Classes which have a constructor method call th is method on each newly-created object, so it is suitable for any initialization that the object may need before it is used. Note: Parent constructors are not c alled implicitly if the child class defines a constructor. In order to run a par ent constructor, a call to parent::__construct() within the child constructor is required. <?php class BaseClass { function __construct() { print "In BaseClass constructor\n"; } } class SubClass extends BaseClass { function __construct() { parent::__construct(); print "In SubClass constructor\n"; } } $obj = new BaseCla ss(); $obj = new SubClass(); ?> For backwards compatibility, if PHP 5 cannot fin d a __construct() function for a given class, it will search for the old-style c onstructor function, by the name of the class. Effectively, it means that the on ly case that would have compatibility issues is if the class had a method named __construct() which was used for different semantics. Destructor void __destruct ( void ) PHP 5 introduces a destructor concept similar to that o f other object-oriented languages, such as C++. The destructor method will be ca lled as soon as all references to a particular object are removed or when the ob ject is explicitly destroyed or in any order in shutdown sequence. <?php class M yDestructableClass { function __construct() { print "In constructor\n";

$this->name = "MyDestructableClass"; } function __destruct() { print "Destroying " . $this->name . "\n"; } } $obj = new MyDestructableClass(); ?> Like construct ors, parent destructors will not be called implicitly by the engine. In order to run a parent destructor, one would have to explicitly call parent::__destruct() in the destructor body. Note: Destructors called during the script shutdown hav e HTTP headers already sent. The working directory in the script shutdown phase can be different with some SAPIs (e.g. Apache). Note: Attempting to throw an exc eption from a destructor (called in the time of script termination) causes a fat al error.

Visibility The visibility of a property or method can be defined by prefixing the declarati on with the keywords public, protected or private. Class members declared public can be accessed everywhere. Members declared protected can be accessed only wit hin the class itself and by inherited and parent classes. Members declared as pr ivate may only be accessed by the class that defines the member. Property Visibility Class properties must be defined as public, private, or protected. If declared u sing var without an explicit visibility keyword, the property will be defined as public. Note: The PHP 4 method of declaring a variable with the var keyword is still supported for compatibility reasons (as a synonym for the public keyword). In PHP 5 before 5.1.3, its usage would generate an E_STRICT warning. <?php /** * Define MyClass */ class MyClass { public $public = 'Public'; protected $protec ted = 'Protected'; private $private = 'Private'; function { echo echo echo } } $ obj = new MyClass(); echo $obj->public; // Works echo $obj->protected; // Fatal Error echo $obj->private; // Fatal Error $obj->printHello(); // Shows Public, Pr otected and Private /** * Define MyClass2 */ class MyClass2 extends MyClass { // We can redeclare the public and protected method, but not private protected $pr otected = 'Protected2'; printHello() $this->public; $this->protected; $this->pri vate;

function { echo echo echo } } printHello() $this->public; $this->protected; $this->private; $obj2 = new MyClass2(); echo $obj2->public; // Works echo $obj2->private; // Und efined echo $obj2->protected; // Fatal Error $obj2->printHello(); // Shows Publi c, Protected2, Undefined ?> Method Visibility Class methods may be defined as public, private, or protected. Methods declared without any explicit visibility keyword are defined as public.

<?php /** * Define MyClass */ class MyClass { // Declare a public constructor pu blic function __construct() { } // Declare a public method public function MyPub lic() { } // Declare a protected method protected function MyProtected() { } // Declare a private method private function MyPrivate() { } // This is public func tion Foo() { $this->MyPublic(); $this->MyProtected(); $this->MyPrivate(); } } $m yclass = new MyClass; $myclass->MyPublic(); // Works $myclass->MyProtected(); // Fatal Error $myclass->MyPrivate(); // Fatal Error $myclass->Foo(); // Public, P rotected and Private work /** * Define MyClass2 */ class MyClass2 extends MyClas s { // This is public function Foo2() { $this->MyPublic(); $this->MyProtected(); $this->MyPrivate(); // Fatal Error } } $myclass2 = new MyClass2;

$myclass2->MyPublic(); // Works $myclass2->Foo2(); // Public and Protected work, not Private class Bar { public function test() { $this->testPrivate(); $this->t estPublic(); } public function testPublic() { echo "Bar::testPublic\n"; } privat e function testPrivate() { echo "Bar::testPrivate\n"; } } class Foo extends Bar { public function testPublic() { echo "Foo::testPublic\n"; } private function te stPrivate() { echo "Foo::testPrivate\n"; } } $myFoo = new foo(); $myFoo->test(); // Bar::testPrivate // Foo::testPublic ?>

Object Inheritance Inheritance is a well-esablished programming principle, and PHP makes use of thi s principle in its object model. This principle will affect the way many classes and objects relate to one another. For example, when you extend a class, the su bclass inherits all of the public and protected methods from the parent class. U nless a class overrides those methods, they will retain their original functiona lity. This is useful for defining and abstracting functionality, and permits the implementation of additional functionality in similar objects without the need to reimplement all of the shared functionality. <?php class foo { public functio n printItem($string) { echo 'Foo: ' . $string . PHP_EOL; } public function print PHP() { echo 'PHP is great.' . PHP_EOL; } } class bar extends foo { public funct ion printItem($string) { echo 'Bar: ' . $string . PHP_EOL; } } $foo = new foo(); $bar = new bar(); $foo->printItem('baz'); $foo->printPHP(); $bar->printItem('ba z'); $bar->printPHP(); ?> // // // // Output: Output: Output: Output: 'Foo: baz' 'PHP is great' 'Bar: baz' 'PHP is great'

Scope Resolution Operator (::) The Scope Resolution Operator (also called Paamayim Nekudotayim) or in simpler t erms, the double colon, is a token that allows access to static, constant, and o verridden properties or methods of a class. When referencing these items from ou tside the class definition, use the name of the class. As of PHP 5.3.0, it's pos sible to reference the class using a variable. The variable's value can not be a keyword (e.g. self, parent and static). Paamayim Nekudotayim would, at first, s eem like a strange choice for naming a double-colon. However, while writing the Zend Engine 0.5 (which powers PHP 3), that's what the Zend team decided to call it. It actually does mean double-colon - in Hebrew! <?php class MyClass { const CONST_VALUE = 'A constant value'; } $classname = 'MyClass'; echo $classname::CON ST_VALUE; // As of PHP 5.3.0 echo MyClass::CONST_VALUE; ?> <?php class OtherClas s extends MyClass { public static $my_static = 'static var'; public static funct ion doubleColon() { echo parent::CONST_VALUE . "\n"; echo self::$my_static . "\n "; } } $classname = 'OtherClass'; echo $classname::doubleColon(); // As of PHP 5 .3.0 OtherClass::doubleColon(); ?> When an extending class overrides the parents definition of a method, PHP will not call the parent's method. It's up to the e xtended class on whether or not the parent's method is called. This also applies to Constructors and Destructors, Overloading, and Magic method definitions.

Static Keyword Declaring class properties or methods as static makes them accessible without ne eding an instantiation of the class. A property declared as static can not be ac cessed with an instantiated class object (though a static method can). For compa tibility with PHP 4, if no visibility declaration is used, then the property or method will be treated as if it was declared as public. Because static methods a re callable without an instance of the object created, the pseudo-variable $this is not available inside the method declared as static. Static properties cannot be accessed through the object using the arrow operator ->. Calling non-static methods statically generates an E_STRICT level warning. Like any other PHP stati c variable, static properties may only be initialized using a literal or constan t; expressions are not allowed. So while you may initialize a static property to an integer or array (for instance), you may not initialize it to another variab le, to a function return value, or to an object. As of PHP 5.3.0, it's possible to reference the class using a variable. The variable's value can not be a keywo rd (e.g. self, parent and static). <?php class Foo { public static $my_static = 'foo'; public function staticValue() { return self::$my_static; } } class Bar ex tends Foo { public function fooStatic() { return parent::$my_static; } } print F oo::$my_static . "\n"; $foo = new Foo(); print $foo->staticValue() . "\n"; print $foo->my_static . "\n"; // Undefined "Property" my_static print $foo::$my_static . "\n"; $classname = 'Foo'; print $classname::$my_static . "\n"; // As of PHP 5.3.0 print Bar::$my_static . "\n"; $bar = new Bar(); print $bar->fooStatic() . "\n"; ?>

Class Abstraction PHP 5 introduces abstract classes and methods. It is not allowed to create an in stance of a class that has been defined as abstract. Any class that contains at least one abstract method must also be abstract. Methods defined as abstract sim ply declare the method's signature they cannot define the implementation. When i nheriting from an abstract class, all methods marked abstract in the parent's cl ass declaration must be defined by the child; additionally, these methods must b e defined with the same (or a less restricted) visibility. For example, if the a bstract method is defined as protected, the function implementation must be defi ned as either protected or public, but not private. <?php abstract class Abstrac tClass { // Force Extending class to define this method abstract protected funct ion getValue(); abstract protected function prefixValue($prefix); // Common meth od public function printOut() { print $this->getValue() . "\n"; } } class Concre teClass1 extends AbstractClass { protected function getValue() { return "Concret eClass1"; } public function prefixValue($prefix) { return "{$prefix}ConcreteClas s1"; } } class ConcreteClass2 extends AbstractClass { public function getValue() { return "ConcreteClass2"; } public function prefixValue($prefix) { return "{$p refix}ConcreteClass2"; } } $class1 = new ConcreteClass1; $class1->printOut();

echo $class1->prefixValue('FOO_') ."\n"; $class2 = new ConcreteClass2; $class2-> printOut(); echo $class2->prefixValue('FOO_') ."\n"; ?>

Object Interfaces Object interfaces allow you to create code which specifies which methods a class must implement, without having to define how these methods are handled. Interfa ces are defined using the interface keyword, in the same way as a standard class , but without any of the methods having their contents defined. All methods decl ared in an interface must be public, this is the nature of an interface. implements To implement an interface, the implements operator is used. All methods in the i nterface must be implemented within a class; failure to do so will result in a f atal error. Classes may implement more than one interface if desired by separati ng each interface with a comma. Note: A class cannot implement two interfaces th at share function names, since it would cause ambiguity. Note: Interfaces can be extended like classes using the extend operator. Note: The class implementing t he interface must use the exact same method signatures as are defined in the int erface. Not doing so will result in a fatal error. Constants Its possible for interfaces to have constants. Interface constants works exactly like class constants. They cannot be overridden by a class/interface that inher its it. Examples <?php interface a { public function foo(); } interface b extends a { public func tion baz(Baz $baz); } // This will work class c implements b { public function f oo() { } public function baz(Baz $baz)

{ } } // This will not work and result in a fatal error class d implements b { p ublic function foo() { } public function baz(Foo $foo) { } } ?>

Overloading Overloading in PHP provides means to dynamically "create" properties and methods . These dynamic entities are processed via magic methods one can establish in a class for various action types. The overloading methods are invoked when interac ting with properties or methods that have not been declared or are not visible i n the current scope. The rest of this section will use the terms "inaccessible p roperties" and "inaccessible methods" to refer to this combination of declaratio n and visibility. All overloading methods must be defined as public. Note: None of the arguments of these magic methods can be passed by reference. Note: PHP's interpretation of "overloading" is different than most object oriented languages . Overloading traditionally provides the ability to have multiple methods with t he same name but different quantities and types of arguments. Changelog Version Description 5.3.0 Added __callStatic(). Added warning to enforce public visibility and non-static declaration. 5.1.0 Added __isset() and __unset(). Property overloading void __set ( string $name , mixed $value ) mixed __get ( string $name ) bool __i sset ( string $name ) void __unset ( string $name ) __set() is run when writing data to inaccessible properties. __get() is utilized for reading data from inacc essible properties. __isset() is triggered by calling isset() or empty() on inac cessible properties. __unset() is invoked when unset() is used on inaccessible p roperties. The $name argument is the name of the property being interacted with. The __set() method's $value argument specifies the value the $name'ed property should be set to. Property overloading only works in object context. These magic methods will not be triggered in static context. Therefore these methods can no t be declared static. Note: The return value of __set() is ignored because of th e way PHP processes the assignment operator. Similarly, __get() is never called when chaining assignemnts together like this: $a = $obj->b = 8; <?php class PropertyTest { /** Location for overloaded data. */

private $data = array(); /** Overloading not used on declared properties. public $declared = 1; s. */ /** Overloading only used on this when accessed outside the clas */ private $hid den = 2; public function __set($name, $value) { echo "Setting '$name' to '$value '\n"; $this->data[$name] = $value; } public function __get($name) { echo "Gettin g '$name'\n"; if (array_key_exists($name, $this->data)) { return $this->data[$na me]; } $trace = debug_backtrace(); trigger_error( 'Undefined property via __get( ): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_U SER_NOTICE); return null; } /** As of PHP 5.1.0 */ public function __isset($name ) { echo "Is '$name' set?\n"; return isset($this->data[$name]); } /** As of PHP 5.1.0 */ public function __unset($name) { echo "Unsetting '$name'\n"; unset($thi s->data[$name]); } /** Not a magic method, just here for example. public functio n getHidden() { return $this->hidden; } */ } echo "<pre>\n";

$obj = new PropertyTest; $obj->a = 1; echo $obj->a . "\n\n"; var_dump(isset($obj ->a)); unset($obj->a); var_dump(isset($obj->a)); echo "\n"; echo $obj->declared . "\n\n"; echo echo "; echo echo ; echo ?> "Let's experiment with the private pr operty named 'hidden':\n"; "Privates are visible inside the class, so __get() no t used...\n $obj->getHidden() . "\n"; "Privates not visible outside of class, so __get() is used...\n" $obj->hidden . "\n"; Method overloading mixed __call ( string $name , array $arguments ) mixed __callStatic ( string $na me , array $arguments ) __call() is triggered when invoking inaccessible methods in an object context. __callStatic() is triggered when invoking inaccessible me thods in a static context. The $name argument is the name of the method being ca lled. The $arguments argument is an enumerated array containing the parameters p assed to the $name'ed method. <?php class MethodTest { public function __call($n ame, $arguments) { // Note: value of $name is case sensitive. echo "Calling obje ct method '$name' " . implode(', ', $arguments). "\n"; } /** As of PHP 5.3.0 */ public static function __callStatic($name, $arguments) { // Note: value of $name is case sensitive. echo "Calling static method '$name' " . implode(', ', $argum ents). "\n"; } } $obj = new MethodTest; $obj->runTest('in object context');

MethodTest::runTest('in static context'); ?> // As of PHP 5.3.0

Object Iteration PHP 5 provides a way for objects to be defined so it is possible to iterate thro ugh a list of items, with, for example a foreach statement. By default, all visi ble properties will be used for the iteration. <?php class MyClass { public $var 1 = 'value 1'; public $var2 = 'value 2'; public $var3 = 'value 3'; protected $pr otected = 'protected var'; private $private = 'private var'; function iterateVis ible() { echo "MyClass::iterateVisible:\n"; foreach($this as $key => $value) { p rint "$key => $value\n"; } } } $class = new MyClass(); foreach($class as $key => $value) { print "$key => $value\n"; } echo "\n"; $class->iterateVisible(); ?>

Patterns Patterns are ways to describe best practices and good designs. They show a flexi ble solution to common programming problems. Factory The Factory pattern allows for the instantiation of objects at runtime. It is ca lled a Factory Pattern since it is responsible for "manufacturing" an object. A Parameterized Factory receives the name of the class to instantiate as argument. <?php class Example { // The parameterized factory method public static functio n factory($type) { if (include_once 'Drivers/' . $type . '.php') { $classname = 'Driver_' . $type; return new $classname; } else { throw new Exception ('Driver not found'); } } } ?> Singleton The Singleton pattern applies to situations in which there needs to be a single instance of a class. The most common example of this is a database connection. I mplementing this pattern allows a programmer to make this single instance easily accessible by many other objects. <?php class Example { // Hold an instance of the class private static $instance; // A private constructor; prevents direct cr eation of object private function __construct() { echo 'I am constructed'; } // The singleton method public static function singleton() { if (!isset(self::$inst ance)) { $c = __CLASS__;

self::$instance = new $c; } return self::$instance; } // Example method public f unction bark() { echo 'Woof!'; } // Prevent users to clone the instance public f unction __clone() { trigger_error('Clone is not allowed.', E_USER_ERROR); } } ?>

Magic Methods The function names __construct, __destruct, __call, __callStatic, __get, __set, __isset, __unset, __sleep, __wakeup, __toString, __invoke, __set_state and __clo ne are magical in PHP classes. You cannot have functions with these names in any of your classes unless you want the magic functionality associated with them. C aution PHP reserves all function names starting with __ as magical. It is recomm ended that you do not use function names with __ in PHP unless you want some doc umented magic functionality. __sleep and __wakeup serialize() checks if your class has a function with the magic name __sleep. If so, that function is executed prior to any serialization. It can clean up the ob ject and is supposed to return an array with the names of all variables of that object that should be serialized. If the method doesn't return anything then NUL L is serialized and E_NOTICE is issued. The intended use of __sleep is to commit pending data or perform similar cleanup tasks. Also, the function is useful if you have very large objects which do not need to be saved completely. Conversely , unserialize() checks for the presence of a function with the magic name __wake up. If present, this function can reconstruct any resources that the object may have. The intended use of __wakeup is to reestablish any database connections th at may have been lost during serialization and perform other reinitialization ta sks. __toString The __toString method allows a class to decide how it will react when it is conv erted to a string. It is worth noting that before PHP 5.2.0 the __toString metho d was only called when it was directly combined with echo() or print(). Since PH P 5.2.0, it is called in any string context (e.g. in printf() with %s modifier) but not in other types contexts (e.g. with %d modifier). Since PHP 5.2.0, conver ting objects without __toString method to string would cause E_RECOVERABLE_ERROR . __invoke The __invoke method is called when a script tries to call an object as a functio n. __set_state This static method is called for classes exported by var_export() since PHP 5.1. 0. The only parameter of this method is an array containing exported properties in the form array('property' => value, ...).

Final Keyword PHP 5 introduces the final keyword, which prevents child classes from overriding a method by prefixing the definition with final. If the class itself is being d efined final then it cannot be extended. <?php class BaseClass { public function test() { echo "BaseClass::test() called\n"; } final public function moreTesting () { echo "BaseClass::moreTesting() called\n"; } } class ChildClass extends Base Class { public function moreTesting() { echo "ChildClass::moreTesting() called\n "; } } // Results in Fatal error: Cannot override final method BaseClass::mo reT esting() ?>

Object Cloning Creating a copy of an object with fully replicated properties is not always the wanted behavior. A good example of the need for copy constructors, is if you hav e an object which represents a GTK window and the object holds the resource of t his GTK window, when you create a duplicate you might want to create a new windo w with the same properties and have the new object hold the resource of the new window. Another example is if your object holds a reference to another object wh ich it uses and when you replicate the parent object you want to create a new in stance of this other object so that the replica has its own separate copy. An ob ject copy is created by using the clone keyword (which calls the object's __clon e() method if possible). An object's __clone() method cannot be called directly. $copy_of_object = clone $object; When an object is cloned, PHP 5 will perform a shallow copy of all of the object 's properties. Any properties that are references to other variables, will remai n references. Once the cloning is complete, if a __clone() method is defined, th en the newly created object's __clone() method will be called, to allow any nece ssary properties that need to be changed. <?php class SubObject { static $instan ces = 0; public $instance; public function __construct() { $this->instance = ++s elf::$instances; } public function __clone() { $this->instance = ++self::$instan ces; } } class MyCloneable { public $object1; public $object2; function __clone( ) { // Force a copy of this->object, otherwise // it will point to same object. $this->object1 = clone $this->object1; } } $obj = new MyCloneable();

$obj->object1 = new SubObject(); $obj->object2 = new SubObject(); $obj2 = clone $obj; print("Original Object:\n"); print_r($obj); print("Cloned Object:\n"); pri nt_r($obj2); ?>

Comparing Objects In PHP 5, object comparison is more complicated than in PHP 4 and more in accord ance to what one will expect from an Object Oriented Language (not that PHP 5 is such a language). When using the comparison operator (==), object variables are compared in a simple manner, namely: Two object instances are equal if they hav e the same attributes and values, and are instances of the same class. On the ot her hand, when using the identity operator (===), object variables are identical if and only if they refer to the same instance of the same class. An example wi ll clarify these rules.

<?php function bool2str($bool) { if ($bool === false) { return 'FALSE'; } else { return 'TRUE'; } } function { echo echo echo echo } compareObjects(&$o1, &$o2) 'o1 'o1 'o1 'o1 == o2 : ' . bool2str($o1 == $o2) . != o2 : ' . bool2str($o1 != $ o2) . === o2 : ' . bool2str($o1 === $o2) !== o2 : ' . bool2str($o1 !== $o2) "\n" ; "\n"; . "\n"; . "\n"; class Flag { public $flag; function Flag($flag = true) { $this->flag = $flag; } } class OtherFlag { public $flag; function OtherFlag($flag = true) { $this->flag = $flag; } } $o $p $q $r = = = = new Flag(); new Flag(); $o; new OtherFlag(); echo "Two instances of the same class\n"; compareObjects($o, $p); echo "\nTwo re ferences to the same instance\n"; compareObjects($o, $q); echo "\nInstances of t wo different classes\n"; compareObjects($o, $r);

?>

Type Hinting PHP 5 introduces Type Hinting. Functions are now able to force parameters to be objects (by specifying the name of the class in the function prototype) or array s (since PHP 5.1). However, if NULL is used as the default parameter value, it w ill be allowed as an argument for any later call. <?php // An example class clas s MyClass { /** * A test function * * First parameter must be an object of type OtherClass */ public function test(OtherClass $otherclass) { echo $otherclass->v ar; } /** * Another test function * * First parameter must be an array */ public function test_array(array $input_array) { print_r($input_array); } } // Another example class class OtherClass { public $var = 'Hello World'; } ?>

Late Static Bindings As of PHP 5.3.0, PHP implements a feature called late static bindings which can be used to reference the called class in a context of static inheritance. This f eature was named "late static bindings" with an internal perspective in mind. "L ate binding" comes from the fact that static:: will no longer be resolved using the class where the method is defined but it will rather be computed using runti me information. It was also called a "static binding" as it can be used for (but is not limited to) static method calls. Limitations of self:: Static references to the current class like ng the class in which the function belongs, ass A { public static function who() { echo test() { self::who(); } } class B extends A o __CLASS__; } } B::test(); ?> self:: or __CLASS__ are resolved usi as in where it was defined: <?php cl __CLASS__; } public static function { public static function who() { ech

Late Static Bindings' usage Late static bindings tries to solve that limitation by introducing a keyword tha t references the class that was initially called at runtime. Basically, a keywor d that would allow you to reference B from test() in the previous example. It wa s decided not to introduce a new keyword but rather use static that was already reserved. <?php class A { public static function who() { echo __CLASS__; } publi c static function test() { static::who(); // Here comes Late Static Bindings } }

class B extends A { public static function who() { echo __CLASS__; } } B::test() ; ?> Edge cases There are lots of different ways to trigger a method call in PHP, like callbacks or magic methods. As late static bindings base their resolution on runtime info rmation, it might give unexpected results in socalled edge cases. <?php class A { protected static function who() { echo __CLASS__."\n"; } public function __get ($var) { return static::who(); } } class B extends A { protected static function who() { echo __CLASS__."\n"; } } $b = new B; $b->foo; ?>

Objects and references One of the key-points of PHP5 OOP that is often mentioned is that "objects are p assed by references by default". This is not completely true. This section recti fies that general thought using some examples. A PHP reference is an alias, whic h allows two different variables to write to the same value. As of PHP5, an obje ct variable doesn't contain the object itself as value anymore. It only contains an object identifier which allows object accessors to find the actual object. W hen an object is sent by argument, returned or assigned to another variable, the different variables are not aliases: they hold a copy of the identifier, which points to the same object. <?php class A { public $foo = 1; } $a = new A; $b = $ a; // $a and $b are copies of the same identifier // ($a) = ($b) = <id> $b->foo = 2; echo $a->foo."\n"; $c = new A; $d = &$c; // $c and $d are references // ($c,$d) = <id> $d->foo = 2; echo $c->foo."\n"; $e = new A; function foo($obj) { // ($obj) = ($e ) = <id> $obj->foo = 2; } foo($e); echo $e->foo."\n"; ?>

Object Serialization Serializing objects - objects in sessions serialize() returns a string containing a byte-stream representation of any valu e that can be stored in PHP. unserialize() can use this string to recreate the o riginal variable values. Using serialize to save an object will save all variabl es in an object. The methods in an object will not be saved, only the name of th e class. In order to be able to unserialize() an object, the class of that objec t needs to be defined. That is, if you have an object of class A and serialize t his, you'll get a string that refers to class A and contains all values of varia bled contained it. If you want to be able to unserialize this in another file, a n object of class A, the definition of class A must be prest ent in in that file first. This can be done for example by storing the class definition of class A in an include file and including this file or making use of the spl_autoload_reg ister() function. <?php // classa.inc: class A { public $one = 1; public functio n show_one() { echo $this->one; } } // page1.php: include("classa.inc"); $a = ne w A; $s = serialize($a); // store $s somewhere where page2.php can find it. file _put_contents('store', $s); // page2.php: // this is needed for the unserialize to work properly. include("classa.inc"); $s = file_get_contents('store'); $a = u nserialize($s); // now use the function show_one() of the $a object. $a->show_on e(); ?> If an application is using sessions and uses session_register() to regis ter objects, these objects are serialized automatically at the end of each PHP p age, and are unserialized automatically on each of the

following pages. This means that these objects can show up on any of the applica tion's pages once they become part of the session. However, session_register() i s deprecated as of PHP 5.3.0, and removed as of PHP 6.0.0. Reliance on this func tion is not recommended. It is strongly recommended that if an application seria lizes objects, for use later in the application, that the application include th e class definition for that object throughout the application. Not doing so migh t result in an object being unserialized without a class definition, which will result in PHP giving the object a class of __PHP_Incomplete_Class_Name, which ha s no methods and would render the object useless. So if in the example above $a became part of a session by running session_register("a"), you should include th e file classa.inc on all of your pages, not only page1.php and page2.php.

Vous aimerez peut-être aussi