Métodos mágicos PHP

Las clases PHP tiene una serie de nombres de métodos reservados llamados métodos “mágicos”. Se identifican por el prefijo “__”  y ninguna clase puede tener métodos con estos nombres a menos que se desee aplicar la funcionalidad mágica asociada a cada uno de ellos.

metodos mágicos PHP
metodos mágicos PHP

__construct()

El constructor se encarga de recibir datos para inicializar los objetos.

class Post
{
    protected $id;
    protected $title;
    protected $content;
    private   $author;

    /**
     * Post constructor.
     * @param $id
     * @param $title
     * @param $content
     * @param $author
     */
    public function __construct($id, $title, $content, $author)
    {
        $this->id = $id;
        $this->title = $title;
        $this->content = $content;
        $this->author = $author;
    }

}


$post = new Post(1, 'Sample post', 'Content sample.', 'Juan Luis');

//Las propiedades del objeto Post toman los valores pasados por constructor
var_dump($post);

//Resultado
object(Post)[1]
  protected 'id' => int 1
  protected 'title' => string 'Sample post' (length=11)
  protected 'content' => string 'Content sample.' (length=15)
  private 'author' => string 'Juan Luis' (length=9)

__call()

Se ejecuta cuando llamamos a un método que no existe. También existe el método __callStatic que funciona igual pero cuando llamamos a un método estático.

class Post
{
    protected $id;
    protected $title;
    protected $content;
    private   $author;

    ... 

    function __call($name, $arguments)
    {
       echo $this->$name;
    }

}

$post = new Post(1, 'Sample post', 'Content sample.', 'Juan Luis');

//devuelve el author del objeto Post como si se tratase de un getAurhor()
$post->author();

Un ejemplo real sería el utilizado por Doctrine ORM al utilizar los métodos findByNombrePropiedad o findOneByNombrePropiedad que realizan una consulta a BD con el método seleccionado aunque no exista dicha consulta en el repository.

__get()

Se ejecuta cuando llamamos a una propiedad que no exista o que sea privada.

<?php

class Post
{
    protected $id;
    protected $title;
    protected $content;
    private   $author;

   ...

    function __get($name)
    {
        return "This property is not accessible or not exit";
    }
}

$post = new Post(1, 'Sample post', 'Content sample.', 'Juan Luis');

//Hace una llamada a la propiedad PRIVADA author
echo $post->author; //Devuelve 'This property is not accessible or not exit'

__set()

Se ejecuta cuando añadimos un valor a una propiedad privada

<?php

class Post
{
    protected $id;
    protected $title;
    protected $content;
    private   $author;
   
    ...  

    function __set($name, $value)
    {
        $this->$name = $value;
    }

}

$post = new Post(1, 'Sample post', 'Content sample.', 'Juan Luis');
//establezco a 'Anonimo' la propiedad PRIVADA author
$post->author = 'Anonimo';

var_dump($post);
//resultado
object(Post)[1]
  protected 'id' => int 1
  protected 'title' => string 'Sample post' (length=11)
  protected 'content' => string 'Content sample.' (length=15)
  private 'author' => string 'Anonimo' (length=7)

__isset()

Se ejecuta cuando consultamos si existe una propiedad que no existe, es privada o protegida con la función isset() o empty()

<?php

class Post
{
    protected $id;
    public $title;
    protected $content;
    private   $author;

    public function __construct($id, $title, $content, $author)
    {
        $this->id = $id;
        $this->title = $title;
        $this->content = $content;
        $this->author = $author;
    }

    function __isset($name)
    {
       echo  "This property no existe";
    }
}

$post = new Post(1, 'Sample post', 'Content sample.', 'Juan Luis');

empty($post->other); //This property no existe

isset($post->otherProperty); //This property no existe

__unset()

Se ejecuta cuando intentamos borrar una propiedad que no existe, es privada o protegida con la función unset()

<?php

class Post
{
    protected $id;
    public $title;
    protected $content;
    private   $author;

    public function __construct($id, $title, $content, $author)
    {
        $this->id = $id;
        $this->title = $title;
        $this->content = $content;
        $this->author = $author;
    }

    function __unset($name)
    {
        echo "Yoy Cant not delete ".$name;
    }
}

$post = new Post(1, 'Sample post', 'Content sample.', 'Juan Luis');

unset($post->id); //Yoy Cant not delete id
var_dump($post);

__sleep() y __wakeup()

La serialización es un proceso que convierte un objeto a un string (utilizado para guardar objetos en BD por ejemplo). El método __sleep() invoca un objeto cuando utilizamos la función serialize(), es útil cuando solo queremos serializar algunas propiedades del objeto. El método __wakeup() se llama cuando aplicamos la función unserialize() sobre el objeto.

class Post
{
    protected $id;
    public $title;
    protected $content;
    private   $author;

    ...

    function __sleep()
    {
        return [
            'id',
            'title',
        ];
    }

    function __wakeup()
    {
        echo "the object is unserialize";
    }

}

$post = new Post(1, 'Sample post', 'Content sample.', 'Juan Luis');

$serialize = serialize($post);

var_dump($serialize); //devuelve solo id y title = string 'O:4:"Post":2:{s:5:"�*�id";i:1;s:5:"title";s:11:"Sample post";}' (length=62)

$unserialize = unserialize($serialize); // invoca al método __wakeup() y devuelve = the object is unserialize
var_dump($unserialize);
//devuelve el objeto deserializado (las propiedades content y author están en null debido a que no las serializamos)

object(Post)[2]
  protected 'id' => int 1
  public 'title' => string 'Sample post' (length=11)
  protected 'content' => null
  private 'author' => null

__toString()

Este método es llamado cuando se imprime el objeto por pantalla ( sin llamar a ninguna propiedad ni método), convierte el objeto en una cadena de texto.
Un ejemplo real sería el utilizado en el objeto QueryBuilder de Doctrine, al imprimir el objeto muestra la consulta DQL realizada

class Post
{
    protected $id;
    public $title;
    protected $content;
    private   $author;

    ..

    function __toString()
    {
        return $this->title;
    }

}

$post = new Post(1, 'Sample post', 'Content sample.', 'Juan Luis');

echo $post; // Imprime -> Sample post

__invoke()

Este método permite llamar a un objeto PHP “como si fuera” una función.

class Post
{
    protected $id;
    public $title;
    protected $content;
    private   $author;

    ..

    function __invoke()
    {
        return $this->id.":".$this->title;
    }
}

$post = new Post(1, 'Sample post', 'Content sample.', 'Juan Luis');

echo $post(); //muestra 1:Sample post

__clone()

Se acciona cuando clonamos un objeto PHP con la función clone.

<?php

class Post
{
    protected $id;
    public $title;
    protected $content;
    private   $author;

    ...

    function __clone()
    {
        $this->id ++; //Incrementamos el id +1
    }
}

$post = new Post(1, 'Sample post', 'Content sample.', 'Juan Luis');
var_dump($post);
//Resultado
object(Post)[1]
  protected 'id' => int 1
  public 'title' => string 'Sample post' (length=11)
  protected 'content' => string 'Content sample.' (length=15)
  private 'author' => string 'Juan Luis' (length=9)

$postClonado = clone($post);

var_dump($postClonado);
//Resultado, incrementa el identificador
object(Post)[2]
  protected 'id' => int 2
  public 'title' => string 'Sample post' (length=11)
  protected 'content' => string 'Content sample.' (length=15)
  private 'author' => string 'Juan Luis' (length=9)

Recursos:

Autor: Juan Luis García Borrego

Soy una persona responsable, activa, constante, con muchas ganas de aprender y crecer como profesional. Tengo un carácter positivo y agradable que me permite sentirme cómodo trabajando en equipo. Mis intereses profesionales se centran en torno a PHP, en concreto al framework Symfony y su ecosistema, en el cual me siento muy cómodo desarrollando y es un claro ejemplo de un software de calidad, con buenas prácticas y ‘Clean Code’.

1 opinión en “Métodos mágicos PHP”

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *