ホームページ > バックエンド開発 > PHPの問題 > phpマジックメソッドとは

phpマジックメソッドとは

青灯夜游
リリース: 2023-03-17 17:32:01
オリジナル
4246 人が閲覧しました

PHP では、二重アンダースコア「__」で始まる名前の組み込みメソッドは、「__construct()」、「__set()」、「__get()」、「__isset()」など、マジック メソッドと呼ばれます。 、「__unset()」、「__sleep()」、「__wakeup()」、「__call()」、「__invoke()」などがありますが、このうち「__construct()」はクラスの構築メソッドであり、オブジェクト作成後の最初のステップ、オブジェクトによって自動的に呼び出されるメソッド。

phpマジックメソッドとは

#このチュートリアルの動作環境: Windows7 システム、PHP8 バージョン、DELL G3 コンピューター

php のマジック メソッド

PHP では、二重アンダースコア (

__) で始まる名前のメソッドを PHP ではマジック メソッドと呼び、PHP において非常に重要な役割を果たします。マジック メソッドには次のものが含まれます:

#メソッド名__construct()__destruct()__call($ funName, $引数)__callStatic($funName, $arguments)#__get($propertyName)__set($property, $value)__isset($content) __unset($content)__sleep()__wakeup()__toString()__invoke()__set_state($an_array)__clone()__autoload($className)__debugInfo()

この記事では、いくつかの例を使用して、PHP マジック メソッドの使用方法を示します。

1.__construct()

オブジェクトが作成されると、PHP クラスのコンストラクター メソッドが最初に呼び出されます。すべてのクラスにはコンストラクター メソッドがあります。クラス内で明示的に定義しない場合、クラス内では定義されませんが、デフォルトの引数なしのクラス コンストラクターが存在します。

1) コンストラクター メソッドの適用

クラスのコンストラクター メソッドは、通常、オブジェクトの作成時の初期化やメンバーへの値の割り当てなど、いくつかの初期化タスクを実行するために使用されます。

2) クラスのコンストラクター メソッドの宣言形式

function __constrct([parameter list]){

    方法具体实现 //通常为成员变量初始赋值。

}
ログイン後にコピー

注: ほとんどのクラスで宣言できるコンストラクターは 1 つだけです。なぜなら、PHP はコンストラクターのオーバーロードをサポートしていないからです。

以下は完全な例です:

<?php
    class Person
    {                                                                     
            public $name;       
            public $age;       
            public $sex;       

        /**
         * 明确定义含参的构造方法
         */                                                                                       
        public function __construct($name="", $sex="Male", $age=22)
        {     
            $this->name = $name;
            $this->sex = $sex;
            $this->age = $age;
        }

        /**
         * say 方法定义
         */
        public function say()
        {
            echo "Name:" . $this->name . ",Sex:" . $this->sex . ",Age:" . $this->age;
        }   

    }
ログイン後にコピー

パラメータを使用せずに $person1 オブジェクトを作成します。

$Person1 = new Person();
echo $Person1->say(); //显示:Name:,Sex:Male,Age:22
ログイン後にコピー

パラメータ「Jams」を指定して呼び出して、$person2 オブジェクトを作成します。

$Person2 = new Person("Jams");
echo $Person2->say(); // 显示: Name: Jams, Sex: Male, Age: 22
ログイン後にコピー

3 つのパラメータを指定して呼び出して、$person3 オブジェクトを作成します。

$Person3 = new Person ("Jack", "Male", 25);
echo $Person3->say(); // 显示:Name: Jack, Sex: Male, Age: 25
ログイン後にコピー

__destruct()

デストラクターはコンストラクターの逆です。

デストラクターを使用すると、オブジェクトを破棄する前に、ファイルを閉じる、結果セットをクリアするなど、いくつかの操作を実行できます。

デストラクターは、PHP 5 で導入された新機能です。

デストラクターの宣言はコンストラクターと似ており、2 つのアンダースコアで始まり、名前は __destruct() に固定されています。

デストラクターの宣言

function __destruct()
{
    //method body
}
ログイン後にコピー

デストラクターはパラメーターを受け取ることができません。

デストラクターの使用

デストラクターは通常、クラスでは一般的ではありません。これはクラスのオプションの部分であり、通常はクラスが破棄される前にいくつかのクリーンアップ タスクを完了するために使用されます。

これはデストラクターの使用例です。

<?php
class Person{     

    public $name;         
    public $age;         
    public $sex;         

