PHP
Metody magiczne
Szukaj…
__get (), __set (), __isset () i __unset ()
Ilekroć próbujesz odzyskać określone pole z takiej klasy:
$animal = new Animal();
$height = $animal->height;
PHP wywołuje magiczną metodę __get($name)
, w tym przypadku $name
równa się "height"
. Zapisywanie do pola klasy takiego:
$animal->height = 10;
Wywoła magiczną metodę __set($name, $value)
, z $name
równą "height"
i $value
równą 10
.
PHP ma również dwie wbudowane funkcje isset()
, które sprawdzają, czy zmienna istnieje, i unset()
, która niszczy zmienną. Sprawdzanie, czy pole obiektów jest ustawione tak:
isset($animal->height);
Wywoła funkcję __isset($name)
na tym obiekcie. Zniszczenie takiej zmiennej:
unset($animal->height);
Wywoła funkcję __unset($name)
na tym obiekcie.
Zwykle, gdy nie definiujesz tych metod w swojej klasie, PHP po prostu pobiera pole, które jest przechowywane w twojej klasie. Można jednak zastąpić te metody, aby utworzyć klasy, które mogą przechowywać dane jak tablicę, ale są użyteczne jak obiekt:
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));
}
Funkcja empty () i metody magiczne
Zauważ, że wywołanie empty()
dla atrybutu klasy wywoła __isset()
ponieważ zgodnie z instrukcją PHP:
empty () jest w istocie zwięzłym odpowiednikiem ! isset ($ var) || $ var == false
__construct () i __destruct ()
__construct()
jest najczęstszą magiczną metodą w PHP, ponieważ służy do konfigurowania klasy podczas jej inicjalizacji. Przeciwieństwem metody __construct()
jest metoda __destruct()
. Ta metoda jest wywoływana, gdy nie ma już odwołań do utworzonego obiektu lub wymuszasz jego usunięcie. Śmieciarka PHP oczyści obiekt, najpierw wywołując jego destruktor, a następnie usuwając go z pamięci.
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 ()
Ilekroć obiekt jest traktowany jako ciąg znaków, wywoływana jest metoda __toString()
. Ta metoda powinna zwrócić ciąg znaków reprezentujący klasę.
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;
__odwołać się()
Ta magiczna metoda jest wywoływana, gdy użytkownik próbuje wywołać obiekt jako funkcję. Możliwe przypadki użycia mogą obejmować niektóre podejścia, takie jak programowanie funkcjonalne lub niektóre wywołania zwrotne.
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 () i __callStatic ()
__call()
i __callStatic()
są wywoływane, gdy ktoś wywołuje nieistniejącą metodę obiektową w kontekście obiektowym lub statycznym.
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());
}
}
Przykład:
$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 () i __wakeup ()
__sleep
i __wakeup
to metody związane z procesem serializacji. funkcja serialize
sprawdza, czy klasa ma metodę __sleep
. Jeśli tak, zostanie ono wykonane przed serializacją. __sleep
ma zwracać tablicę nazw wszystkich zmiennych obiektu, które powinny być serializowane.
__wakeup
z kolei zostanie wykonane przez unserialize
jeśli jest obecne w klasie. Jego celem jest przywrócenie zasobów i innych rzeczy, które są potrzebne do zainicjowania po unserializacji.
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();
}
}
__Informacje debugowania()
Ta metoda jest wywoływana przez
var_dump()
podczas zrzutu obiektu w celu uzyskania właściwości, które powinny zostać wyświetlone. Jeśli metoda nie jest zdefiniowana na obiekcie, zostaną wyświetlone wszystkie właściwości publiczne, chronione i prywatne. - Podręcznik PHP
class DeepThought {
public function __debugInfo() {
return [42];
}
}
var_dump(new DeepThought());
Powyższy przykład wyświetli:
class DeepThought#1 (0) {
}
var_dump(new DeepThought());
Powyższy przykład wyświetli:
class DeepThought#1 (1) {
public ${0} =>
int(42)
}
__clone ()
__clone
jest wywoływany przy użyciu słowa kluczowego clone
. Służy do manipulowania stanem obiektu podczas klonowania, po tym, jak obiekt został faktycznie sklonowany.
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;
}
}
Przykład:
$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