<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="http://commons.oreilly.com/wiki/skins/common/feed.css?97"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://commons.oreilly.com/wiki/index.php?title=PHP_Cookbook/Classes_and_Objects&amp;action=history&amp;feed=atom</id>
		<title>PHP Cookbook/Classes and Objects - Revision history</title>
		<link rel="self" type="application/atom+xml" href="http://commons.oreilly.com/wiki/index.php?title=PHP_Cookbook/Classes_and_Objects&amp;action=history&amp;feed=atom"/>
		<link rel="alternate" type="text/html" href="http://commons.oreilly.com/wiki/index.php?title=PHP_Cookbook/Classes_and_Objects&amp;action=history"/>
		<updated>2013-05-22T10:59:24Z</updated>
		<subtitle>Revision history for this page on the wiki</subtitle>
		<generator>MediaWiki 1.11.0</generator>

	<entry>
		<id>http://commons.oreilly.com/wiki/index.php?title=PHP_Cookbook/Classes_and_Objects&amp;diff=7319&amp;oldid=prev</id>
		<title>Docbook2Wiki: Initial conversion from Docbook</title>
		<link rel="alternate" type="text/html" href="http://commons.oreilly.com/wiki/index.php?title=PHP_Cookbook/Classes_and_Objects&amp;diff=7319&amp;oldid=prev"/>
				<updated>2008-03-07T13:36:04Z</updated>
		
		<summary type="html">&lt;p&gt;Initial conversion from Docbook&lt;/p&gt;

			&lt;table style=&quot;background-color: white; color:black;&quot;&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;tr&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;←Older revision&lt;/td&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Revision as of 13:36, 7 March 2008&lt;/td&gt;
			&lt;/tr&gt;
		&lt;/table&gt;</summary>
		<author><name>Docbook2Wiki</name></author>	</entry>

	<entry>
		<id>http://commons.oreilly.com/wiki/index.php?title=PHP_Cookbook/Classes_and_Objects&amp;diff=3117&amp;oldid=prev</id>
		<title>Evanlenz: 1 revision(s)</title>
		<link rel="alternate" type="text/html" href="http://commons.oreilly.com/wiki/index.php?title=PHP_Cookbook/Classes_and_Objects&amp;diff=3117&amp;oldid=prev"/>
				<updated>2008-03-06T22:30:02Z</updated>
		
		<summary type="html">&lt;p&gt;1 revision(s)&lt;/p&gt;

			&lt;table style=&quot;background-color: white; color:black;&quot;&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;tr&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;←Older revision&lt;/td&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Revision as of 22:30, 6 March 2008&lt;/td&gt;
			&lt;/tr&gt;
		&lt;/table&gt;</summary>
		<author><name>Evanlenz</name></author>	</entry>

	<entry>
		<id>http://commons.oreilly.com/wiki/index.php?title=PHP_Cookbook/Classes_and_Objects&amp;diff=3116&amp;oldid=prev</id>
		<title>Docbook2Wiki: Initial conversion from Docbook</title>
		<link rel="alternate" type="text/html" href="http://commons.oreilly.com/wiki/index.php?title=PHP_Cookbook/Classes_and_Objects&amp;diff=3116&amp;oldid=prev"/>
				<updated>2008-03-06T22:28:45Z</updated>
		
		<summary type="html">&lt;p&gt;Initial conversion from Docbook&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{PHP Cookbook/TOC}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
At first, PHP wasn't an object-oriented (OO) language. As it evolved, more and more object-oriented features appeared. First, you could define classes, but there were no constructors. Then, constructors appeared, but there were no destructors. Slowly but surely, as more people began to push the limits of PHP's syntax, additional features were added to satisfy the demand.&lt;br /&gt;
&lt;br /&gt;
However, if you're the type of person who wishes PHP to be a true OO language, you'll probably be disappointed. At its heart, PHP is a procedural language. It isn't Java. But, if you're the type of person who wants to use some OO features in your code, PHP is probably right for you.&lt;br /&gt;
&lt;br /&gt;
A ''class'' is a package containing two things: data and methods to access and modify that data. The data portion consists of variables; they're known as ''properties''. The other part of a class is a set of functions that can alter a class' properties; they're called ''methods''.&lt;br /&gt;
&lt;br /&gt;
When we define a class, we don't define an object that can be accessed and manipulated. Instead, we define a template for an object. From this blueprint, we create malleable objects through a process known as ''instantiation'' . A program can have multiple objects of the same class, just as a person can have more than one book or many pieces of fruit.&lt;br /&gt;
&lt;br /&gt;
Classes also live in a defined hierarchy. At the top of the chain, there is a generic class. In PHP, this class is named &amp;lt;tt&amp;gt;stdClass&amp;lt;/tt&amp;gt; , for &amp;quot;standard class.&amp;quot; Each class down the line is more specialized than its parent. For example, a parent class could be a building. Buildings can be further divided into residential and commercial. Residential buildings can be further subdivided into houses and apartment buildings, and so forth.&lt;br /&gt;
&lt;br /&gt;
Both houses and apartment buildings have the same set of properties as all residential buildings, just as residential and commercial buildings share some things in common. When classes are used to express these parent-child relationships, the child class inherits the properties and methods defined in the parent class. This allows you to reuse the code from the parent class and requires you to write code only to adapt the new child to its specialized circumstances. This is called ''inheritance'' and is one of the major advantages of classes over functions. The process of defining a child class from a parent is known as ''subclassing'' or ''extending''.&lt;br /&gt;
&lt;br /&gt;
Objects play another role in PHP outside their traditional OO position. Since PHP can't use more than one namespace, the ability for a class to package multiple properties into a single object is extremely helpful. It allows clearly demarcated separate areas for variables.&lt;br /&gt;
&lt;br /&gt;
Classes in PHP are easy to define and create:&lt;br /&gt;
&lt;br /&gt;
 class guest_book {&lt;br /&gt;
     var $comments;&lt;br /&gt;
     var $last_visitor;&lt;br /&gt;
 &lt;br /&gt;
     function update($comment, $visitor) {&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;class&amp;lt;/tt&amp;gt; keyword defines an class, just as &amp;lt;tt&amp;gt;function&amp;lt;/tt&amp;gt; defines a function. Properties are declared using the &amp;lt;tt&amp;gt;var&amp;lt;/tt&amp;gt; keyword. Method declaration is identical to how functions are defined.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt; keyword instantiates an object:&lt;br /&gt;
&lt;br /&gt;
 $gb = new guest_book;&lt;br /&gt;
&lt;br /&gt;
Object instantiation is covered in more detail in [[PHP Cookbook/Classes and Objects#Instantiating Objects|Recipe 7.2]].&lt;br /&gt;
&lt;br /&gt;
Inside a class, you can optionally declare properties using &amp;lt;tt&amp;gt;var&amp;lt;/tt&amp;gt;. There's no requirement to do so, but it is a useful way to reveal all the class' variables. Since PHP doesn't force you to predeclare all your variables, it's possible to create one inside a class without PHP throwing an error or otherwise letting you know. This can cause the list of variables at the top of a class definition to be misleading, because it's not the same as the list of variables actually in the class.&lt;br /&gt;
&lt;br /&gt;
Besides declaring a property, you can also assign it a value:&lt;br /&gt;
&lt;br /&gt;
 var $last_visitor = 'Donnan';&lt;br /&gt;
&lt;br /&gt;
You can assign constant values only using this construct:&lt;br /&gt;
&lt;br /&gt;
 var $last_visitor = 'Donnan';         // okay&lt;br /&gt;
 var $last_visitor = 9;                // okay&lt;br /&gt;
 var $last_visitor = array('Jesse');   // okay&lt;br /&gt;
 var $last_visitor = pick_visitor( );   // bad&lt;br /&gt;
 var $last_visitor = 'Chris' . '9';    // bad&lt;br /&gt;
&lt;br /&gt;
If you try to assign something else, PHP dies with a parse error.&lt;br /&gt;
&lt;br /&gt;
To assign a non-constant value to a variable, do it from a method inside the class.&lt;br /&gt;
&lt;br /&gt;
 var $last_visitor;&lt;br /&gt;
 &lt;br /&gt;
 function update($comment, $visitor) {&lt;br /&gt;
     if (!empty($comment)) {&lt;br /&gt;
         array_unshift($this-&amp;gt;comments, $comment);&lt;br /&gt;
         $this-&amp;gt;last_visitor = $visitor;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
If the visitor left a comment, you add it to the top of the array of comments and set that person as the latest visitor to the guest book. The variable &amp;lt;tt&amp;gt;$this&amp;lt;/tt&amp;gt; is a special variable that refers to the current object. So, to access the &amp;lt;tt&amp;gt;$size&amp;lt;/tt&amp;gt; property of an object from inside that object, refer to &amp;lt;tt&amp;gt;$this-&amp;gt;size&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To assign nonconstant values to variables upon instantiation, assign them in the class constructor. The ''class constructor'' is a method automatically called when a new object is created, and it has the same name as your class:&lt;br /&gt;
&lt;br /&gt;
 class guest_book {&lt;br /&gt;
     var $comments;&lt;br /&gt;
     var $last_visitor;&lt;br /&gt;
 &lt;br /&gt;
     function guest_book($user) {&lt;br /&gt;
         $dbh  =  mysql_connect('localhost', 'username', 'password');&lt;br /&gt;
         $db   =  mysql_select_db('sites');&lt;br /&gt;
         $user =  mysql_real_escape_string($user);&lt;br /&gt;
         $sql  = &amp;quot;SELECT comments, last_visitor FROM guest_books WHERE user='$user'&amp;quot;;&lt;br /&gt;
         $r    =  mysql_query($sql);&lt;br /&gt;
 &lt;br /&gt;
         if ($obj  = mysql_fetch_object($r)) {&lt;br /&gt;
             $this-&amp;gt;comments = $obj-&amp;gt;comments;&lt;br /&gt;
             $this-&amp;gt;last_visitor = $obj-&amp;gt;last_visitor;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 $gb = new guest_book('stewart');&lt;br /&gt;
&lt;br /&gt;
Constructors are covered in [[PHP Cookbook/Classes and Objects#Defining Object Constructors|Recipe 7.3]]. Note that &amp;lt;tt&amp;gt;mysql_real_escape_string()&amp;lt;/tt&amp;gt; is new as of PHP 4.3; for earlier versions, use &amp;lt;tt&amp;gt;mysql_escape_string()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Be careful not to mistakenly type &amp;lt;tt&amp;gt;$this-&amp;gt;$size&amp;lt;/tt&amp;gt;. This is legal, but it's not the same as &amp;lt;tt&amp;gt;$this-&amp;gt;size&amp;lt;/tt&amp;gt;. Instead, it accesses the property of the object whose name is the value stored in the &amp;lt;tt&amp;gt;$size&amp;lt;/tt&amp;gt; variable. More often then not, &amp;lt;tt&amp;gt;$size&amp;lt;/tt&amp;gt; is undefined, so &amp;lt;tt&amp;gt;$this-&amp;gt;$size&amp;lt;/tt&amp;gt; appears empty. For more on variable property names, see [[PHP Cookbook/Functions#Creating Functions That Take a Variable Number of Arguments|Recipe 6.6]].&lt;br /&gt;
&lt;br /&gt;
Besides using &amp;lt;tt&amp;gt;-&amp;gt;&amp;lt;/tt&amp;gt; to access a method or member variable, you can also use &amp;lt;tt&amp;gt;::&amp;lt;/tt&amp;gt;. This syntax can access static methods in a class. These methods are identical for every instance of an class, because they can't rely on instance-specific data. For example:&lt;br /&gt;
&lt;br /&gt;
 class convert {&lt;br /&gt;
     // convert from Celsius to Fahrenheit&lt;br /&gt;
     function c2f($degrees) {&lt;br /&gt;
         return (1.8 * $degrees) + 32;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 $f = convert::c2f(100); // 212&lt;br /&gt;
&lt;br /&gt;
To implement inheritance by extending an existing class, use the &amp;lt;tt&amp;gt;extends&amp;lt;/tt&amp;gt; keyword:&lt;br /&gt;
&lt;br /&gt;
 class xhtml extends xml {&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Child classes inherit parent methods and can optionally choose to implement their own specific versions:&lt;br /&gt;
&lt;br /&gt;
 class DB {&lt;br /&gt;
     var $result;&lt;br /&gt;
 &lt;br /&gt;
     function getResult() {&lt;br /&gt;
         return $this-&amp;gt;result;&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     function query($sql) {&lt;br /&gt;
         error_log(&amp;quot;query() must be overridden by a database-specific child&amp;quot;);&lt;br /&gt;
         return false;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 class MySQL extends DB {&lt;br /&gt;
     function query($sql) {&lt;br /&gt;
         $this-&amp;gt;result =  mysql_query($sql);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;MySQL&amp;lt;/tt&amp;gt; class above inherits the &amp;lt;tt&amp;gt;getResult( )&amp;lt;/tt&amp;gt; method unchanged from the parent DB class, but has its own MySQL-specific &amp;lt;tt&amp;gt;query( )&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
Preface the method name with &amp;lt;tt&amp;gt;parent&amp;lt;/tt&amp;gt; :: to explicitly call a parent method:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;function escape($sql) {&lt;br /&gt;
    $safe_sql = mysql_real_escape_string($sql); // escape special characters&lt;br /&gt;
    $safe_sql = parent::escape($safe_sql); // parent method adds '' around $sql&lt;br /&gt;
    return $safe_sql;&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[PHP Cookbook/Classes and Objects#Accessing Overridden Methods|Recipe 7.8]] covers accessing overridden methods.&lt;br /&gt;
&lt;br /&gt;
The underlying engine powering PHP is named Zend. PHP 4 uses Zend Engine 1; PHP 5 will use an updated version — Zend Engine 2 (ZE2). ZE2 has an entirely new object model that allows PHP to support many new object-oriented features: constructors and destructors, private methods, exception handling, cloning, and nested classes. In this chapter, we mention when there's a difference in syntax or features between PHP 4 and what's supported by ZE2, so you can plan for the future.&lt;br /&gt;
&lt;br /&gt;
== Instantiating Objects ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want to create a new instance of an object.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Define the class, then use &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt; to create an instance of the class:&lt;br /&gt;
&lt;br /&gt;
 class user {&lt;br /&gt;
     function load_info($username) {&lt;br /&gt;
        // load profile from database&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 $user = new user;&lt;br /&gt;
 $user-&amp;gt;load_info($_REQUEST['username']);&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
You can instantiate multiple instances of the same object:&lt;br /&gt;
&lt;br /&gt;
 $adam = new user;&lt;br /&gt;
 $adam-&amp;gt;load_info('adam');&lt;br /&gt;
 &lt;br /&gt;
 $dave = new user;&lt;br /&gt;
 $dave-&amp;gt;load_info('adam');&lt;br /&gt;
&lt;br /&gt;
These are two independent objects that happen to have identical information. They're like identical twins; they may start off the same, but they go on to live separate lives.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
[[PHP Cookbook/Classes and Objects#Cloning Objects|Recipe 7.5]] for more on copying objects; [[PHP Cookbook/Classes and Objects#Assigning Object References|Recipe 7.6]] for more on copying objects by reference; documentation on classes and objects at ''http://www.php.net/oop''.&lt;br /&gt;
&lt;br /&gt;
== Defining Object Constructors ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want to define a method that is called when an object is instantiated. For example, you want to automatically load information from a database into an object when it's created.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Define a method with the same name as the class:&lt;br /&gt;
&lt;br /&gt;
 class user {&lt;br /&gt;
     function user($username, $password) {&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
If a function has the same name as its class, it acts as a constructor:&lt;br /&gt;
&lt;br /&gt;
 class user {&lt;br /&gt;
     var $username;&lt;br /&gt;
 &lt;br /&gt;
     function user($username, $password) { &lt;br /&gt;
         if ($this-&amp;gt;validate_user($username, $password)) {&lt;br /&gt;
             $this-&amp;gt;username = $username;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 $user = new user('Grif', 'Mistoffelees'); // using built-in constructor&lt;br /&gt;
&lt;br /&gt;
PHP hasn't always had support for constructors. So people made pseudo-constructors by adopting a naming convention and calling that function after creation:&lt;br /&gt;
&lt;br /&gt;
 class user {&lt;br /&gt;
     ...&lt;br /&gt;
 &lt;br /&gt;
     init($username, $password) { ... }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 $user = new user();&lt;br /&gt;
 $user-&amp;gt;init($username, $password);&lt;br /&gt;
&lt;br /&gt;
If you see this, it's usually a result of legacy code.&lt;br /&gt;
&lt;br /&gt;
However, having a standard name for all constructors makes it easier to call your parent's constructor (because you don't need to know the name of the parent class) and also doesn't require you to modify the constructor if you rename your class name. With Zend Engine 2, the naming conventions of constructors have been modified, and the new constructor name is &amp;lt;tt&amp;gt;_ _construct( )&amp;lt;/tt&amp;gt;. However, for backwards compatibility, if this method isn't found, PHP tries to call a constructor with the same name as the class.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
[[PHP Cookbook/Classes and Objects#Accessing Overridden Methods|Recipe 7.8]] for more on calling parent constructors; documentation on object constructors at ''http://www.php.net/oop.constructor''.&lt;br /&gt;
&lt;br /&gt;
== Destroying an Object ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want to eliminate an object.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Objects are automatically destroyed when a script terminates. To force the destruction of an object, use &amp;lt;tt&amp;gt;unset( )&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
 $car = new car; // buy new car&lt;br /&gt;
 ...&lt;br /&gt;
 unset($car);    // car wreck&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
It's not normally necessary to manually clean up objects, but if you have a large loop, &amp;lt;tt&amp;gt;unset( )&amp;lt;/tt&amp;gt; can help keep memory usage from spiraling out of control.&lt;br /&gt;
&lt;br /&gt;
PHP 4 doesn't have destructors, however Zend Engine 2 supports them with the &amp;lt;tt&amp;gt;_ _destruct( )&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
Documentation on &amp;lt;tt&amp;gt;unset( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/unset''.&lt;br /&gt;
&lt;br /&gt;
== Cloning Objects ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want to make a copy of an existing object. For instance, you have an object containing a message posting and you want to copy it as the basis for a reply message.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt; to assign the object to a new variable:&lt;br /&gt;
&lt;br /&gt;
 $rabbit = new rabbit;&lt;br /&gt;
 $rabbit-&amp;gt;eat();&lt;br /&gt;
 $rabbit-&amp;gt;hop();&lt;br /&gt;
 $baby = $rabbit;&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
In PHP, all that's needed to make a copy of an object is to assign it to a new variable. From then on, each instance of the object has an independent life and modifying one has no effect upon the other:&lt;br /&gt;
&lt;br /&gt;
 class person {&lt;br /&gt;
     var $name;&lt;br /&gt;
 &lt;br /&gt;
     function person ($name) {&lt;br /&gt;
         $this-&amp;gt;name = $name;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 $adam = new person('adam');&lt;br /&gt;
 print $adam-&amp;gt;name;    // adam&lt;br /&gt;
 $dave = $adam;&lt;br /&gt;
 $dave-&amp;gt;name = 'dave';&lt;br /&gt;
 print $dave-&amp;gt;name;    // dave&lt;br /&gt;
 print $adam-&amp;gt;name;    // still adam&lt;br /&gt;
&lt;br /&gt;
Zend Engine 2 allows explicit object cloning via a &amp;lt;tt&amp;gt;_ _clone( )&amp;lt;/tt&amp;gt; method that is called whenever an object is copied. This provides more finely-grained control over exactly which properties are duplicated.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
[[PHP Cookbook/Classes and Objects#Assigning Object References|Recipe 7.6]] for more on assigning objects by reference.&lt;br /&gt;
&lt;br /&gt;
== Assigning Object References ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want to link two objects, so when you update one, you also update the other.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;tt&amp;gt;=&amp;amp;&amp;lt;/tt&amp;gt; to assign one object to another by reference:&lt;br /&gt;
&lt;br /&gt;
 $adam = new user;&lt;br /&gt;
 $dave =&amp;amp; $adam;&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
When you do an object assignment using &amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt;, you create a new copy of an object. So, modifying one doesn't alter the other. But when you use &amp;lt;tt&amp;gt;=&amp;amp;&amp;lt;/tt&amp;gt;, the two objects point at each other, so any changes made in the first are also made in the second:&lt;br /&gt;
&lt;br /&gt;
 $adam = new user;&lt;br /&gt;
 $adam-&amp;gt;load_info('adam');&lt;br /&gt;
 &lt;br /&gt;
 $dave =&amp;amp; $adam;&lt;br /&gt;
 $dave-&amp;gt;load_info('dave');&lt;br /&gt;
&lt;br /&gt;
The values in &amp;lt;tt&amp;gt;$adam&amp;lt;/tt&amp;gt; are equal to those of &amp;lt;tt&amp;gt;$dave&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
[[PHP Cookbook/Classes and Objects#Cloning Objects|Recipe 7.5]] for more on copying object; documentation on references at ''http://www.php.net/references''.&lt;br /&gt;
&lt;br /&gt;
== Calling Methods on an Object Returned by Another Method ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You need to call a method on an object returned by another method.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Assign the object to a temporary variable, and then call the method of that temporary variable:&lt;br /&gt;
&lt;br /&gt;
 $orange = $fruit-&amp;gt;get('citrus');&lt;br /&gt;
 $orange-&amp;gt;peel( );&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
This is necessary because a parse error results from:&lt;br /&gt;
&lt;br /&gt;
 $fruit-&amp;gt;get('citrus')-&amp;gt;peel( );&lt;br /&gt;
&lt;br /&gt;
Zend Engine 2 supports direct dereferencing of objects returned from a method so this workaround is no longer necessary.&lt;br /&gt;
&lt;br /&gt;
== Accessing Overridden Methods ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want to access a method in the parent class that's been overridden in the child.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Prefix &amp;lt;tt&amp;gt;parent&amp;lt;/tt&amp;gt;:: to the method name:&lt;br /&gt;
&lt;br /&gt;
 class shape {&lt;br /&gt;
     function draw( ) {&lt;br /&gt;
         // write to screen&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 class circle extends shape {&lt;br /&gt;
    function draw($origin, $radius) {&lt;br /&gt;
       // validate data&lt;br /&gt;
       if ($radius &amp;gt; 0) {&lt;br /&gt;
           parent::draw( );&lt;br /&gt;
           return true;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       return false;&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
When you override a parent method by defining one in the child, the parent method isn't called unless you explicitly reference it.&lt;br /&gt;
&lt;br /&gt;
In the Solution, we override the &amp;lt;tt&amp;gt;draw( )&amp;lt;/tt&amp;gt; method in the child class, &amp;lt;tt&amp;gt;circle&amp;lt;/tt&amp;gt;, because you want to accept circle specific parameters and validate the data. However, in this case, we still want to perform the generic &amp;lt;tt&amp;gt;shape::draw( )&amp;lt;/tt&amp;gt; action, which does the actual drawing, so we call &amp;lt;tt&amp;gt;parent::draw( )&amp;lt;/tt&amp;gt; inside your method if &amp;lt;tt&amp;gt;$radius&amp;lt;/tt&amp;gt; is greater than 0.&lt;br /&gt;
&lt;br /&gt;
Only code inside the class can use &amp;lt;tt&amp;gt;parent&amp;lt;/tt&amp;gt;::. Calling &amp;lt;tt&amp;gt;parent::draw( )&amp;lt;/tt&amp;gt; from outside the class gets you a parse error. For example, if &amp;lt;tt&amp;gt;circle::draw( )&amp;lt;/tt&amp;gt; checked only the radius, but you also wanted to call &amp;lt;tt&amp;gt;shape::draw( )&amp;lt;/tt&amp;gt;, this wouldn't work:&amp;lt;ref&amp;gt;In fact, it fails with the error &amp;lt;tt&amp;gt;unexpected T_PAAMAYIM_NEKUDOTAYIM&amp;lt;/tt&amp;gt;, which is Hebrew for &amp;quot;double-colon.&amp;quot;&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 $circle = new circle;&lt;br /&gt;
 if ($circle-&amp;gt;draw($origin, $radius)) {&lt;br /&gt;
     $circle-&amp;gt;parent::draw();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
If you want to call the constructor belonging to an object's parent but don't know the parent's class name, use &amp;lt;tt&amp;gt;get_parent_class( )&amp;lt;/tt&amp;gt; to dynamically identify the parent, then combine that with &amp;lt;tt&amp;gt;parent&amp;lt;/tt&amp;gt;:: to call the parent's constructor:&lt;br /&gt;
&lt;br /&gt;
 class circle extends shape {&lt;br /&gt;
     &lt;br /&gt;
     function circle( ) {&lt;br /&gt;
         $parent = get_parent_class($this);&lt;br /&gt;
         parent::$parent( );&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;tt&amp;gt;get_parent_class( )&amp;lt;/tt&amp;gt; takes a class name or an object and returns the name of the object's parent. In order to maintain generality, pass &amp;lt;tt&amp;gt;$this&amp;lt;/tt&amp;gt;, which is the reference to the current object. In this case, the function returns &amp;lt;tt&amp;gt;shape&amp;lt;/tt&amp;gt;. Then, use &amp;lt;tt&amp;gt;parent&amp;lt;/tt&amp;gt;:: to ensure PHP explicitly calls the constructor in the parent class. Calling &amp;lt;tt&amp;gt;$parent( )&amp;lt;/tt&amp;gt; without &amp;lt;tt&amp;gt;parent&amp;lt;/tt&amp;gt;:: runs the risk of calling a method in &amp;lt;tt&amp;gt;circle&amp;lt;/tt&amp;gt; that overrides the parent definition.&lt;br /&gt;
&lt;br /&gt;
The call to &amp;lt;tt&amp;gt;parent::$parent( )&amp;lt;/tt&amp;gt; may look a little odd. However, PHP just substitutes in the parent class name for the &amp;lt;tt&amp;gt;$parent&amp;lt;/tt&amp;gt; variable. Then, because there are &amp;lt;tt&amp;gt;( )&amp;lt;/tt&amp;gt;s after the variable, PHP knows it should make a method call.&lt;br /&gt;
&lt;br /&gt;
It's possible to hardcode the call to &amp;lt;tt&amp;gt;parent::shape( )&amp;lt;/tt&amp;gt; directly into the &amp;lt;tt&amp;gt;circle&amp;lt;/tt&amp;gt; constructor:&lt;br /&gt;
&lt;br /&gt;
 function circle( ) {&lt;br /&gt;
     parent::shape( );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
However, this isn't as flexible as using &amp;lt;tt&amp;gt;get_parent_class( )&amp;lt;/tt&amp;gt;. It is faster, so if you know your object hierarchy isn't going to change, that may be a trade-off you can benefit from.&lt;br /&gt;
&lt;br /&gt;
Last, you can't chain the &amp;lt;tt&amp;gt;parent&amp;lt;/tt&amp;gt; :: keyword to work back to a &amp;quot;grandparent&amp;quot; class, so, &amp;lt;tt&amp;gt;parent::parent::foo( )&amp;lt;/tt&amp;gt; doesn't work.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
[[PHP Cookbook/Classes and Objects#Defining Object Constructors|Recipe 7.3]] for more on object constructors; documentation on class parents at ''http://www.php.net/keyword.parent'' and on &amp;lt;tt&amp;gt;get_parent_class( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/get-parent-class''.&lt;br /&gt;
&lt;br /&gt;
== Using Property Overloading ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want handler functions to execute whenever you read and write object properties. This lets you write generalized code to handle property access in your class.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Use the experimental overload extension and write &amp;lt;tt&amp;gt;_ _get( )&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;_ _set( )&amp;lt;/tt&amp;gt; methods to intercept property requests.&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
Property overloading allows you to seamlessly obscure from the user the actual location of your object's properties and the data structure you use to store them.&lt;br /&gt;
&lt;br /&gt;
For example, the &amp;lt;tt&amp;gt;pc_user&amp;lt;/tt&amp;gt; class shown in [[PHP Cookbook/Classes and Objects#phpckbk-CHP-7-EX-1|Example 7-1]] stores variables in an array, &amp;lt;tt&amp;gt;$data&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;phpckbk-CHP-7-EX-1&amp;quot;&amp;gt;&lt;br /&gt;
'''Example 7-1. pc_user class'''&lt;br /&gt;
&lt;br /&gt;
 require_once 'DB.php';&lt;br /&gt;
 &lt;br /&gt;
 class pc_user {&lt;br /&gt;
 &lt;br /&gt;
     var $data = array();&lt;br /&gt;
 &lt;br /&gt;
     function pc_user($user) {&lt;br /&gt;
         /* connect to database and load information on &lt;br /&gt;
          * the user named $user into $this-&amp;gt;data&lt;br /&gt;
          */&lt;br /&gt;
          &lt;br /&gt;
          $dsn = 'mysql://user:password@localhost/test';&lt;br /&gt;
          $dbh = DB::connect($dsn);&lt;br /&gt;
          if (DB::isError($dbh)) { die ($dbh-&amp;gt;getMessage()); }&lt;br /&gt;
 &lt;br /&gt;
          $user = $dbh-&amp;gt;quote($user);&lt;br /&gt;
          $sql = &amp;quot;SELECT name,email,age,gender FROM users WHERE user LIKE '$user'&amp;quot;;&lt;br /&gt;
          if ($data = $dbh-&amp;gt;getAssoc($sql)) {&lt;br /&gt;
              foreach($data as $key =&amp;gt; $value) {&lt;br /&gt;
                  $this-&amp;gt;data[$key] = $value;&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     function __get($property_name, &amp;amp;$property_value) {&lt;br /&gt;
         if (isset($this-&amp;gt;data[$property_name])) {&lt;br /&gt;
             $property_value = $this-&amp;gt;data[$property_name];&lt;br /&gt;
             return true;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         return false;&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     function __set($property_name, $property_value) {&lt;br /&gt;
         $this-&amp;gt;data[$property_name] = $property_value;&lt;br /&gt;
         return true;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's how to use the &amp;lt;tt&amp;gt;pc_user&amp;lt;/tt&amp;gt; class:&lt;br /&gt;
&lt;br /&gt;
 overload('pc_user');&lt;br /&gt;
 &lt;br /&gt;
 $user = new pc_user('johnwood');&lt;br /&gt;
 $name = $user-&amp;gt;name;                // reads $user-&amp;gt;data['name']&lt;br /&gt;
 $user-&amp;gt;email = 'jonathan@wopr.mil'; // sets  $user-&amp;gt;data['email']&lt;br /&gt;
&lt;br /&gt;
The class constructor connects to the &amp;lt;tt&amp;gt;users&amp;lt;/tt&amp;gt; table in the database and retrieves information about the user named &amp;lt;tt&amp;gt;$user&amp;lt;/tt&amp;gt;. When you set data, &amp;lt;tt&amp;gt;_ _set( )&amp;lt;/tt&amp;gt; rewrites the element inside of &amp;lt;tt&amp;gt;$data&amp;lt;/tt&amp;gt;. Likewise, use &amp;lt;tt&amp;gt;_ _get( )&amp;lt;/tt&amp;gt; to trap the call and return the correct array element.&lt;br /&gt;
&lt;br /&gt;
Using an array as the alternate variable storage source doesn't provide many benefits over a nonoverloaded object, but this feature isn't restricted to simple arrays. For instance, you can make &amp;lt;tt&amp;gt;$this-&amp;gt;email&amp;lt;/tt&amp;gt; return the &amp;lt;tt&amp;gt;get_name( )&amp;lt;/tt&amp;gt; method of an email object. You can also avoid pulling all the user information from the database at once and request it on demand. Another alternative is to use a more persistent storage mechanism, such as files, shared memory, or a database to hold data.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
[[PHP Cookbook/Functions#Returning More Than One Value|Recipe 6.8]] for information on storing objects in external sources; documentation on the overload extension at ''http://www.php.net/overload''.&lt;br /&gt;
&lt;br /&gt;
== Using Method Polymorphism ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want to execute different code depending on the number and type of arguments passed to a method.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
PHP doesn't support method polymorphism as a built-in feature. However, you can emulate it using various type-checking functions. The following &amp;lt;tt&amp;gt;combine( )&amp;lt;/tt&amp;gt; function uses &amp;lt;tt&amp;gt;is_numeric()&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;is_string()&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;is_array()&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;is_bool()&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
 // combine() adds numbers, concatenates strings, merges arrays,&lt;br /&gt;
 // and ANDs bitwise and boolean arguments&lt;br /&gt;
 function combine($a, $b) {&lt;br /&gt;
     if (is_numeric($a) &amp;amp;&amp;amp; is_numeric($b)) {&lt;br /&gt;
         return $a + $b;&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     if (is_string($a)  &amp;amp;&amp;amp; is_string($b))  {&lt;br /&gt;
         return &amp;quot;$a$b&amp;quot;;&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     if (is_array($a)   &amp;amp;&amp;amp; is_array($b))   {&lt;br /&gt;
         return array_merge($a, $b);&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     if (is_bool($a)    &amp;amp;&amp;amp; is_bool($b))    {&lt;br /&gt;
         return $a &amp;amp; $b;&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     return false;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
Because PHP doesn't allow you to declare a variable's type in a method prototype, it can't conditionally execute a different method based on the method's signature, as can Java and C++. You can, instead, make one function and use a &amp;lt;tt&amp;gt;switch&amp;lt;/tt&amp;gt; statement to manually recreate this feature.&lt;br /&gt;
&lt;br /&gt;
For example, PHP lets you edit images using GD. It can be handy in an image class to be able to pass in either the location of the image (remote or local) or the handle PHP has assigned to an existing image stream. [[PHP Cookbook/Classes and Objects#phpckbk-CHP-7-EX-2|Example 7-2]] shows a &amp;lt;tt&amp;gt;pc_Image&amp;lt;/tt&amp;gt; class that does just that.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;phpckbk-CHP-7-EX-2&amp;quot;&amp;gt;&lt;br /&gt;
'''Example 7-2. pc_Image class'''&lt;br /&gt;
&lt;br /&gt;
 class pc_Image {&lt;br /&gt;
 &lt;br /&gt;
     var $handle;&lt;br /&gt;
 &lt;br /&gt;
     function ImageCreate($image) {&lt;br /&gt;
         if (is_string($image)) {&lt;br /&gt;
             // simple file type guessing&lt;br /&gt;
 &lt;br /&gt;
             // grab file suffix&lt;br /&gt;
             $info = pathinfo($image);&lt;br /&gt;
             $extension = strtolower($info['extension']);&lt;br /&gt;
             switch ($extension) {&lt;br /&gt;
             case 'jpg':&lt;br /&gt;
             case 'jpeg':&lt;br /&gt;
                 $this-&amp;gt;handle = ImageCreateFromJPEG($image);&lt;br /&gt;
                 break;&lt;br /&gt;
             case 'png':&lt;br /&gt;
                 $this-&amp;gt;handle = ImageCreateFromPNG($image);&lt;br /&gt;
                 break;&lt;br /&gt;
             default:&lt;br /&gt;
                 die('Images must be JPEGs or PNGs.');&lt;br /&gt;
             }&lt;br /&gt;
         } elseif (is_resource($image)) {&lt;br /&gt;
             $this-&amp;gt;handle = $image;&lt;br /&gt;
         } else {&lt;br /&gt;
             die('Variables must be strings or resources.');&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, any string passed in is treated as the location of a file, so we use &amp;lt;tt&amp;gt;pathinfo()&amp;lt;/tt&amp;gt; to grab the file extension. Once we know the extension, we try to guess which &amp;lt;tt&amp;gt;ImageCreateFrom( )&amp;lt;/tt&amp;gt; function accurately opens the image and create a handle.&lt;br /&gt;
&lt;br /&gt;
If it's not a string, we're dealing directly with a GD stream, which is of type &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt;. Since there's no conversion necessary, we assign the stream directly to &amp;lt;tt&amp;gt;$handle&amp;lt;/tt&amp;gt;. Of course, if you're using this class in a production environment, you'd be more robust in your error handling.&lt;br /&gt;
&lt;br /&gt;
Method polymorphism also encompasses methods with differing numbers of arguments. The code to find the number of arguments inside a method is identical to how you process variable argument functions using &amp;lt;tt&amp;gt;func_num_args( )&amp;lt;/tt&amp;gt;. This is discussed in [[PHP Cookbook/Functions#Creating Functions That Take a Variable Number of Arguments|Recipe 6.6]].&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
[[PHP Cookbook/Functions#Creating Functions That Take a Variable Number of Arguments|Recipe 6.6]] for variable argument functions; documentation on &amp;lt;tt&amp;gt;is_string( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/is-string'', &amp;lt;tt&amp;gt;is_resource( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/is-resource'', and &amp;lt;tt&amp;gt;pathinfo( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/pathinfo''.&lt;br /&gt;
&lt;br /&gt;
== Finding the Methods and Properties of an Object ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want to inspect an object to see what methods and properties it has, which lets you write code that works on any generic object, regardless of type.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;tt&amp;gt;get_class_methods( )&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;get_class_vars( )&amp;lt;/tt&amp;gt; to probe an object for information:&lt;br /&gt;
&lt;br /&gt;
 // learn about cars&lt;br /&gt;
 $car_methods = get_class_methods('car');&lt;br /&gt;
 $car_vars    = get_class_vars('car');&lt;br /&gt;
 &lt;br /&gt;
 // act on our knowledge&lt;br /&gt;
 if (in_array('speed_away', $car_methods)) {&lt;br /&gt;
     $getaway_van = new car;&lt;br /&gt;
     $getaway_van-&amp;gt;speed_away( );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
It's rare to have an object and be unable to examine the actual code to see how it's described. Still, these functions can be useful for projects you want to apply to a whole range of different classes, such as creating automated class documentation, generic object debuggers, and state savers, like &amp;lt;tt&amp;gt;serialize( )&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Both &amp;lt;tt&amp;gt;get_class_methods( )&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;get_class_vars( )&amp;lt;/tt&amp;gt; return an array of values. In &amp;lt;tt&amp;gt;get_class_methods( )&amp;lt;/tt&amp;gt;, the keys are numbers, and the values are the method names. For &amp;lt;tt&amp;gt;get_class_vars( )&amp;lt;/tt&amp;gt;, both variable names and default values (assigned using &amp;lt;tt&amp;gt;var&amp;lt;/tt&amp;gt;) are returned, with the variable name as the key and the default value, if any, as the value.&lt;br /&gt;
&lt;br /&gt;
Another useful function is &amp;lt;tt&amp;gt;get_object_vars( )&amp;lt;/tt&amp;gt; . Unlike its sister function &amp;lt;tt&amp;gt;get_class_vars( )&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;get_object_vars( )&amp;lt;/tt&amp;gt; returns variable information about a specific instance of an object, instead of a generic newly created object.&lt;br /&gt;
&lt;br /&gt;
As a result, you can use it to check the status of an object as it currently exists in a program:&lt;br /&gt;
&lt;br /&gt;
 $clunker = new car;&lt;br /&gt;
 $clunker_vars = get_object_vars($clunker); // we pass the object, not the class&lt;br /&gt;
&lt;br /&gt;
Since you want information about a specific object, you pass the object and not its class name. But, &amp;lt;tt&amp;gt;get_object_vars( )&amp;lt;/tt&amp;gt; returns information in the same format as &amp;lt;tt&amp;gt;get_class_vars( )&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This makes it easy to write quick scripts to see if you're adding new class variables:&lt;br /&gt;
&lt;br /&gt;
 $new_vars = array_diff(array_keys(get_object_vars($clunker)),&lt;br /&gt;
                        array_keys(get_class_vars('car')));&lt;br /&gt;
&lt;br /&gt;
You extract the variable names using &amp;lt;tt&amp;gt;array_keys( )&amp;lt;/tt&amp;gt; . Then, with the help of &amp;lt;tt&amp;gt;array_diff( )&amp;lt;/tt&amp;gt;, you find which variables are in the &amp;lt;tt&amp;gt;$clunker&amp;lt;/tt&amp;gt; object that aren't defined in the &amp;lt;tt&amp;gt;car&amp;lt;/tt&amp;gt; class.&lt;br /&gt;
&lt;br /&gt;
If you just need a quick view at an object instance, and don't want to fiddle with &amp;lt;tt&amp;gt;get_class_vars( )&amp;lt;/tt&amp;gt;, use either &amp;lt;tt&amp;gt;var_dump( )&amp;lt;/tt&amp;gt; , &amp;lt;tt&amp;gt;var_export( )&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;print_r( )&amp;lt;/tt&amp;gt; to print the object's values. Each of these three functions prints out information in a slightly different way; &amp;lt;tt&amp;gt;var_export( )&amp;lt;/tt&amp;gt; can optionally return the information, instead of displaying it.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
[[PHP Cookbook/Variables#Dumping Variable Contents as Strings|Recipe 5.9]] for more on printing variables; documentation on &amp;lt;tt&amp;gt;get_class_vars( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/get-class-vars'', &amp;lt;tt&amp;gt;get_class_methods( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/get-class-methods'', &amp;lt;tt&amp;gt;get_object_vars( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/get-object-vars'', &amp;lt;tt&amp;gt;var_dump( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/var-dump'', &amp;lt;tt&amp;gt;var_export( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/var-export'', and &amp;lt;tt&amp;gt;print_r( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/print-r''.&lt;br /&gt;
&lt;br /&gt;
== Adding Properties to a Base Object ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want to create an object and add properties to it, but you don't want to formally define it as a specific class. This is useful when you have a function that requires an object with certain properties, such as what's returned from &amp;lt;tt&amp;gt;mysql_fetch_object( )&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;imap_header( )&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Use the built-in base class, &amp;lt;tt&amp;gt;stdClass&amp;lt;/tt&amp;gt; :&lt;br /&gt;
&lt;br /&gt;
 $pickle = new stdClass;&lt;br /&gt;
 $pickle-&amp;gt;type = 'fullsour';&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
Just as &amp;lt;tt&amp;gt;array( )&amp;lt;/tt&amp;gt; returns an empty array, creating an object of the type &amp;lt;tt&amp;gt;stdClass&amp;lt;/tt&amp;gt; provides you with an object without properties or methods.&lt;br /&gt;
&lt;br /&gt;
Like objects belonging to other classes, you can create new object properties, assign them values, and check those properties:&lt;br /&gt;
&lt;br /&gt;
 $guss = new stdClass;&lt;br /&gt;
 &lt;br /&gt;
 $guss-&amp;gt;location = 'Essex';&lt;br /&gt;
 print &amp;quot;$guss-&amp;gt;location\n&amp;quot;;&lt;br /&gt;
 $guss-&amp;gt;location = 'Orchard';&lt;br /&gt;
 print &amp;quot;$guss-&amp;gt;location\n&amp;quot;;&lt;br /&gt;
 '''Essex'''&lt;br /&gt;
                '''Orchard'''&lt;br /&gt;
             &lt;br /&gt;
&lt;br /&gt;
Methods, however, can't be defined after an object is instantiated.&lt;br /&gt;
&lt;br /&gt;
It is useful to create objects of &amp;lt;tt&amp;gt;stdClass&amp;lt;/tt&amp;gt; when you have a function that takes a generic object, such as one returned from a database fetching function, but you don't want to actually make a database request. For example:&lt;br /&gt;
&lt;br /&gt;
 function pc_format_address($obj) {&lt;br /&gt;
     return &amp;quot;$obj-&amp;gt;name &amp;lt;$obj-&amp;gt;email&amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 $sql = &amp;quot;SELECT name, email FROM users WHERE id=$id&amp;quot;;&lt;br /&gt;
 $dbh = mysql_query($sql);&lt;br /&gt;
 $obj = mysql_fetch_object($dbh);&lt;br /&gt;
 print pc_format_address($obj);&lt;br /&gt;
 '''David Sklar &amp;lt;david@example.com&amp;gt;'''&lt;br /&gt;
             &lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;pc_print_address( )&amp;lt;/tt&amp;gt; function takes a name and email address and converts it to a format as you might see in the To and From fields in an email program. Here's how to call this function without calling &amp;lt;tt&amp;gt;mysql_fetch_object( )&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
 $obj = new stdClass;&lt;br /&gt;
 $obj-&amp;gt;name = 'Adam Trachtenberg';&lt;br /&gt;
 $obj-&amp;gt;email = 'adam@example.com';&lt;br /&gt;
 print pc_format_address($obj);&lt;br /&gt;
 '''Adam Trachtenberg &amp;lt;adam@example.com&amp;gt;'''&lt;br /&gt;
             &lt;br /&gt;
&lt;br /&gt;
== Creating a Class Dynamically ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want to create a class, but you don't know everything about it until your code is executed.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;tt&amp;gt;eval( )&amp;lt;/tt&amp;gt; with interpolated variables:&lt;br /&gt;
&lt;br /&gt;
 eval(&amp;quot;class van extends $parent_class {&lt;br /&gt;
     function van() {&lt;br /&gt;
         \$this-&amp;gt;$parent_class();&lt;br /&gt;
     }&lt;br /&gt;
 };&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 $mystery_machine = new van;&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
While it's okay in PHP to use variable names to call functions or create objects, it's not okay to define functions and classes in a similar manner:&lt;br /&gt;
&lt;br /&gt;
 $van( );                     // okay&lt;br /&gt;
 $van = new $parent_class    // okay&lt;br /&gt;
 function $van( ) {};         // bad&lt;br /&gt;
 class $parent_class {};     // bad&lt;br /&gt;
&lt;br /&gt;
Trying to do either of the last two examples results in a parser error because PHP expects a string, and you supplied a variable.&lt;br /&gt;
&lt;br /&gt;
So, if you want to make a class named &amp;lt;tt&amp;gt;$van&amp;lt;/tt&amp;gt; and you don't know beforehand what's going to be stored in &amp;lt;tt&amp;gt;$van&amp;lt;/tt&amp;gt;, you need to employ &amp;lt;tt&amp;gt;eval( )&amp;lt;/tt&amp;gt; to do your dirty work:&lt;br /&gt;
&lt;br /&gt;
 eval(&amp;quot;class $van {};&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
There is a performance hit whenever you call &amp;lt;tt&amp;gt;eval( )&amp;lt;/tt&amp;gt;, so high traffic sites should try to restructure their code to avoid this technique when possible. Also, if you're defining your class based on input from users, be sure to escape any potentially dangerous characters.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
[[PHP Cookbook/Classes and Objects#Instantiating an Object Dynamically|Recipe 7.14]] to instantiate an object dynamically; documentation on &amp;lt;tt&amp;gt;eval( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/eval''.&lt;br /&gt;
&lt;br /&gt;
== Instantiating an Object Dynamically ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
You want to instantiate an object, but you don't know the name of the class until your code is executed. For example, you want to localize your site by creating an object belonging to a specific language. However, until the page is requested, you don't know which language to select.&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Use a variable for your class name:&lt;br /&gt;
&lt;br /&gt;
 $language = $_REQUEST['language'];&lt;br /&gt;
 $valid_langs = array('en_US' =&amp;gt; 'US English', &lt;br /&gt;
                      'en_GB' =&amp;gt; 'British English', &lt;br /&gt;
                      'es_US' =&amp;gt; 'US Spanish',&lt;br /&gt;
                      'fr_CA' =&amp;gt; 'Canadian French');&lt;br /&gt;
 &lt;br /&gt;
 if (isset($valid_langs[$language]) &amp;amp;&amp;amp; class_exists($language)) {&lt;br /&gt;
     $lang = new $language;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Discussion ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you may not know the class name you want to instantiate at runtime, but you know part of it. For instance, to provide your class hierarchy a pseudo-namespace, you may prefix a leading series of characters in front of all class names; this is why we often use &amp;lt;tt&amp;gt;pc_&amp;lt;/tt&amp;gt; to represent ''PHP Cookbook'' or PEAR uses &amp;lt;tt&amp;gt;Net_&amp;lt;/tt&amp;gt; before all Networking classes.&lt;br /&gt;
&lt;br /&gt;
However, while this is legal PHP:&lt;br /&gt;
&lt;br /&gt;
 $class_name = 'Net_Ping';&lt;br /&gt;
 $class = new $class_name;               // new Net_Ping&lt;br /&gt;
&lt;br /&gt;
This is not:&lt;br /&gt;
&lt;br /&gt;
 $partial_class_name = 'Ping';&lt;br /&gt;
 $class = new &amp;quot;Net_$partial_class_name&amp;quot;; // new Net_Ping&lt;br /&gt;
&lt;br /&gt;
This, however, is okay:&lt;br /&gt;
&lt;br /&gt;
 $partial_class_name = 'Ping';&lt;br /&gt;
 $class_prefix = 'Net_';&lt;br /&gt;
 &lt;br /&gt;
 $class_name = &amp;quot;$class_prefix$partial_class_name&amp;quot;;&lt;br /&gt;
 $class = new $class_name;               // new Net_Ping&lt;br /&gt;
&lt;br /&gt;
So, you can't instantiate an object when its class name is defined using variable concatenation in the same step. However, because you can use simple variable names, the solution is to preconcatenate the class name.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
&lt;br /&gt;
[[PHP Cookbook/Functions#Using Named Parameters|Recipe 6.5]] for more on variable variables; [[PHP Cookbook/Classes and Objects#Creating a Class Dynamically|Recipe 7.13]] for more on defining a class dynamically; documentation on &amp;lt;tt&amp;gt;class_exists( )&amp;lt;/tt&amp;gt; at ''http://www.php.net/class-exists''.&lt;br /&gt;
== Notes ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Docbook2Wiki</name></author>	</entry>

	</feed>