    public function __construct($name="", $sex="Male", $age=22)
    {   
        $this->name = $name;
        $this->sex  = $sex;
        $this->age  = $age;
    }

    /**
     * say method
     */
    public function say()
    {
        echo "Name:".$this->name.",Sex:".$this->sex.",Age:".$this->age;
    }   

    /**
     * declare a destructor method
     */
    public function __destruct()
    {
            echo "Well, my name is ".$this->name;
    }
}

$Person = new Person("John");
unset($Person); //destroy the object of $Person created above
ログイン後にコピー

出力結果

Well, my name is John
ログイン後にコピー

__call()

このメソッドは 2 つのパラメーターを受け取ります。最初のパラメータは未定義のメソッド名で、2 番目のパラメータはメソッドに渡されるパラメータで構成される配列です。

Use

function __call(string $function_name, array $arguments)
{
    // method body
}
ログイン後にコピー

プログラム内で未定義のメソッドを呼び出す場合、__call() メソッドが呼び出されます。

<?php
class Person
{                             
    function say()
    {
           echo "Hello, world!<br>";
    }     

    function __call($funName, $arguments)
    {
          echo "The function you called:" . $funName . "(parameter:" ;  // Print the method's name that is not existed.
          print_r($arguments); // Print the parameter list of the method that is not existed.
          echo ")does not exist!!<br>\n";                   
    }                                         
}
$Person = new Person();           
$Person->run("teacher"); // If the method which is not existed is called within the object, then the __call() method will be called automatically.
$Person->eat("John", "apple");             
$Person->say();
ログイン後にコピー

結果の表示

The function you called: run (parameter: Array([0] => teacher)) does not exist!
The function you called: eat (parameter: Array([0] => John[1] => apple)) does not exist!
Hello world!
ログイン後にコピー

4. __callStatic()

プログラム内で未定義の静的メソッドが呼び出された場合、__callStatic( ) メソッドが自動的に呼び出されます。

__callStatic() の使用法は __call() と似ています。以下に例を示します。

<?php
class Person
{
    function say()
    {
        echo "Hello, world!<br>";
    }

    public static function __callStatic($funName, $arguments)
    {
        echo "The static method you called:" . $funName . "(parameter:" ;  // 打印出未定义的方法名。
        print_r($arguments); // 打印出未定义方法的参数列表。
        echo ")does not exist!<br>\n";
    }
}
$Person = new Person();
$Person::run("teacher"); // 如果此项目内不存在的方法被调用了,那么 __callStatic() 方法将被自动调用。
$Person::eat("John", "apple");
$Person->say();
ログイン後にコピー

実行結果は次のとおりです。

The static method you called: run (parameter: Array([0] => teacher)) does not exist!
The static method you called: eat (parameter: Array([0] => John[1] => apple)) does not exist!
Hello world!
ログイン後にコピー

__get()

オブジェクトのプライベート プロパティに外部からアクセスしようとすると、アプリケーションは例外をスローして実行を終了します。この問題は、__get メソッドを使用して解決できます。このメソッドは、オブジェクトの外部からプライベート プロパティの値を取得できます。例は次のとおりです

<?php
class Person
{
    private $name;
    private $age;

    function __construct($name="", $age=1)
    {
        $this->name = $name;
        $this->age = $age;
    }

    public function __get($propertyName)
    {   
        if ($propertyName == "age") {
            if ($this->age > 30) {
                return $this->age - 10;
            } else {
                return $this->$propertyName;
            }
        } else {
            return $this->$propertyName;
        }
    }
}
$Person = new Person("John", 60);   // Instantiate the object with the Person class and assign initial values to the properties with the constructor.
echo "Name:" . $Person->name . "<br>";   // When the private property is accessed, the __get() method will be called automatically,so we can get the property value indirectly.
echo "Age:" . $Person->age . "<br>";    // The __get() method is called automatically,and it returns different values according to the object itself.
ログイン後にコピー

結果は次のようになります

Name: John
Age: 50
ログイン後にコピー

6. __set()

set($property,$value)メソッドを使用しますクラスのプライベート プロパティを設定します。未定義のプロパティが割り当てられた後、set() メソッドがトリガーされ、渡されるパラメータは設定されたプロパティの名前と値です。

次はデモ コードです:

<?php
class Person
{
    private $name;
    private $age;

    public function __construct($name="",  $age=25)
    {
        $this->name = $name;
        $this->age  = $age;
    }

    public function __set($property, $value) {
        if ($property=="age")
        {
            if ($value > 150 || $value < 0) {
                return;
            }
        }
        $this->$property = $value;
    }

    public function say(){
        echo "My name is ".$this->name.",I'm ".$this->age." years old";
    }
}

$Person=new Person("John", 25); //请注意,类初始化并为“name”和“age”分配初始值。
$Person->name = "Lili";     // "name" 属性值被成功修改。如果没有__set()方法,程序将报错。
$Person->age = 16; // "age"属性修改成功。
$Person->age = 160; //160是无效值,因此修改失败。
$Person->say();  //输出:My name is Lili, I'm 16 years old。
ログイン後にコピー

コードの実行結果:

My name is Lili, I'm 16 years old
ログイン後にコピー

7. __​​isset()

__isset() メソッドを使用する前に、 let まずは isset() メソッドの使い方を説明します。 isset() メソッドは主に、この変数が設定されているかどうかを判断するために使用されます。

isset() メソッドがオブジェクトの外部で使用される場合は、次の 2 つの状況が考えられます。

  1. パラメータがパブリック プロパティの場合、isset() メソッドを使用して決定することができます。パラメータが属性に設定されているかどうか。
  2. パラメータがプライベート プロパティの場合、isset() メソッドは機能しません。

では、プライベート プロパティの場合、それが設定されているかどうかを知る方法はあるのでしょうか?もちろん、 __isset() メソッドがクラス内で定義されている限り、 isset() メソッドをクラスの外部で使用して、プライベート プロパティが設定されているかどうかを判断できます。

未定義またはアクセスできないプロパティに対して isset() または empty() が呼び出された場合、__isset() メソッドが呼び出されます。以下は例です:

<?php
class Person
{
    public $sex;
    private $name;
    private $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

    /**
     * @param $content
     *
     * @return bool
     */
    public function __isset($content) {
        echo "The {$content} property is private,the __isset() method is called automatically.<br>";
        echo  isset($this->$content);
    }
}

$person = new Person("John", 25); // Initially assigned.
echo isset($person->sex),"<br>";
echo isset($person->name),"<br>";
echo isset($person->age),"<br>";
ログイン後にコピー

コードの実行結果は次のとおりです:

1
The name property is private,the __isset() method is called automatically.
1
The age property is private,the __isset() method is called automatically.
1
ログイン後にコピー

8. __unset()

isset() メソッドに似ています. 未定義の場合、またはアクセスできないプロパティに対して unset() メソッドが呼び出された場合、unset() メソッドが呼び出されます。以下は例です:

<?php
class Person
{
    public $sex;
    private $name;
    private $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

    /**
     * @param $content
     *
     * @return bool
     */
    public function __unset($content) {
        echo "It is called automatically when we use the unset() method outside the class.<br>";
        echo  isset($this->$content);
    }
}

$person = new Person("John", 25); // Initially assigned.
unset($person->sex),"<br>";
unset($person->name),"<br>";
unset($person->age),"<br>";
ログイン後にコピー

コードの実行結果は次のとおりです:

It is called automatically when we use the unset() method outside the class.
1
It is called automatically when we use the unset() method outside the class.
1
ログイン後にコピー

9. __sleep()

serialize() メソッドは、クラス () 内のマジック メソッド __sleep。存在する場合、このメソッドが最初に呼び出され、次にシリアル化操作が実行されます。

__sleep() メソッドは通常、データを保存する前にシリアル化する必要がある属性を指定するために使用されます。この機能は、すべてを保存する必要がない非常に大きなオブジェクトがある場合に便利です。

詳細については、次のコードを参照してください:

<?php
class Person
{
    public $sex;
    public $name;
    public $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

    /**
     * @return array
     */
    public function __sleep() {
        echo "It is called when the serialize() method is called outside the class.<br>";
        $this->name = base64_encode($this->name);
        return array('name', 'age'); // It must return a value of which the elements are the name of the properties returned.
    }
}

$person = new Person('John'); // Initially assigned.
echo serialize($person);
echo '<br/>';
ログイン後にコピー

コードの実行結果は次のとおりです:

It is called when the serialize() method is called outside the class.
O:6:"Person":2:{s:4:"name";s:8:"5bCP5piO";s:3:"age";i:25;}
ログイン後にコピー

10. __wakeup()

およびsleep() メソッド、wakeup() メソッドは通常、データベース接続の再確立やその他の初期化操作の実行などの逆シリアル化操作に使用されます。

