PHP
マジックメソッド
サーチ…
__get()、__set()、__isset()および__unset()
次のようにクラスから特定のフィールドを取得しようとするたびに:
$animal = new Animal();
$height = $animal->height;
PHPは__get($name)
というマジックメソッドを呼び出します。この場合、 $name
は"height"
と同じです。次のようなクラスフィールドへの書き込み:
$animal->height = 10;
マジックメソッドの呼び出します__set($name, $value)
と、 $name
と同じ"height"
と$value
に等しい10
。
PHPには、変数が存在するかどうかを調べる組み込み関数isset()
と、変数を破棄するunset()
2つの組み込み関数もあります。オブジェクトフィールドが次のように設定されているかどうかを確認する:
isset($animal->height);
そのオブジェクトに対して__isset($name)
関数を呼び出します。次のような変数を破棄する:
unset($animal->height);
そのオブジェクトに対して__unset($name)
関数を呼び出します。
通常、これらのメソッドをクラスに定義しないと、PHPはクラスに格納されているフィールドを取得します。ただし、これらのメソッドをオーバーライドして、配列のようなデータを保持できるクラスを作成できますが、オブジェクトのように使用できます。
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));
}
空()関数とマジックメソッド
class属性でempty()
を呼び出すと、 __isset()
が__isset()
れることに注意してください。
empty()は本質的には!isset($ var)|| $ var == false
__construct()および__destruct()
__construct()
は、初期化時にクラスを設定するために使用されるため、PHPで最も一般的な魔法のメソッドです。 __construct()
メソッドの反対は、 __construct()
__destruct()
メソッドです。このメソッドは、作成したオブジェクトへの参照がなくなった場合、または削除を強制した場合に呼び出されます。 PHPのガベージコレクションでは、まずデストラクタを呼び出してメモリからオブジェクトを削除することでオブジェクトをクリーンアップします。
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()
オブジェクトが文字列として扱われるときはいつでも、 __toString()
メソッドが呼び出されます。このメソッドは、クラスの文字列表現を返す必要があります。
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;
__invoke()
このマジックメソッドは、ユーザーがオブジェクトを関数として呼び出そうとしたときに呼び出されます。考えられるユースケースには、関数型プログラミングやコールバックなどのいくつかのアプローチが含まれている可能性があります。
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()および__callStatic()
__call()
および__callStatic()
は、オブジェクトまたは静的コンテキスト内に存在しないオブジェクトメソッドを呼び出すときに呼び出されます。
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());
}
}
例:
$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()と__wakeup()
__sleep
と__wakeup
は、シリアライズ処理に関連するメソッドです。クラスに__sleep
メソッドがあるかどうかをチェックする関数のserialize
。もしそうなら、それは任意のシリアル化の前に実行されます。 __sleep
は、直列化されるべきオブジェクトのすべての変数の名前の配列を返すものとします。
__wakeup
ターンでは、によって実行されるunserialize
それがクラスに存在している場合。非直列化時に初期化するために必要なリソースやその他のものを再構築することが意図されています。
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();
}
}
__デバッグ情報()
このメソッドは、オブジェクトをダンプして表示するプロパティを取得するときに、
var_dump()
によって呼び出されます。メソッドがオブジェクトに定義されていない場合は、public、protected、およびprivateのすべてのプロパティが表示されます。 - PHP Manual
class DeepThought {
public function __debugInfo() {
return [42];
}
}
var_dump(new DeepThought());
上の例は次のように出力されます:
class DeepThought#1 (0) {
}
var_dump(new DeepThought());
上の例は次のように出力されます:
class DeepThought#1 (1) {
public ${0} =>
int(42)
}
__クローン()
__clone
は、 clone
キーワードを使用して呼び出されます。これは、オブジェクトが実際に複製された後、複製時にオブジェクトの状態を操作するために使用されます。
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;
}
}
例:
$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