PHP
Magische methoden
Zoeken…
__get (), __set (), __isset () en __unset ()
Wanneer u probeert een bepaald veld uit een klasse als volgt op te halen:
$animal = new Animal();
$height = $animal->height;
PHP roept de magische methode __get($name)
, waarbij $name
in dit geval $name
gelijk is aan "height"
. Schrijven naar een klasveld als volgt:
$animal->height = 10;
Zal de magische methode __set($name, $value)
aanroepen, met $name
gelijk aan "height"
en $value
gelijk aan 10
.
PHP heeft ook twee ingebouwde functies isset()
, die controleren of er een variabele bestaat, en unset()
, die een variabele vernietigt. Controleren of een objectveld als volgt is ingesteld:
isset($animal->height);
__isset($name)
de functie __isset($name)
op dat object aan. Zo'n variabele vernietigen:
unset($animal->height);
__unset($name)
de functie __unset($name)
op dat object aan.
Normaal gesproken haalt PHP, wanneer u deze methoden niet voor uw klas definieert, alleen het veld op zoals het in uw klas is opgeslagen. U kunt deze methoden echter overschrijven om klassen te maken die gegevens kunnen bevatten als een array, maar bruikbaar zijn als een object:
class Example {
private $data = [];
public function __set($name, $value) {
$this->data[$name] = $value;
}
public function __get($name) {
if (!array_key_exists($name, $this->data)) {
return null;
}
return $this->data[$name];
}
public function __isset($name) {
return isset($this->data[$name]);
}
public function __unset($name) {
unset($this->data[$name]);
}
}
$example = new Example();
// Stores 'a' in the $data array with value 15
$example->a = 15;
// Retrieves array key 'a' from the $data array
echo $example->a; // prints 15
// Attempt to retrieve non-existent key from the array returns null
echo $example->b; // prints nothing
// If __isset('a') returns true, then call __unset('a')
if (isset($example->a)) {
unset($example->a));
}
empty () functie en magische methoden
Merk op dat het aanroepen van empty()
op een __isset()
omdat, zoals in de PHP-handleiding staat:
empty () is in wezen het beknopte equivalent van ! isset ($ var) || $ var == false
__construct () en __destruct ()
__construct()
is de meest voorkomende magische methode in PHP, omdat deze wordt gebruikt om een klasse in te stellen wanneer deze wordt geïnitialiseerd. Het tegenovergestelde van de methode __construct()
is de methode __destruct()
. Deze methode wordt genoemd wanneer er geen verwijzingen meer zijn naar een object dat u hebt gemaakt of wanneer u de verwijdering ervan forceert. De afvalverzameling van PHP zal het object opruimen door eerst zijn vernietiger aan te roepen en vervolgens uit het geheugen te verwijderen.
class Shape {
public function __construct() {
echo "Shape created!\n";
}
}
class Rectangle extends Shape {
public $width;
public $height;
public function __construct($width, $height) {
parent::__construct();
$this->width = $width;
$this->height = $height;
echo "Created {$this->width}x{$this->height} Rectangle\n";
}
public function __destruct() {
echo "Destroying {$this->width}x{$this->height} Rectangle\n";
}
}
function createRectangle() {
// Instantiating an object will call the constructor with the specified arguments
$rectangle = new Rectangle(20, 50);
// 'Shape Created' will be printed
// 'Created 20x50 Rectangle' will be printed
}
createRectangle();
// 'Destroying 20x50 Rectangle' will be printed, because
// the `$rectangle` object was local to the createRectangle function, so
// When the function scope is exited, the object is destroyed and its
// destructor is called.
// The destructor of an object is also called when unset is used:
unset(new Rectangle(20, 50));
__toString ()
Wanneer een object als een tekenreeks wordt behandeld, wordt de methode __toString()
aangeroepen. Deze methode moet een stringvoorstelling van de klasse retourneren.
class User {
public $first_name;
public $last_name;
public $age;
public function __toString() {
return "{$this->first_name} {$this->last_name} ($this->age)";
}
}
$user = new User();
$user->first_name = "Chuck";
$user->last_name = "Norris";
$user->age = 76;
// Anytime the $user object is used in a string context, __toString() is called
echo $user; // prints 'Chuck Norris (76)'
// String value becomes: 'Selected user: Chuck Norris (76)'
$selected_user_string = sprintf("Selected user: %s", $user);
// Casting to string also calls __toString()
$user_as_string = (string) $user;
__beroep doen op()
Deze magische methode wordt aangeroepen wanneer de gebruiker object als functie probeert aan te roepen. Mogelijke use cases kunnen enkele benaderingen zijn, zoals functioneel programmeren of enkele callbacks.
class Invokable
{
/**
* This method will be called if object will be executed like a function:
*
* $invokable();
*
* Args will be passed as in regular method call.
*/
public function __invoke($arg, $arg, ...)
{
print_r(func_get_args());
}
}
// Example:
$invokable = new Invokable();
$invokable([1, 2, 3]);
// optputs:
Array
(
[0] => 1
[1] => 2
[2] => 3
)
__call () en __callStatic ()
__call()
en __callStatic()
worden aangeroepen wanneer iemand de niet-bestaande __callStatic()
in de object- of statische context aanroept.
class Foo
{
/**
* This method will be called when somebody will try to invoke a method in object
* context, which does not exist, like:
*
* $foo->method($arg, $arg1);
*
* First argument will contain the method name(in example above it will be "method"),
* and the second will contain the values of $arg and $arg1 as an array.
*/
public function __call($method, $arguments)
{
// do something with that information here, like overloading
// or something generic.
// For sake of example let's say we're making a generic class,
// that holds some data and allows user to get/set/has via
// getter/setter methods. Also let's assume that there is some
// CaseHelper which helps to convert camelCase into snake_case.
// Also this method is simplified, so it does not check if there
// is a valid name or
$snakeName = CaseHelper::camelToSnake($method);
// Get get/set/has prefix
$subMethod = substr($snakeName, 0, 3);
// Drop method name.
$propertyName = substr($snakeName, 4);
switch ($subMethod) {
case "get":
return $this->data[$propertyName];
case "set":
$this->data[$propertyName] = $arguments[0];
break;
case "has":
return isset($this->data[$propertyName]);
default:
throw new BadMethodCallException("Undefined method $method");
}
}
/**
* __callStatic will be called from static content, that is, when calling a nonexistent
* static method:
*
* Foo::buildSomethingCool($arg);
*
* First argument will contain the method name(in example above it will be "buildSomethingCool"),
* and the second will contain the value $arg in an array.
*
* Note that signature of this method is different(requires static keyword). This method was not
* available prior PHP 5.3
*/
public static function __callStatic($method, $arguments)
{
// This method can be used when you need something like generic factory
// or something else(to be honest use case for this is not so clear to me).
print_r(func_get_args());
}
}
Voorbeeld:
$instance = new Foo();
$instance->setSomeState("foo");
var_dump($instance->hasSomeState()); // bool(true)
var_dump($instance->getSomeState()); // string "foo"
Foo::exampleStaticCall("test");
// outputs:
Array
(
[0] => exampleCallStatic
[1] => test
)
__sleep () en __wakeup ()
__sleep
en __wakeup
zijn methoden die gerelateerd zijn aan het serialisatieproces. serialize
functie controleert of een klasse een __sleep
methode heeft. Als dit het geval is, wordt deze vóór serialisatie uitgevoerd. __sleep
wordt verondersteld een array met de namen van alle variabelen van een object te retourneren dat moet worden geserialiseerd.
__wakeup
op zijn beurt uitgevoerd door unserialize
als het aanwezig is in de klas. Het is de bedoeling om middelen en andere zaken te herstellen die nodig zijn om te worden geïnitialiseerd na unserialisatie.
class Sleepy {
public $tableName;
public $tableFields;
public $dbConnection;
/**
* This magic method will be invoked by serialize function.
* Note that $dbConnection is excluded.
*/
public function __sleep()
{
// Only $this->tableName and $this->tableFields will be serialized.
return ['tableName', 'tableFields'];
}
/**
* This magic method will be called by unserialize function.
*
* For sake of example, lets assume that $this->c, which was not serialized,
* is some kind of a database connection. So on wake up it will get reconnected.
*/
public function __wakeup()
{
// Connect to some default database and store handler/wrapper returned into
// $this->dbConnection
$this->dbConnection = DB::connect();
}
}
__debugInfo ()
Deze methode wordt door
var_dump()
bij het dumpen van een object om de eigenschappen te krijgen die moeten worden weergegeven. Als de methode niet is gedefinieerd voor een object, worden alle openbare, beschermde en privé-eigenschappen getoond. - PHP-handleiding
class DeepThought {
public function __debugInfo() {
return [42];
}
}
var_dump(new DeepThought());
Het bovenstaande voorbeeld zal uitvoeren:
class DeepThought#1 (0) {
}
var_dump(new DeepThought());
Het bovenstaande voorbeeld zal uitvoeren:
class DeepThought#1 (1) {
public ${0} =>
int(42)
}
__clone ()
__clone
wordt ingeroepen door het gebruik van de clone
zoekwoord. Het wordt gebruikt om de objectstatus te manipuleren bij het klonen, nadat het object daadwerkelijk is gekloond.
class CloneableUser
{
public $name;
public $lastName;
/**
* This method will be invoked by a clone operator and will prepend "Copy " to the
* name and lastName properties.
*/
public function __clone()
{
$this->name = "Copy " . $this->name;
$this->lastName = "Copy " . $this->lastName;
}
}
Voorbeeld:
$user1 = new CloneableUser();
$user1->name = "John";
$user1->lastName = "Doe";
$user2 = clone $user1; // triggers the __clone magic method
echo $user2->name; // Copy John
echo $user2->lastName; // Copy Doe