php tutorial magic method using example of php magic function

  • 2020-12-22 17:35:59
  • OfStack


/** PHP Put all in __ Class methods that begin with (two underscores) are used as magic methods. So when you define your own class methods, don't start with  __ For the prefix.  * */
// __toString , __set , __get__isset() , __unset()
/*
  The __toString method allows a class to decide how it will react when it is converted to a string.
  __set() is run when writing data to inaccessible members.
  __get() is utilized for reading data from inaccessible members.
  __isset() is triggered by calling isset() or empty() on inaccessible members.
  __unset() is invoked when unset() is used on inaccessible members.
 */
class TestClass {
    private $data = array();
    public $foo;
    public function __construct($foo) {
        $this->foo = $foo;
    }
    public function __toString() {
        return $this->foo;
    }
    public function __set($name, $value) {
        echo "__set, Setting '$name' to '$value'\n";
        $this->data[$name] = $value;
    }
    public function __get($name) {
        echo "__get, Getting '$name'\n";
        if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }
    }
    /** As of PHP 5.1.0 */
    public function __isset($name) {
        echo "__isset, Is '$name' set?\n";
        return isset($this->data[$name]);
    }
    /** As of PHP 5.1.0 */
    public function __unset($name) {
        echo "__unset, Unsetting '$name'\n";
        unset($this->data[$name]);
    }
}
$obj = new TestClass('Hello');
echo "__toString, $obj\n";
$obj->a = 1;
echo $obj->a . "\n\n";
var_dump(isset($obj->a));
unset($obj->a);
var_dump(isset($obj->a));
echo "\n\n"; 
/**
   The output results are as follows: 
  __toString, Hello
  __set, Setting 'a' to '1'
  __get, Getting 'a'
  __isset, Is 'a' set?
  bool(true)
  __unset, Unsetting 'a'
  __isset, Is 'a' set?
  bool(false)
 **/
 
// __call  __callStatic
/*
  mixed __call ( string $name , array $arguments )
  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.
  The $name argument is the name of the method being called.
  The $arguments argument is an enumerated array containing the parameters passed to the $name'ed method.
 */
class MethodTest {
    public function __call($name, $arguments) {
        // Note: value of $name is case sensitive.
        echo "__call, 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 "__callStatic, Calling static method '$name' " . implode(', ', $arguments) . "\n";
    }
}
$obj = new MethodTest;
$obj->runTest('in object context', 'param2', 'param3');
//MethodTest::runTest('in static context'); // As of PHP 5.3.0
echo "\n\n"; 
/**
  The output results are as follows: 
 __call, Calling object method 'runTest' in object context, param2, param3
  string(10) "__invoke: "
 */
 
// __invoke
/* 
  The __invoke method is called when a script tries to call an object as a function.
  Note: This feature is available since PHP 5.3.0.
*/
class CallableClass {
    function __invoke($x) {
        var_dump($x);
    }
}
$obj = new CallableClass;
//$obj(5);
var_dump('__invoke: ' . is_callable($obj));
echo "\n\n"; 
 
 
// __sleep  __wakeup
/*
   serialization serialize You can include variables in objects , Into a continuum bytes data .  You can put the serialized variables in there 1 In a file or over the network transfer . 
   Then it is de-serialized back to the original data .  The class you defined before de-serializing the object of the class ,PHP Properties and methods of its object can be successfully stored . 
   Sometimes you might 1 Five objects are executed immediately after de-serialization .  For this purpose ,PHP Will automatically look for __sleep and __wakeup methods .
   when 1 Two objects are serialized ,PHP Will be called __sleep methods ( If it exists ).  In anti-serialization 1 After an object ,PHP  Will be called __wakeup methods . 
   Neither method accepts arguments . __sleep Method must return 1 An array , Contains properties that need to be serialized . PHP The values of other attributes are discarded . 
   If there is no __sleep methods ,PHP All attributes will be saved . The following example shows how to use it __sleep and __wakeup Method to serialize 1 An object . 
  Id Attributes are 1 A temporary property that is not intended to be retained in an object . __sleep Methods are guaranteed not to be included in the serialized object id attribute . 
   When you de-serialize 1 a User object ,__wakeup Method to establish id The new value of the .  This example is designed to be self-sustaining . 
   In actual development , You may find included resources ( Such as images or data streams ) Objects need these methods 
 */
class User {
    public $name;
    public $id;
    function __construct() {
        //give user a unique ID  give 1 A difference between   the ID
        $this->id = uniqid();
    }
    //__sleep The type of the return value is an array, and the values in the array are fields that do not need to be serialized id
    function __sleep() {
        //do not serialize this->id  Don't serialization id
        return(array("name"));
    }
    function __wakeup() {
        //give user a unique ID
        $this->id = uniqid();
    }
}
//create object  Set up 1 A equipment 
$u = new User;
$u->name = "Leon"; //serialize it  serialization   Note the non-serialization id attribute ,id Is abandoned 
$s = serialize($u);
echo "__sleep, __wakeup, s: $s"; //unserialize it  The serialization  id Is reassigned 
$u2 = unserialize($s); //$u and $u2 have different IDs $u and $u2 Is there a difference   the ID
print_r($u);
print_r($u2);
echo "\n\n"; 
/**
  The output results are as follows: 
  __sleep, __wakeup, s: O:4:"User":1:{s:4:"name";s:4:"Leon";}
  User Object
  (
  [name] => Leon
  [id] => 4db1b17640da1
  )
  User Object
  (
  [name] => Leon
  [id] => 4db1b17640dbc
  )
 */

// __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, ...).
 */
class A {
    public $var1;
    public $var2;
    public static function __set_state($an_array) { // As of PHP 5.1.0
        //$an_array The printout is an array, not the object passed on the call 
        print_r($an_array);
        $obj = new A;
        $obj->var1 = $an_array['var1'];
        $obj->var2 = $an_array['var2'];
        return $obj;
    }
}
$a = new A;
$a->var1 = 5;
$a->var2 = 'foo';
echo "__set_state:\n";
eval('$b = ' . var_export($a, true) . ';'); 
// $b = A::__set_state(array(
// 'var1' => 5,
// 'var2' => 'foo',
// ));
var_dump($b);
echo "\n\n"; 
/**
   The output results are as follows: 
  __set_state:
  Array
  (
  [var1] => 5
  [var2] => foo
  )
  object(A)#5 (2) {
  ["var1"]=>
  int(5)
  ["var2"]=>
  string(3) "foo"
  }
 */
 
// __clone
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("__clone, Original Object:\n");
print_r($obj);
print("__clone, Cloned Object:\n");
print_r($obj2);
echo "\n\n";
/**
  The output results are as follows: 
 __clone, Original Object:
  MyCloneable Object
  (
  [object1] => SubObject Object
  (
  [instance] => 1
  ) [object2] => SubObject Object
  (
  [instance] => 2
  ))
  __clone, Cloned Object:
  MyCloneable Object
  (
  [object1] => SubObject Object
  (
  [instance] => 3
  ) [object2] => SubObject Object
  (
  [instance] => 2
  )) 
 */


Related articles: