Magiska metoder

Från Wiki.linux.se
Hoppa till navigering Hoppa till sök

Magiska Metoder

Magiska metoder är speciella metoder som åsidosätter PHP:s standardbeteende när vissa åtgärder utförs på ett objekt.

Varning:

Alla metodnamn som börjar med __ är reserverade av PHP. Därför rekommenderas det inte att använda sådana metodnamn om man inte vill åsidosätta PHP:s beteende.

Följande metodnamn betraktas som magiska: __construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __serialize(), __unserialize(), __toString(), __invoke(), __set_state(), __clone(), och __debugInfo().

Varning:

Alla magiska metoder, med undantag för __construct(), __destruct(), och __clone(), måste deklareras som public, annars genereras ett E_WARNING. Före PHP 8.0.0, genererades ingen diagnostik för de magiska metoderna __sleep(), __wakeup(), __serialize(), __unserialize(), och __set_state().

Varning:

Om typdeklarationer används i definitionen av en magisk metod måste de vara identiska med den signatur som beskrivs i detta dokument. Annars genereras ett fatalt fel. Före PHP 8.0.0, genererades ingen diagnostik. Däremot får __construct() och __destruct() inte deklarera en returtyp; annars genereras ett fatalt fel.

__sleep() och __wakeup()

public __sleep(): array
public __wakeup(): void

`serialize()` kontrollerar om klassen har en funktion med det magiska namnet __sleep(). Om så är fallet, körs den funktionen före någon serialization. Den kan rensa upp objektet och förväntas returnera en array med namnen på alla variabler i objektet som ska serialiseras. Om metoden inte returnerar något, serialiseras null och en E_NOTICE utfärdas.

Notera:

Det är inte möjligt för __sleep() att returnera namn på privata egenskaper i föräldraklasser. Om detta görs resulterar det i ett E_NOTICE-nivåfel. Använd istället __serialize().

Notera:

Från och med PHP 8.0.0 genererar det en varning att returnera ett värde som inte är en array från __sleep(). Tidigare genererade det en notice.

Avsikten med __sleep() är att åtgärda pågående data eller utföra liknande uppgifter för städning. Funktionen är också användbar om ett mycket stort objekt inte behöver sparas helt.

I motsats till detta kontrollerar `unserialize()` om det finns en funktion med det magiska namnet __wakeup(). Om den finns, kan denna funktion återskapa eventuella resurser som objektet kan ha.

Avsikten med __wakeup() är att återställa eventuella databasanslutningar som kan ha förlorats under serialiseringen och utföra andra återinitialiseringsuppgifter.

Exempel #1: Sleep och Wakeup

<?php
class Connection
{
    protected $link;
    private $dsn, $username, $password;
    
    public function __construct($dsn, $username, $password)
    {
        $this->dsn = $dsn;
        $this->username = $username;
        $this->password = $password;
        $this->connect();
    }
    
    private function connect()
    {
        $this->link = new PDO($this->dsn, $this->username, $this->password);
    }
    
    public function __sleep()
    {
        return array('dsn', 'username', 'password');
    }
    
    public function __wakeup()
    {
        $this->connect();
    }
}
?>

__serialize() och __unserialize()

public __serialize(): array
public __unserialize(array $data): void

`serialize()` kontrollerar om klassen har en funktion med det magiska namnet __serialize(). Om så är fallet, körs den funktionen före någon serialization. Den måste konstruera och returnera en associativ array av nyckel/värde-par som representerar den serialiserade formen av objektet. Om ingen array returneras kastas ett TypeError.

Notera: Om både __serialize() och __sleep() är definierade i samma objekt, kommer endast __serialize() att anropas. __sleep() kommer att ignoreras. Om objektet implementerar Serializable-gränssnittet, kommer gränssnittets serialize()-metod att ignoreras och __serialize() kommer att användas istället.

Avsikten med __serialize() är att definiera en serialization-vänlig godtycklig representation av objektet. Elementen i arrayen kan motsvara objektets egenskaper, men det är inte ett krav.

I motsats till detta kontrollerar `unserialize()` om det finns en funktion med det magiska namnet __unserialize(). Om den finns, kommer denna funktion att ges den återställda arrayen som returnerades från __serialize(). Den kan sedan återställa objektets egenskaper från den arrayen på lämpligt sätt.

Notera:

Om både __unserialize() och __wakeup() är definierade i samma objekt, kommer endast __unserialize() att anropas. __wakeup() kommer att ignoreras.

Notera: Denna funktion finns tillgänglig från och med PHP 7.4.0.

Exempel #2: Serialize och Unserialize

<?php
class Connection
{
    protected $link;
    private $dsn, $username, $password;

    public function __construct($dsn, $username, $password)
    {
        $this->dsn = $dsn;
        $this->username = $username;
        $this->password = $password;
        $this->connect();
    }

    private function connect()
    {
        $this->link = new PDO($this->dsn, $this->username, $this->password);
    }

    public function __serialize(): array
    {
        return [
          'dsn' => $this->dsn,
          'user' => $this->username,
          'pass' => $this->password,
        ];
    }

    public function __unserialize(array $data): void
    {
        $this->dsn = $data['dsn'];
        $this->username = $data['user'];
        $this->password = $data['pass'];

        $this->connect();
    }
}
?>

__toString()

public __toString(): string

Metoden __toString() gör det möjligt för en klass att bestämma hur den ska reagera när den behandlas som en sträng. Till exempel vad `echo $obj;` kommer att skriva ut.

