<?xml version="1.0" encoding="utf-8"?> <!-- $Revision$ --> <sect1 xml:id="language.oop5.overloading" xmlns="http://docbook.org/ns/docbook"> <title>Overloading</title> <para> Overloading in PHP provides means to dynamically <quote>create</quote> properties and methods. These dynamic entities are processed via magic methods one can establish in a class for various action types. </para> <para> The overloading methods are invoked when interacting with properties or methods that have not been declared or are not <link linkend="language.oop5.visibility">visible</link> in the current scope. The rest of this section will use the terms <quote>inaccessible properties</quote> and <quote>inaccessible methods</quote> to refer to this combination of declaration and visibility. </para> <para> All overloading methods must be defined as <literal>public</literal>. </para> <note> <para> None of the arguments of these magic methods can be <link linkend="functions.arguments.by-reference">passed by reference</link>. </para> </note> <note> <para> PHP's interpretation of <quote>overloading</quote> is different than most object oriented languages. Overloading traditionally provides the ability to have multiple methods with the same name but different quantities and types of arguments. </para> </note> <sect2 xml:id="language.oop5.overloading.changelog"> &reftitle.changelog; <para> <informaltable> <tgroup cols="2"> <thead> <row> <entry>&Version;</entry> <entry>&Description;</entry> </row> </thead> <tbody> <row> <entry>5.3.0</entry> <entry> Added <function>__callStatic</function>. Added warning to enforce public visibility and non-static declaration. </entry> </row> <row> <entry>5.1.0</entry> <entry> Added <function>__isset</function> and <function>__unset</function>. </entry> </row> </tbody> </tgroup> </informaltable> </para> </sect2> <sect2 xml:id="language.oop5.overloading.members"> <title>Property overloading</title> <methodsynopsis> <type>void</type><methodname>__set</methodname> <methodparam><type>string</type><parameter>name</parameter></methodparam> <methodparam><type>mixed</type><parameter>value</parameter></methodparam> </methodsynopsis> <methodsynopsis> <type>mixed</type><methodname>__get</methodname> <methodparam><type>string</type><parameter>name</parameter></methodparam> </methodsynopsis> <methodsynopsis> <type>bool</type><methodname>__isset</methodname> <methodparam><type>string</type><parameter>name</parameter></methodparam> </methodsynopsis> <methodsynopsis> <type>void</type><methodname>__unset</methodname> <methodparam><type>string</type><parameter>name</parameter></methodparam> </methodsynopsis> <para> <function>__set</function> is run when writing data to inaccessible properties. </para> <para> <function>__get</function> is utilized for reading data from inaccessible properties. </para> <para> <function>__isset</function> is triggered by calling <function>isset</function> or <function>empty</function> on inaccessible properties. </para> <para> <function>__unset</function> is invoked when <function>unset</function> is used on inaccessible properties. </para> <para> The <varname>$name</varname> argument is the name of the property being interacted with. The <function>__set</function> method's <varname>$value</varname> argument specifies the value the <varname>$name</varname>'ed property should be set to. </para> <para> Property overloading only works in object context. These magic methods will not be triggered in static context. Therefore these methods should not be declared <link linkend="language.oop5.static">static</link>. As of PHP 5.3.0, a warning is issued if one of the magic overloading methods is declared <literal>static</literal>. </para> <note> <para> The return value of <function>__set</function> is ignored because of the way PHP processes the assignment operator. Similarly, <function>__get</function> is never called when chaining assignments together like this: <literal><![CDATA[ $a = $obj->b = 8; ]]></literal> </para> </note> <note> <para> It is not possible to use overloaded properties in other language constructs than <function>isset</function>. This means if <function>empty</function> is called on an overloaded property, the overloaded method is not called. </para> <para> To workaround that limitation, the overloaded property must be copied into a local variable in the scope and then be handed to <function>empty</function>. </para> </note> <example> <title> Overloading properties via the <function>__get</function>, <function>__set</function>, <function>__isset</function> and <function>__unset</function> methods </title> <programlisting role="php"> <![CDATA[ <?php class PropertyTest { /** Location for overloaded data. */ private $data = array(); /** Overloading not used on declared properties. */ public $declared = 1; /** Overloading only used on this when accessed outside the class. */ private $hidden = 2; public function __set($name, $value) { echo "Setting '$name' to '$value'\n"; $this->data[$name] = $value; } public function __get($name) { echo "Getting '$name'\n"; if (array_key_exists($name, $this->data)) { return $this->data[$name]; } $trace = debug_backtrace(); trigger_error( 'Undefined property via __get(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_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($this->data[$name]); } /** Not a magic method, just here for example. */ public function 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 "Let's experiment with the private property named 'hidden':\n"; echo "Privates are visible inside the class, so __get() not used...\n"; echo $obj->getHidden() . "\n"; echo "Privates not visible outside of class, so __get() is used...\n"; echo $obj->hidden . "\n"; ?> ]]> </programlisting> &example.outputs; <screen role="php"> <![CDATA[ Setting 'a' to '1' Getting 'a' 1 Is 'a' set? bool(true) Unsetting 'a' Is 'a' set? bool(false) 1 Let's experiment with the private property named 'hidden': Privates are visible inside the class, so __get() not used... 2 Privates not visible outside of class, so __get() is used... Getting 'hidden' Notice: Undefined property via __get(): hidden in <file> on line 70 in <file> on line 29 ]]> </screen> </example> </sect2> <sect2 xml:id="language.oop5.overloading.methods"> <title>Method overloading</title> <methodsynopsis> <type>mixed</type><methodname>__call</methodname> <methodparam><type>string</type><parameter>name</parameter></methodparam> <methodparam><type>array</type><parameter>arguments</parameter></methodparam> </methodsynopsis> <methodsynopsis> <type>mixed</type><methodname>__callStatic</methodname> <methodparam><type>string</type><parameter>name</parameter></methodparam> <methodparam><type>array</type><parameter>arguments</parameter></methodparam> </methodsynopsis> <para> <function>__call</function> is triggered when invoking inaccessible methods in an object context. </para> <para> <function>__callStatic</function> is triggered when invoking inaccessible methods in a static context. </para> <para> The <varname>$name</varname> argument is the name of the method being called. The <varname>$arguments</varname> argument is an enumerated array containing the parameters passed to the <varname>$name</varname>'ed method. </para> <example> <title> Overloading methods via the <function>__call</function> and <function>__callStatic</function> methods </title> <programlisting role="php"> <![CDATA[ <?php class MethodTest { public function __call($name, $arguments) { // Note: value of $name is case sensitive. echo "Calling object 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(', ', $arguments). "\n"; } } $obj = new MethodTest; $obj->runTest('in object context'); MethodTest::runTest('in static context'); // As of PHP 5.3.0 ?> ]]> </programlisting> &example.outputs; <screen role="php"> <![CDATA[ Calling object method 'runTest' in object context Calling static method 'runTest' in static context ]]> </screen> </example> </sect2> </sect1> <!-- Keep this comment at the end of the file Local variables: mode: sgml sgml-omittag:t sgml-shorttag:t sgml-minimize-attributes:nil sgml-always-quote-attributes:t sgml-indent-step:1 sgml-indent-data:t indent-tabs-mode:nil sgml-parent-document:nil sgml-default-dtd-file:"~/.phpdoc/manual.ced" sgml-exposed-tags:nil sgml-local-catalogs:nil sgml-local-ecat-files:nil End: vim600: syn=xml fen fdm=syntax fdl=2 si vim: et tw=78 syn=sgml vi: ts=1 sw=1 -->