<?php
class Person
{
    public $sex;
    public $name;
    public $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

    /**
     * @return array
     */
    public function __sleep() {
        echo "It is called when the serialize() method is called outside the class.<br>";
        $this->name = base64_encode($this->name);
        return array('name', 'age'); // It must return a value of which the elements are the name of the properties returned.
    }

    /**
     * __wakeup
     */
    public function __wakeup() {
        echo "It is called when the unserialize() method is called outside the class.<br>";
        $this->name = 2;
        $this->sex = 'Male';
        // There is no need to return an array here.
    }
}

$person = new Person('John'); // Initially assigned.
var_dump(serialize($person));
var_dump(unserialize(serialize($person)));
ログイン後にコピー

コードの実行結果は次のとおりです:

It is called when the serialize() method is called outside the class.
string(58) "O:6:"Person":2:{s:4:"name";s:8:"5bCP5piO";s:3:"age";i:25;}"
It is called when the unserialize() method is called outside the class.
object(Person)#2 (3) { ["sex"]=> string(3) "Male" ["name"]=> int(2) ["age"]=> int(25) }
ログイン後にコピー

11. __toString()

echo メソッドを使用する場合オブジェクトを直接出力するには、__toString() メソッドを呼び出します。

注: このメソッドは文字列を返す必要があります。そうでない場合は、レベル

E_RECOVERABLE_ERROR

で致命的なエラーが発生します。また、 __toString() メソッドで例外をスローすることもできません。 以下は関連する例です:

<?php
class Person
{
    public $sex;
    public $name;
    public $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

    public function __toString()
    {
        return  'go go go';
    }
}

$person = new Person('John'); // Initially assigned.
echo $person;
ログイン後にコピー

コードの実行結果は次のとおりです:

go go go
ログイン後にコピー

それでは、__toString() メソッドがクラス?試してみましょう。

<?php
class Person
{
    public $sex;
    public $name;
    public $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

}

$person = new Person('John'); // Initially assigned.
echo $person;
ログイン後にコピー

コードの実行結果は次のとおりです:

Catchable fatal error: Object of class Person could not be converted to string in D:\phpStudy\WWW\test\index.php on line 18
ログイン後にコピー

显然,它在页面上报告了一个致命错误,PHP语法不支持这样的写法。

12. __invoke()

当您尝试以调用函数的方式调用对象时,__ invoke()方法将被自动调用。

注意:此功能仅在PHP 5.3.0及更高版本中有效。

下面是相关实例:

<?php
class Person
{
    public $sex;
    public $name;
    public $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

    public function __invoke() {
        echo 'This is an object';
    }

}

$person = new Person('John'); // Initially assigned.
$person();
ログイン後にコピー

运行代码结果如下:

This is an object
ログイン後にコピー

如果坚持使用对象作为方法(但未定义__invoke()方法),则将得到以下结果:

Fatal error: Function name must be a string in D:\phpStudy\WWW\test\index.php on line 18
ログイン後にコピー

13.__set_state()

从PHP 5.1.0开始,在调用var_export()导出类代码时会自动调用__set_state()方法。

__set_state()方法的参数是一个包含所有属性值的数组,其格式为array('property'=> value,...)

在以下示例中,我们没有定义__set_state()方法:

<?php
class Person
{
    public $sex;
    public $name;
    public $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

}

$person = new Person('John'); // Initially assigned.
var_export($person);
ログイン後にコピー

执行代码结果如下:

Person::__set_state(array( 'sex' => 'Male', 'name' => 'John', 'age' => 25, ))
ログイン後にコピー

显然,对象的属性已打印。

现在让我们看看定义__set_state()方法的另一种情况:

<?php
class Person
{
    public $sex;
    public $name;
    public $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

    public static function __set_state($an_array)
    {
        $a = new Person();
        $a->name = $an_array['name'];
        return $a;
    }

}

$person = new Person('John'); // Initially assigned.
$person->name = 'Jams';
var_export($person);
ログイン後にコピー

执行代码结果如下:

Person::__set_state(array( 'sex' => 'Male', 'name' => 'Jams', 'age' => 25, ))
ログイン後にコピー

14. __clone()

在PHP中,我们可以使用clone关键字通过以下语法克隆对象:

$copy_of_object = clone $object;
ログイン後にコピー

但是,使用clone关键字只是一个浅拷贝,因为所有引用的属性仍将指向原始变量。

如果在对象中定义了clone()方法,则将在复制生成的对象中调用clone()方法,该方法可用于修改属性的值(如有必要)。

