Membership
Main Menu
Forum Boards
Stats
- 20 tutorials
- 74,816 members
- 734,938 forum posts
- 13 blog posts
Tutorials
OO PHP Part 1: OOP in Full Effect
Views: 43570
3 Beyond the Absolute Basics
3.1 Object Handles
In PHP5, objects are defined by handles, not unlike resource type variables.
Passing an object to a function doesn’t make a copy of it. Have a read on References Explained if you’re still a little confused by this.
3.2 Interfaces
PHP5 features interfaces. Not to be confused with interfaces in the more general sense, the interface keyword creates an entity that can be used to enforce a common interface upon classes without having to extend them like with abstract classes. Instead an interface is implemented.
Interfaces are different from abstract classes. For one, they’re not actually classes. They don’t define properties, and they don’t define any behaviour. The methods declared in an interface must be declared in classes that implement it.
Because an interface in the more general sense is a definition of how an object interacts with other code, all methods must be declared public (see section on visibility in this chapter). Using abstract classes, an abstract method can have any visibility, but the extending classes must have their implementations use the same (or weaker) visibility. Implementing an interface adds the methods as abstract methods to the subject class, failure to implement it will result in an error like the following:
Fatal error: Class SomeConcreteClass contains n abstract method(s) and must therefore be declared abstract or implement the remaining methodsYes, abstract classes can implement interfaces.
Interfaces can be looked upon as a contract, a certificate of compliance if you will. Other code is guaranteed that a class implementing it will use certain methods to interact.
Enough babbling, let’s see a code example:
Doggie implements 2 interfaces, both Animal and Mammal. You can implement as many interfaces as you like.
3.3 Autoload
A very convenient feature, __autoload allows you to get rid of all those annoying includes that need to be managed. This magic function will execute whenever a class or interface is referenced that hasn’t been defined. That gives you the opportunity to include it.
Here’s a simple example of how that might look using the standard PEAR naming scheme (the segments between underscores become directory names, bar the last, which becomes the filename):
We don’t really need require_once, because once the file is included, __autoload will not trigger on that class or interface reference again.
3.4 Destructors
Destructors are another type of magic methods. Indicated by __destruct, these methods are called when all references to their objects are removed. This includes explicit un-setting and script shutdown. A quick example of this:
This echoes:
Destructing object 'Object one'.
Script still running.
Destructing object 'Object two'.
Object one is destructed when we explicitly unset it, object two just before the script execution is completed. An object’s destructor is always executed (or rather ‘should be’: don’t rely on this mechanism too much). Note that if we had created a second object from within class Example, it’s destructor would also have been executed, as it would have removed all references to the embedded object.
3.5 Visibility
PHP 5 allows you to declare the visibility of methods and properties. There are three types of visibility: public, protected and private.
Public
Public methods and properties are visible (accessible) to any code that queries them. No accessibility restrictions are applied. In PHP 5, methods without visibility declaration are assumed public, the visibility declaration is required, excluding static class members (if you don’t include it, ‘public’ is assumed). Class constants are always globally available.
Protected
Requests are only allowed from within the objects blueprint (that includes parent and child classes). Meaning the following would fail:
Produces:
Fatal error: Cannot access protected property Teeth::$_colour
Should Teeth have been a parent class of Dog instead of a member object (class Dog extends Teeth - don’t do that), $colour would have been accessible though $this, but also statically by Teeth::$_colour (or parent::$_colour).
Private
Access is limited to the declaring class (the class the property is declared in). No external access whatsoever is allowed.
One thing that should be noted when using protected or private properties, is that if you attempt to assign a value to a property that isn’t visible to the class you are doing it in, you will be creating a new property instead of resetting the original. Keep that in mind when you get unexpected values: check the property’s visibility.
3.6 Class Constants
We already covered using static class members, there is another type of class member, which we haven’t covered: class constants.
I am assuming you are already familiar with regular constants, and are aware of how they differ from variables.
Class constants are just regular constants, declared in a class. It’s reference is obtained through the class scope. Because constants are unchangeable, they are independent of any state the object could be in. Therefore they can only be called statically.
Both $dog->NUMBER_OF_LEGS and $this->NUMBER_OF_LEGS would have PHP looking for a non-existent object property: $NUMBER_OF_LEGS.
Class constants are always publicly accessible. Any code can call Dog::NUMBER_OF_LEGS.
3.7 Type Hinting
PHP 5 features type hinting as a means to limit the types of variables that a method will accept as an argument. Let’s kick off with a simple example:
Attempting to use an instance of Dog with the feedRabbit method results in the following error:
Fatal error: Argument 1 passed to Feeder::feedRabbit() must be an instance of Rabbit
However, type hinting allows a more generic use. Consider the following example:
Because $dog is not only a Dog, but also an Animal, the requirement is met. Doggie doesn’t like broccoli (who does?), but that is besides the point. Currently PHP only supports type hinting with objects and arrays.
Note: since PHP 5.2, failing type hinting requirements result in a E_RECOVERABLE_ERROR type error, not an immediate fatal error.
3.8 Exceptions
PHP 5 introduces the concept of exceptions to PHP. An exception is not an error, an uncaught exception is (a fatal error).
Using exceptions you will need the following keywords: try, throw and catch. PHP 5 has it’s build-in Exception class, which you can extend.
You can have multiple catch blocks following a try block. PHP will execute the first catch block that matches the type of the exception thrown. If no exception is thrown or none of the catch declarations match the thrown exception type, no catch blocks are executed.
In the example above, the code in the try block is executed until an exception is thrown. If an exception is thrown, the code in the corresponding catch block is executed. As noted, PHP executes the FIRST matching catch block. So if we switched the catch blocks, the first block would be executed, even though the second is a ‘closer match’.
If there isn’t a corresponding catch block, the exception is ‘falls through’. Assuming the call to the code is not itself contained in a try block, the exception is uncaught, resulting in a fatal error.
3.9 The Final Keyword
The final keyword indicates that the declaration following it is final, no child class will be able to redefine it. One can declare both a single method or a whole class as final. If the whole class is declared final, it becomes un-extendable: no child classes are allowed.
There really isn’t much more to it, apply it only if you are absolutely sure you don’t want that specific class or method extended or re-declared respectively.
3.10 More Magic Methods
Aside from __construct, __destruct, there are quite a few more magic methods:
Overloading
- __call
- __get
- __set
- __isset
- __unset
Object cloning
- __clone
Serialization
- __sleep
- __wakeup
Other
- __toString
- __setState
3.10.1 Object Overloading
If you’re coming from a different OO language, the term ‘overloading’ likely has a very different meaning to you: defining different method with the same name having different signatures. This has nothing to do with that.
Object overloading in PHP refers to the mechanism where a call to a method or property will ‘overload’ the call to a different property or method. The call ultimately made can depend on the type of the arguments or the context.
These magic methods allow you catch calls to methods and properties that haven’t been defined, because you didn’t know (or didn’t want to specify) the exact name.
The magic methods are executed only if the object doesn’t have the method or property declared.
The following example class uses __set to check if an embedded object does have the property requested, before creating a new property for the parent object.
An example __call use:
Methods __get, __isset and __unset have similar uses.
3.10.2 Object cloning
Because in PHP 5 objects use handles, if you would want to create a copy of an object you have to explicitly indicate so with the clone keyword.
Above gives you a new object that is an exact copy of $obj in the state it was when copied.
The __clone method is triggered by this clone keyword. This allows you, for example, to ensure embedded objects are also cloned (otherwise they would this use the same object handle for the embedded objects).
The following example illustrates this:
That will echo:
green
green
Changing the property colour to green on $Snoopy’s teeth, also changes $Lassie’s teeth to green, because they share the same teeth. Imagine that, two dogs attached at the mouth…
To give Lassie’s clone Snoopy its own set of teeth, we can use the __clone method:
Now it will output:
green
white
Voila, a cloned Dog now has its own teeth.
3.10.3 Serialization
Resource handles don’t serialize. If one of your properties has a resource handle as its value, for example a file handle or database connection, You can use the __wakeup magic to re-establish these handles. This method will be called when you call unserialize($serializedObject). The __sleep method is invoked when you serialize an object, and is expected to return an array of property names to be included in the serialization. This allows you to exclude certain properties.
3.10.4 Other
Other methods that don’t fit in the previous categories.
__toString: This magic method can be used to define how an object will present itself if the whole object is treated as a string.
Example:
Result:
I am Dog.
Note that older versions of PHP 5 didn’t support calling __toString() when embedding or concatenating in a string. Currently, this will work as well:
__set_state: This is a static method that can be used to reinitialize an object after being “flattened” by var_export.
3.11 Object Iteration
PHP allows objects to be iterated, all properties visible to the scope the iteration is requested from are used. Example of this with a foreach loop:
Output:
Internal iteration of Example:
Property 'propertyThree' => 'value3'
Property 'propertyOne' => 'value1'
Property 'propertyTwo' => 'value2'
External iteration of Example:
Property 'propertyTwo' => 'value2'
External iteration of ExampleParent:
Property 'propertyTwo' => 'value2'
You’ll notice that the external iteration doesn’t list the private and protected properties.
