Web студия "GrandView"
  Главная   Написать Контакты
   
   
О проекте
Руководство php
 

Magic Methods

The function names __construct, __destruct (see Constructors and Destructors), __call, __get, __set, __isset, __unset (see Overloading), __sleep, __wakeup, __toString, __set_state, __clone and __autoload 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.

Предостережение

PHP reserves all function names starting with __ as magical. It is recommended that you do not use function names with __ in PHP unless you want some documented magic functionality.

__sleep and __wakeup

serialize() checks if your class has a function with the magic name __sleep. If so, that function is executed prior to any serialization. It can clean up the object and is supposed to return an array with the names of all variables of that object that should be serialized.

The intended use of __sleep is to close any database connections that the object may have, commit pending data or perform similar cleanup tasks. Also, the function is useful if you have very large objects which do not need to be saved completely.

Conversely, unserialize() checks for the presence of a function with the magic name __wakeup. If present, this function can reconstruct any resources that the object may have.

The intended use of __wakeup is to reestablish any database connections that may have been lost during serialization and perform other reinitialization tasks.

Пример 19-27. Sleep and wakeup

<?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()
    {
       
mysql_close($this->link);
    }
   
    public function
__wakeup()
    {
       
$this->connect();
    }
}
?>

__toString

The __toString method allows a class to decide how it will react when it is converted to a string.

Пример 19-28. Simple example

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

Результат выполнения данного примера:

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().

__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, ...).



Ключевое слово "final"> <Patterns
Last updated: Sat, 27 Jan 2007
 
add a note add a note User Contributed Notes
Magic Methods
smoseley at transio dot com
30-Oct-2007 05:15
Suggestion: add a __toArray() magic method that would default as exportation of an object's properties in an associative array.
amir_abiri at ipcmedia dot com
24-Jul-2007 04:58
Another small thing that is important to note about __sleep() and privte member variables:

<?php
class A
{
  private
$a;
 
  public function
__construct()
  {
   
$this->a = 1;
  }
}

class
B extends A
{
  protected
$b;
 
  public function
__construct()
  {
   
parent::__construct();
   
$this->b = 2;
  }
 
  function
__sleep()
  {
    return array(
'a', 'b');
  }
}

serialize(new B);
?>

result:
Notice: serialize(): "a" returned as member variable from __sleep() but does not exist in ...

To summerize: in a given class hierarchy in which parent classes contain private member variables, those variables are serialized when __sleep() is not defined. However, once __sleep() is defined, there is no way to make those private member variables serialized as well. From that point on, serialization is performed from the visibility scope of the subclass.

It is particularly important to note this little quirk when designing base classes that their derivables may be serialized, or when subclassing an external library class.
alejandro dot gama at gmail dot com
09-May-2007 07:47
Referering my previus note: there was an error in the code. But i find a better way:

<?
session_start();

class Classes{
  private $name;
  private $statics;
   
  function __construct($name){
    $this->name=$name;
    $this->statics=array();
  }
   
  function setStatic($k,$v){
    if(!is_resource($v))
      $this->statics[$k]=$v;
  }
   
   
  function __wakeup(){
    foreach($this->statics as $k=>$v)
      eval($this->name."::\$".$k."=\$this->statics['".$k."'];");
  }
}

function storeStaticAttributes(){
  $classes=get_declared_classes();
  foreach($classes as $name){
    $reflect=new ReflectionClass($name);

    if($reflect->isUserDefined()){
      $statics=$reflect->getStaticProperties();

      if(empty($_SESSION["_classes"]))
        $_SESSION["_classes"]=array();
           
      if(empty($_SESSION["_classes"][$name]))
        $_SESSION["_classes"][$name]=new Classes($name);

      foreach($statics as $k=>$v)
        $_SESSION["_classes"][$name]->setStatic($k,$v);   
    }
  }
}
register_shutdown_function('storeStaticAttributes');
?>
alejandro dot gama at gmail dot com
09-May-2007 03:09
There is a trick to store static attributes with the objects in the $_SESSION array:

<?
session_start();

class Classes{
  private $name;
  private $statics;

  function __construct($name){
    $this->name=$name;
    $this->statics=array();
  }

  function setStatic($key,$value){
    if(!is_resource($value))
      $this->statics[$key]=$value;
  }
   
  function __wakeup(){
    foreach($this->statics as $k=>$v)
      eval($this->name."::\$".$k."=\$this->statics['".$k."'];");
    unset($this);
  }
}

class Object{
  function __sleep(){
    $name=get_class($this);

    if(empty($_SESSION["_classes"]))
      $_SESSION["_classes"]=array();
       
    if(empty($_SESSION["_classes"][$name])){
      $_SESSION["_classes"][$name]=new Classes($name);
   
      $from_object=get_object_vars($this);
      $from_class=get_class_vars($name);

      if(count($from_object)>0)
        foreach($from_object as $k=>$value)
          if($clave=array_search($k,$from_class))
            unset($from_class[$clave]);

      if(count($from_class)>0)
        foreach($from_class as $k=>$v)
          $_SESSION["_classes"][$name]->setStatic($k,$v);
    }
               
  return $from_object;
  }
   
}
?>

You must inherit all your objects from Object and when you save them in the session the static method from their classes will be store and restore to their original state.

You must have one object from each class (that has static attributes) stored in the session.
Travis Swicegood
08-May-2007 07:43
There is no need to use eval() to mimic mixins (i.e., multiple inheritance) within PHP 5.  You only need to:

<?php

class MyClass
{
    private
$_obj = null;
    public function
__construct($obj)
    {
       
$this->_obj = $obj;
    }

    public function
__call($method, $args)
    {
        if (!
method_exists($this->_obj, $method)) {
            throw new
Exception("unknown method [$method]");
        }

        return
call_user_func_array(
            array(
$this->_obj, $method),
           
$args
       
);
    }
}

?>

You could just as easily add an addMixin() method that would allow you to add multiple objects to an array, and then iterate over that array until you found the right method.  As noted, these are referred to as a Mixins in other languages.
adar at darkpoetry dot de
04-May-2007 06:09
Maybe not really new and all in all definitely not the best solution,but if you cant extend a class (if your class alreay extends an abstract or other things like that) you can 'fake' a extend.

<?php
class MyClass
       
extends SomeAbstractUnknownClass {

    private
$classObject;

    public function
__construct ( classObject $classToExtend ) {
       
$this->classObject = $classToExtend;
    }

    public function
__call($func, $var) {
        if ( !
count($var) ) {
            return
$this->classObject->$func($var);
        } else {
           
$str = '';
           
$values = array_values($var);
            for (
$i=0; $i<count($values); $i++ ) {
               
$str .= "'".$values[$i]."' ,";
            }  
           
$str = substr($str, 0, -2);
            return eval(
'return $this->classObject->'.$func.'('.$str.');');
        }  
    }  
}
?>

So if you'll do a $myClass->unknownMethod() and it is found neither in MyClass nor in SomeAbstractUnknownClass, MyClass will try to call this method in $classObject.

I use this for 'extending' a UserObject-Class which already extends an other one.

Better solutions are always welcome ;)
D
Новости
11 июля 2007
Сайт запущен
© 2007 info@grandviewstudio.com
Z058440144362 Z348613067571