下面是相关的示例:

<?php
class Person
{
    public $sex;
    public $name;
    public $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

    public function __clone()
    {
        echo __METHOD__."your are cloning the object.<br>";
    }

}

$person = new Person('John'); // Initially assigned.
$person2 = clone $person;

var_dump('persion1:');
var_dump($person);
echo '<br>';
var_dump('persion2:');
var_dump($person2);
ログイン後にコピー

运行代码结果如下:

Person::__clone your are cloning the object.
string(9) "persion1:" object(Person)#1 (3) { ["sex"]=> string(3) "Male" ["name"]=> string(6) "John" ["age"]=> int(25) }
string(9) "persion2:" object(Person)#2 (3) { ["sex"]=> string(3) "Male" ["name"]=> string(6) "John" ["age"]=> int(25) }
ログイン後にコピー

15.__autoload()

__autoload()方法可以尝试加载未定义的类。

过去,如果要在程序文件中创建100个对象,则必须使用include()或require()来包含100个类文件,或者必须在同一类文件中定义100个类。 例如以下:

/**
 * file non_autoload.php
 */

require_once('project/class/A.php');
require_once('project/class/B.php');
require_once('project/class/C.php');
.
.
.

if (ConditionA) {
    $a = new A();
    $b = new B();
    $c = new C();
    // …
} else if (ConditionB) {
    $a = newA();
    $b = new B();
    // …
}
ログイン後にコピー

那么,如果我们使用__autoload()方法呢?

/**
 * file autoload_demo.php
 */
function  __autoload($className) {
    $filePath = “project/class/{$className}.php”;
    if (is_readable($filePath)) {
        require($filePath);
    }
}

if (ConditionA) {
    $a = new A();
    $b = new B();
    $c = new C();
    // …
} else if (ConditionB) {
    $a = newA();
    $b = new B();
    // …
}
ログイン後にコピー

当PHP引擎第一次使用类A时,如果未找到类A,则autoload方法将被自动调用,并且类名称“ A”将作为参数传递。因此,我们在autoload()方法中需要做的是根据类名找到相应的类文件,然后将其包含在内。如果找不到该文件,则php引擎将抛出异常。

16. __debugInfo()

当执行 var_dump() 方法时,__debugInfo() 方法会被自动调用。如果 __debugInfo() 方法未被定义,那么 var_dump 方法或打印出这个对象的所有属性。

举例说明:

<?php
class C {
    private $prop;

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

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

var_dump(new C(42));
ログイン後にコピー

执行结果:

object(C)#1 (1) { ["propSquared"]=> int(1764) }
ログイン後にコピー

注意:__debugInfo() 方法应该在 PHP 5.6.0 及以上版本中使用。

总结

以上就是我所了解的 PHP 魔术方法,其中常用的包括 __set() 还有 __get()__autoload()。如果你还有其他疑问,可以从 PHP 官方网站获得更多帮助。

推荐学习:《PHP视频教程

説明
クラスのコンストラクタ
クラスのデストラクタ
未定義または到達不能なメソッドが呼び出された場合、__call() メソッドが呼び出されます。
未定義または到達不能な静的メソッドが呼び出された場合、__callStatic() メソッドが呼び出されます。
クラスのメンバ変数を取得する場合、__get()メソッドが呼び出されます。
クラスのメンバー変数を割り当てるとき、__set() メソッドが呼び出されます。
未定義または到達不能なメンバーに値を割り当てるために isset() または empty() が呼び出される場合、__isset() メソッドは転送される。
reset() を呼び出して未定義または到達不能なメンバーを更新する場合、__unset() メソッドが呼び出されます。
serialize() を実行すると、__sleep() メソッドが最初に呼び出されます。
逆シリアル化 deserialization() を実行すると、__wakeup() メソッドが最初に呼び出されます。
echo メソッドを使用して表示オブジェクトを直接出力する場合、__toString() メソッドが最初に呼び出されます。
関数を使用してオブジェクトにアクセスする場合、__invoke() メソッドが最初に呼び出されます。
var_export() メソッドが呼び出されるとき、__set_state() メソッドが呼び出されます。
オブジェクトがコピーされて割り当てられると、__clone() メソッドが呼び出されます。
未定義のクラスをロードしようとすると呼び出されます。
デバッグ情報を出力します。

以上がphpマジックメソッドとはの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
php
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
関連するチュートリアル
人気のおすすめ
最新のコース
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート