Blog de programación, errores, soluciones

Chose Language:
comments
Author: Admin/Publisher |finished | checked

OOP – Magic Methods in PHP

In PHP, there is a group of methods called magic methods that can assist when an event occurs on the object. These methods are invoked without needing to be explicitly called by you, which is why they are referred to as magic methods.

Most likely, you are familiar with two of these if you have used another programming language: the constructor and the destructor of the object.

IMPORTANT: All magic methods must be public.

Métodos mágicos

construct
destruct
call y callstatic
getvalue
setvalue
isset
unset
serialize, sleep
unserialize, wakeap
tostring
invoke
setstate
clone
debuginfo

This time, to indicate visibility or access levels, we will use the following notation:

  • public
  • protected
  • private

Construct

Probably, the __construct() method is the most well-known in the entire list, and it’s the method you first learn when studying object-oriented programming in PHP.

construct example
<?php
class Perro{
  public $nome;
  public $raza;
  public __construct(string $n,string $r){
     $this->nombre = $n;
     $this->raza = $r;
  }
}
$p = new Perro("Yoshi","Terrier");
echo $p->nombre;//deberia darnos Yoshi

This a very simple example but functional

Destructor

The __destruct() method is called when the object is destroyed. I’m not very good at giving examples, and the ones I found online weren’t good enough. So, imagine it’s like an online browser game, and you have an object, for example, a sword.

destruct example
class espada{
   __destruct(){
     echo "la espada se ha roto";
  }
}

Call y CallStatic

The __call() and __callStatic() methods are invoked when you try to call a method that doesn’t exist or is inaccessible (private or protected) in an object. The __callStatic() method is triggered when trying to call a static method and must be declared as static.

__call() example
<?php
class Perro{
   private $raza;
   private $nombre;

   public function __construct($nombre,$raza){
      $this->raza = $raza;
      $this->nombre = $nombre;
   }
   private function ladrar(){
       echo "waw waw";
   }
   public function __get($property_name){
      return $this->$property_name;
   }
   public function __call($method_name,$args){
       if(method_exists($this,$method_name)){
           echo "el metodo es privado";
       }
       else{
           echo "<p>tal metodo no existe en el objeto de clase ".__CLASS__."</p>";
       }
   }
}
$p = new Perro("Yoshi","Terrier");
echo $p->__get('nombre');//obtendra Yoshi
$p->ladrar();
$p->nadar();
These two magic methods, in case you haven’t noticed, can also be used for method overloading based on their name and arguments.
Ejemplo de sobrecarga con __call
class SampleClass {
    public function __call($name, $args) {
        if ($name == 'multiply') {
            if (count($args) == 2) {
                return $args[0] * $args[1];
            } else if (count($args) == 3) {
                return $args[0] * $args[1] * $args[2];
            }
        }
        // Handle other methods or throw an error if the method is not defined
    }
}

$obj = new SampleClass();
echo $obj->multiply(2, 3)."\n"; // Output: 6
echo $obj->multiply(2, 3, 4); // Output: 24

Get value

__get() – It is used to read inaccessible data (protected, private, or non-existent properties).

__get() example
<?php
class Perro{
   private $raza;
   private $nombre;

   public function __construct($nombre,$raza){
      $this->raza = $raza;
      $this->nombre = $nombre;
   }
   public function __get($property_name){
      return $this->$property_name;
   }
}
$p = new Perro("Yoshi","Terrier");
echo $p->__get('nombre');//obtendra Yoshi

Set value

The real way to assign a value to an inaccessible (private or protected) property of an object is by using __set().

__set() example
<?php
class Perro{
   private $raza;
   private $nombre;

   public function __construct($nombre,$raza){
      $this->raza = $raza;
      $this->nombre = $nombre;
   }

   public function __get($property_name){
      return $this->$property_name;
   }

   public function __set($property_name,$property_value){
      $this->$property_name = $property_value;
   }
}
$p = new Perro("Yoshi","Terrier");
$p->__set('nombre','Joker');
echo $p->__get('nombre');//obtendra Joker

isset

It is executed when isset() is called on an inaccessible or non-existing property: __isset().

__isset() example
<?php
class Perro{
   private $raza;
   private $nombre= "yoshi";

    public function __isset($r){
        if(isset($this->$r)){
            echo "la propiedad existe \n";
        }else{
            echo "no hay ninguna propiedad $r iicializada \n";
        }
    }
}

$p = new Perro();
$p->__isset("nombre");
$p->__isset("raza");

unset(__unset())

It is executed when unset is called on a private (private), protected, or non-existent property.

__unset() example
<?php
class Perro{
    private $raza= "buldog";
    private $nombre= "yoshi";

    public function __unset($n){
        if(isset($this->$n)){
            unset($this->$n);
        }
    }
}

$p = new Perro();
$p->__unset("raza");
var_dump($p);

As you can see, we have destroyed the $raza property of the object.

Use case, I would say that this method makes more sense to be used when the property is an associative array and we want to remove one of its members. The use we gave it in the example wouldn’t make much sense, since we created that variable for a reason in the first place, or I don’t see the point at this moment, although it makes it easier to see the functionality of the method in this example.

Serialize(__serialize(), __sleep())

In case an object has the __serialize() or __sleep() method, it is executed before serialization.

In this method, we must return an array with the names of all the variables of the object that will be serialized.

__sleep()
public function __sleep ( void ) : array{
   //code
   //must return an associative array
}
disponible desde PHP 7.4.0

__serialize()

public function __serialize ( void ) : array{
   //code
   //must return an associative array
}

Probablemente __serialize() remplace a __sleep() en un futuro

Generally, when we use serialize in an object, the result is as follows:

<?php
class Perro{
    private $raza= "buldog";
    private $nombre= "yoshi";

}

$p = new Perro();

$x= serialize($p);
var_dump($x);
string(81) "O:5:"Perro":2:{s:11:"Perroraza";s:6:"buldog";s:13:"Perronombre";s:5:"yoshi";}"

As you might be thinking, but what is this perroraza, of course, this is not what we want when serializing an object.

<?php
class Perro{
    private $raza= "buldog";
    private $nombre= "yoshi";

    public function __serialize(): array{
        return ["raza","nombre"];
    }
}

$p = new Perro();
$x = serialize($p);
var_dump($x);
string(48) "O:5:"Perro":2:{i:0;s:4:"raza";i:1;s:6:"nombre";}"

If we run unserialize, we will get the following; this matter of serializing and deserializing is starting to get interesting

var_dump(unserialize($x));
object(Perro)#2 (4) {
  ["raza":"Perro":private]=>
  string(6) "buldog"
  ["nombre":"Perro":private]=>
  string(5) "yoshi"
  ["0"]=>
  string(4) "raza"
  ["1"]=>
  string(6) "nombre"
}

To understand more about the topic of serialize and unserialize, I recommend reading this topic.

http://php.net/manual/en/language.oop5.serialization.php

unserialize (__unserialize() y __wakeup())

Each time an unserialize is called on the object, it will execute; if the __unserialize and __wakeup methods are declared, __unserialize will execute instead of __wakeup.

This method can reconstruct any resources that the object may have.

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

__wakeup().

disponible desde PHP 7.4.0

__unserialize()

toString (__toString)

This method is executed each time our object is attempted to be used as a string.

__toString example
<?php
class Perro{
    private $raza= "buldog";
    private $nombre= "yoshi";

    public function __toString(){
        echo "raza:".$this->raza."\n nombre:".$this->nombre;
    }
}

$p = new Perro();
$p->__toString();

Another example to clarify the concept:

Ejemplo 2 de __toString
<?php
class Perro{
    private $raza= "buldog";
    private $nombre= "yoshi";

    public function __toString(){
        return "raza:".$this->raza."\n nombre:".$this->nombre;
    }
}

$p = new Perro();
echo "".$p;

Invocation

__invoke() is called when an object is attempted to be used as a function.

__invoke() example
<?php
class Perro{
    private $debug=false;
    private $raza= "buldog";
    private $nombre= "yoshi";

    private function ladrar(){
        echo "waw waw";
    }
    public function __invoke(){
        echo "raza: $this->raza - nombre: $this->nombre";
    }
}

$p = new Perro();
$p();

Set state

The __set_state method is a static method that is called when an object is exported with the var_export() function. This function returns a parsable string representation of a variable, and when it encounters an object, it uses the __set_state method to recreate the object from its exported state.

sintaxis

Sintaxis / Sintax
public static function __set_state ( array $properties ) : object{
   //code
   //must return return object
}

Clone

It is executed once the object has been cloned; if the __clone() method is defined, it will be called, allowing any property that needs to be changed to be modified.

__clone() example
<?php
class Perro{
   private $raza;
   private $nombre;

   public function __construct($nombre,$raza){
      $this->raza = $raza;
      $this->nombre = $nombre;
   }
   private function ladrar(){
       echo "waw waw";
   }
   public function __get($property_name){
      return $this->$property_name."\n";
   }
   public function __set($property_name, $value){
       $this->$property_name = $value;
   }
   public function __clone(){
       $this->nombre ="";
   }
   public function __call($method_name,$args){
       if(method_exists($this,$method_name)){
           echo "el metodo es privado \n";
       }
       else{
           echo "tal metodo no existe en el objeto de clase ".__CLASS__."\n";
       }
   }
}
$p = new Perro("Yoshi","Terrier");
echo $p->__get('nombre');//obtendra Yoshi
$p->ladrar();
$p->nadar();

$p2 = clone $p;
echo $p2->__get('nombre');
echo $p2->__get('raza');
echo $p2->__set('nombre','pako');
echo $p2->__get('nombre');
echo $p->__get('nombre');
unset($p);
echo $p2->__get("nombre");

The above is a simple example, but it makes it clear what can be done with __clone()

debuginfo

Finally, we have the __debugInfo() method, which is invoked by var_dump().

Sintaxis / Sintax
public function __debugInfo ( void ) : array{
   //code
   //must return an array
}

As you can see, the method must return an array.

If the method is not defined on an object, all public, protected, and private properties will be displayed.

__debuginfo() example
class Perro{
    private $debug=false;
    private $raza= "buldog";
    private $nombre= "yoshi";

    private function ladrar(){
        echo "waw waw";
    }
    public function __debuginfo(){
        if($this->debug){
            $data["properties"]="raza,nombre";
            return $data;
        }
        else{
            return array(get_object_vars ($this),get_class_methods($this));
        } 
    }
}

$p = new Perro();
var_dump($p);
Category: en-php
Something wrong? If you found an error or mistake in the content you can contact me on Twitter | @luisg2249_luis.
Last 4 post in same category

Comments