Varning: Från och med PHP 8.0.0 följer returvärdet standardsemantiken för PHP-typer, vilket betyder att det kommer att tvingas till en sträng om möjligt och om strikt typning är inaktiverad.

Ett Stringable-objekt kommer inte att accepteras av en strängtypdeklaration om strikt typning är aktiverad. Om sådant beteende önskas måste typdeklarationen acceptera både Stringable och string via en unionstyp.

Från och med PHP 8.0.0 kommer alla klasser som innehåller en __toString()-metod också att implicit implementera Stringable-gränssnittet, och kommer därmed att klara typkontroller för det gränssnittet. Det rekommenderas att implementera gränssnittet uttryckligen ändå.

I PHP 7.4 måste returvärdet vara en sträng, annars kastas ett Error.

Före PHP 7.4.0 måste returvärdet vara en sträng, annars genereras ett fatalt E_RECOVERABLE_ERROR.

Varning: Det var inte möjligt att kasta ett undantag inom en __toString()-metod före PHP 7.4.0. Att göra det resulterar i ett fatalt fel.

Exempel #3: Enkelt Exempel

<?php
// Deklarera en enkel klass
class TestClass
{
    public $foo;

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

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

$class = new TestClass('Hej');
echo $class;
?>

Utdata från ovanstående exempel:

Hej

__invoke()

__invoke( ...$values): mixed

Metoden __invoke() anropas när ett skript försöker anropa ett objekt som en funktion.

Exempel #4: Använda __invoke()

<?php
class CallableClass
{
    public function __invoke($x)
    {
        var_dump($x);
    }
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));
?>

Utdata från ovanstående exempel:

int(5)
bool(true)

Exempel #5: Använda __invoke()

<?php
class Sort
{
    private $key;

    public function __construct(string $key)
    {
        $this->key = $key;
    }

    public function __invoke(array $a, array $b): int
    {
        return $a[$this->key] <=> $b[$this->key];
    }
}

$customers = [
    ['id' => 1, 'first_name' => 'John', 'last_name' => 'Do'],
    ['id' => 3, 'first_name' => 'Alice', 'last_name' => 'Gustav'],
    ['id' => 2, 'first_name' => 'Bob', 'last_name' => 'Filipe']
];

// sortera kunder efter förnamn
usort($customers, new Sort('first_name'));
print_r($customers);

// sortera kunder efter efternamn
usort($customers, new Sort('last_name'));
print_r($customers);
?>

Utdata från ovanstående exempel:

Array
(
    [0] => Array
        (
            [id] => 3
            [first_name] => Alice
            [last_name] => Gustav
        )

    [1] => Array
        (
            [id] => 2
            [first_name] => Bob
            [last_name] => Filipe
        )

    [2] => Array
        (
            [id] => 1
            [first_name] => John
            [last_name] => Do
        )

)
Array
(
    [0] => Array
        (
            [id] => 1
            [first_name] => John
            [last_name] => Do
        )

    [1] => Array
        (
            [id] => 2
            [first_name] => Bob
            [last_name] => Filipe
        )

    [2] => Array
        (
            [id] => 3
            [first_name] => Alice
            [last_name] => Gustav
        )

)

__set_state()

static __set_state(array $properties): object

Denna statiska metod anropas för klasser som exporteras av `var_export()`.

Den enda parametern för denna metod är en array som innehåller exporterade egenskaper i form av ['property' => value, ...].

Exempel #6: Använda __set_state()

<?php

class A
{
    public $var1;
    public $var2;

    public static function __set_state($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';

$b = var_export($a, true);
var_dump($b);
eval('$c = ' . $b . ';');
var_dump($c);
?>

Utdata från ovanstående exempel:

string(60) "A::__set_state(array(
   'var1' => 5,
   'var2' => 'foo',
))"
object(A)#2 (2) {
  ["var1"]=>
  int(5)
  ["var2"]=>
  string(3) "foo"
}

Notera: När ett objekt exporteras, kontrollerar `var_export()` inte om __set_state() är implementerat av objektets klass, så omimportering av objekt kommer att resultera i ett Error undantag, om __set_state() inte är implementerat. Detta påverkar särskilt vissa interna klasser. Det är programmerarens ansvar att verifiera att endast objekt som återimporteras vars klass implementerar __set_state().

__debugInfo()

__debugInfo(): array

Denna metod anropas av `var_dump()` när ett objekt dumpas för att få egenskaperna som ska visas. Om metoden inte är definierad på ett objekt, kommer alla publika, skyddade och privata egenskaper att visas.

Exempel #7: Använda __debugInfo()

<?php
class C {
    private $prop;

    public function __construct($val) {
        $this->prop = $val;
    }

    public function __debugInfo() {
        return [
            'propSquared' => $this->prop ** 2,
        ];
    }
}

var_dump(new C(42));
?>

Utdata från ovanstående exempel:

object(C)#1 (1) {
  ["propSquared"]=>
  int(1764)
}

Sidslut

Orginalhemsidan på Engelska : https://www.php.net/manual/en/language.oop5.magic.php
PHP
Språkreferens
Språkreferens#Klasser_och_Objekt


Det här är en maskinöversättning av PHP-manualen till svenska. Om du hittar fel är vi tacksamma om du rapporterar dem via formuläret som finns på https://www.linux.se/kontaka-linux-se/