Магия в PHP

Краткое содержание лекции

Теоретические задания | Практические задания

Магические методы вызываются самим PHP при определенных обстоятельствах, начинаются с символа __. Мое мнение, что наличие некоторых из них в вашем коде, может заставить тимлида выписать вам направление к врачу.

__construct()

<?php
class Test
{
    /**
     * @var \DateTime
     */
    private $creaionDate;

    public function __construct()
    {
        $this->creationDate = new DateTime();
    }
}
?>
<?php
class Test
{
    /**
     * @var \Service
     */
    private $service;

    public function __construct(\Service $service)
    {
        $this->service = $service;
    }
}
?>

__destruct()

<?php
class Test
{
    /**
     * @var resource
     */
    private $file;

    public function __construct()
    {
        $this->file = fopen('/tmp/log.txt', 'w');
    }

    public function __destruct()
    {
        fclose($this->file);
    }
}
?>

__call(), __callStatic()

<?php
class Test
{
    /**
     * @var string
     */
    private $username;

    /**
     * @var string $method
     * @var array $args
     */
    public function __call($method, $args)
    {
        if ($method == 'getName') {
            return $this->getUsername();
        }

        return false;
    }

    public function getUsername()
    {
        return $this->username;
    }
}
?>
<?php
class Test
{
    /**
     * @var string $method
     * @var array $args
     */
    public function __call($method, $args)
    {
      echo "unknown method " . $method;

      return false;
    }
}
?>

__get(), __set(), __isset(), __unset()

<?php
class Test
{
    /**
     * @var string
     */
    private $username;

    /**
     * @var string $name
     */
    public function __get($name)
    {
        if ($name == 'name') {
            return $this->username;
        }

        return false;
    }
}
?>
<?php
$test = new Test();
echo $test->name;
?>
<?php
class Test {
    private $firstField;
    private $secondField;

    public function __get($property) {
            if (property_exists($this, $property)) {
                return $this->$property;
            }
    }

    public function __set($property, $value) {
        if (property_exists($this, $property)) {
            $this->$property = $value;
        }
    }
}
?>
<?php
$test = new Test();
echo $test->name;
$test->firstField = 12;
echo $test->firstField;
?>

__sleep(), __wakeup()

<?php
//Example from http://php.net/manual/ru/language.oop5.magic.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();
    }
}
?>

__clone()

__toString()

<?php
class News
{
    public $id;

    public function __toString()
    {
        return 'News #' . $this->id;
    }
}
?>
<?php
$news = new News();
$news->id = 5;
echo $news;
?>
<?php
class Workflow
{
    private $action;

    private $status;

    /**
     * Converts workflow string to class attibutes 
     * "is ready for:printing"
     *
     * @param string $workflowAsString
     */
    public function __construct($workflowAsString)
    {
        $tmp = explode(':', $workflowAsString);
        $this->status = $tmp[0];
        $this->action = $tmp[1];
        unset($tmp);
    }

    public function __toString()
    {
        return $this->status . ':' . $this->action;
    }
}
?>

__invoke()

<?php
class News
{
    public $id;

    public function __invoke($value)
    {
        $this->id = $value;
    }
}
?>
<?php
$news = new News();
$news(45);
echo $news->id;
?>

__set_state()

Полезные ссылки