zoukankan      html  css  js  c++  java
  • PHP Magic Methods

    Magic Methods

    The function names __construct()__destruct()__call()__callStatic()

    __get()__set()__isset()__unset()__sleep()__wakeup()__toString()__invoke()__set_state() and __clone() 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.

     

    Constructor

    void __construct ([ mixed $args [, $... ]] )
    <?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 BaseClass();
    $obj = new SubClass();
    ?>

     

    Destructor

    void __destruct ( void )
    <?php
    class MyDestructableClass {
       function __construct() {
           print "In constructor\n";
           $this->name = "MyDestructableClass";
       }
    
       function __destruct() {
           print "Destroying " . $this->name . "\n";
       }
    }
    
    $obj = new MyDestructableClass();
    ?>

     

    Property overloading

    public void __set ( string $name , mixed $value )
    public mixed __get ( string $name )
    public bool __isset ( string $name )
    public void __unset ( string $name )

    __set() is run when writing data to inaccessible properties.

    __get() is utilized for reading data from inaccessible properties.

    __isset() is triggered by calling isset() or empty() on inaccessible properties.

    __unset() is invoked when unset() is used on inaccessible properties.

    <?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";
    ?>

    The above example will output:

    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

     

    Method overloading

    public mixed __call ( string $name , array $arguments )
    public static mixed __callStatic ( string $name , array $arguments )

    __call() is triggered when invoking inaccessible methods in an object context.

    __callStatic() is triggered when invoking inaccessible methods in a static context.

    <?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
    ?>

    The above example will output:

    Calling object method 'runTest' in object context
    Calling static method 'runTest' in static context

    __sleep and __wakeup()

    public array __sleep ( void )
    void __wakeup ( void )
    <?php
    class Connection
    {
        protected $link;
        private $server, $username, $password, $db;
        
        public function __construct($server, $username, $password, $db)
        {
            $this->server = $server;
            $this->username = $username;
            $this->password = $password;
            $this->db = $db;
            $this->connect();
        }
        
        private function connect()
        {
            $this->link = mysql_connect($this->server, $this->username, $this->password);
            mysql_select_db($this->db, $this->link);
        }
        
        public function __sleep()
        {
            return array('server', 'username', 'password', 'db');
        }
        
        public function __wakeup()
        {
            $this->connect();
        }
    }
    ?>

    __tostring()

    public string __toString ( void )

    The __toString() method allows a class to decide how it will react when it is treated like a string. For example, what echo $obj; will print. This method must return a string, as otherwise a fatal E_RECOVERABLE_ERROR level error is emitted.

    <?php
    // Declare a simple class
    class TestClass
    {
        public $foo;
    
        public function __construct($foo)
        {
            $this->foo = $foo;
        }
    
        public function __toString()
        {
            return $this->foo;
        }
    }
    
    $class = new TestClass('Hello');
    echo $class;
    ?>

    The above example will output:

    Hello

    It is worth noting that before PHP 5.2.0 the __toString() method was only called when it was directly combined with echo or print. Since PHP 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, converting objects without __toString() method to string would cause E_RECOVERABLE_ERROR.

    __clone()

    void __clone ( void )

    Once the cloning is complete, if a __clone() method is defined, then the newly created object's __clone() method will be called, to allow any necessary properties that need to be changed.

    <?php
    class SubObject
    {
        static $instances = 0;
        public $instance;
    
        public function __construct() {
            $this->instance = ++self::$instances;
        }
    
        public function __clone() {
            $this->instance = ++self::$instances;
        }
    }
    
    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");
    print_r($obj2);
    
    ?>

    The above example will output:

    Original Object:
    MyCloneable Object
    (
        [object1] => SubObject Object
            (
                [instance] => 1
            )
    
        [object2] => SubObject Object
            (
                [instance] => 2
            )
    
    )
    Cloned Object:
    MyCloneable Object
    (
        [object1] => SubObject Object
            (
                [instance] => 3
            )
    
        [object2] => SubObject Object
            (
                [instance] => 2
            )
    
    )

     

  • 相关阅读:
    《Microsoft Sql server 2008 Internals》读书笔记第十一章DBCC Internals(2)
    《Microsoft Sql server 2008 Internals》读书笔记第十一章DBCC Internals(9)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(10)
    CKEditor在asp.net环境下的使用一例
    《Microsoft Sql server 2008 Internals》读书笔记第五章Table(7)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(11)
    千万数据的连续ID表,快速读取其中指定的某1000条数据?
    javascript中的float运算精度
    .Net与Java的互操作(.NET StockTrader微软官方示例应用程序)
    《Microsoft Sql server 2008 Internals》读书笔记第十一章DBCC Internals(6)
  • 原文地址:https://www.cnblogs.com/bruceleeliya/p/2736772.html
Copyright © 2011-2022 走看看