PHP面向对象 1.7 常见的魔术方法及应用

灰太狼 2022-08-18 02:19 267阅读 0赞

1. __clone()

该方法是在对象克隆时自动调用的,所以就可以通过此方法对克隆后的副本进行重新初始化。

__clone()方法不需要任何参数,该方法中自动包含$this$that两个对象的引用。$this是副本对象的引用,$that是原本对象的引用。

  1. <?php //声明一个Myclass类,在类中声明一个常量和一个成员方法 class MyClass { const CONSTANT = 'CONSTANT VALUE'; //使用const声明一个常量并直接赋上初值; private $name; private $age; private $sex; function __construct($name, $age, $sex) { $this->name = $name; $this->age = $age; $this->sex = $sex; } function __clone() { $this->name = "我是" . $this->name . "的副本"; $this->age = 100; } function say() { echo "我的名字:" . $this->name . ",性别:" . $this->sex . "年龄:" . $this->age; } } $class = new MyClass("chris", 20, '男'); $class2 = clone $class; //创建一个副本class2 $class->say(); $class2->say();

2. 类中通用的方法__toString()

“魔术”方法__toString()是快速获取对象的字符串表示的最简便方式,它是在直接输出对象引用时自动调用的方法。正常情况下如果直接输出对象的应用会报错:”Catchable fatal error:Object of class Person could not be converted to string”

如果在类中听添加了__toString() 方法,则直接输出 __toString方法返回的字符串,所以__toString()方法一定要有一个字符串作为返回值。通常在此方法中返回的字符串是使用对象中多个属性值链接而成的。

  1. <?php
  2. //声明一个Myclass类,在类中声明一个常量和一个成员方法
  3. class TestClass {
  4. private $foo; //在类中声明一个成员方法
  5. function __construct($foo) {
  6. $this->foo = $foo;
  7. }
  8. public function __toString() {
  9. return $this->foo;
  10. }
  11. }
  12. $obj = new TestClass('Hello world!');
  13. echo $obj;//直接输出__toString中的返回值Hello world!

3. __call()方法

调用对象中不存在的方法时会自动调用该方法,并且程序也会继续向下执行

需要两个参数:第一个参数是调用不存在的方法时,接收这个方法名称的字符串,而参数列表则以数组的形式传递到__call()方法的第二个参数中

魔术方法call的高级应用:连贯操作

  1. <?php class DB { //声明一个私有成员属性组,主要是通过下表定义可以参加连贯操作的全部方法名称 private $sql = array( "field" => "", "where" => "", "order" => "", "limit" => "", "group" => "", "having" => "" ); //连贯操作调用field() where() ordre() limit() group() having()方法,组合sql语句 function __call($methodName, $args) { //将第一个参数(代表不存方法的方法名称),全部转换成小写方式,获取方法名称 $methodName = strtolower($methodName); //如果调用的方法名和成员属性数组$sql下标对应上,则将第二个参数给数组中下标对应的元素 if (array_key_exists($methodName, $this->sql)) { $this->sql[$methodName] = $args[0]; } else { echo '调用类' . get_class($this) . '中的方法' . $methodName . '()不存在'; } //返回自己对象则可以继续调用本对象中的方法,形成连贯操作 return $this; } //简单应用,没有实际意义,只是输出连贯操作后组合的一个sql语句,是连贯操作最后调用的一个方法 function select() { echo "SELECT FROM {$this->sql['field']} user {$this->sql['where']} {$this->sql['order']} {$this->sql['limit']} {$this->sql['group']} {$this->sql['having']}"; } } $db = new DB; //连贯操作,也可以分为多行去连续调用多个方法 $db->field('sex,count(sex)') ->where('where sex("男","女")') ->group('group by sex') ->having('having avg(age)>25') ->select(); //如果调用的方法不存在,则 $db->query('SELECT * FROM user');

4.自动加载类__autoload()

__autoload()全局函数(不是在类中声明的函数)。如果存在这个函数,PHP会用一个参数来调用它,即类的名称。

  1. /*这个例子中假设当前目录下每个文件对应一个类,当脚本尝试来创建一个类User()实例时,PHP会自动执行__autoload()函数,脚本假设user.class.php中定义有User类,不管调用时是大写还是小写,PHP将会返回名称的小写。。在组织定义类的文件名时一定要注意规则。*/
  2. <?php
  3. //声明一个自动加载类的魔术方法__autoload()
  4. function __autoload($className) {
  5. //在方法中使用include包含所在的文件
  6. include(strtolower($className) . ".class.php");
  7. }
  8. $obj = new User(); //User类不存在,则自动调用__autoload()函数,将类名"User"作为参数传入
  9. $obj2 = new Shop(); //Shop类不存在则自动调用__autoload()函数,将类名"shop"作为参数传入

5. 对象串行化

对象会随着生成对象的程序的终止而终止,有时候需要将对象的状态记录下来,需要时再进行恢复。串行化就是把整个对象转化成为二进制字符串。

对象需要在网络中传输时,将对象串行化成二进制串后在网络中传输
对象需要持久保存时,将对象串行化写入文件或是数据库中
serialize()函数进行串行化一个对象,参数为对象的引用名,返回值为一个被串行化的字符串。
unserialize()函数进行反串行化,把串行化后的二进制字符串再转化为对象。

person.class.php

  1. <?php
  2. // 声明一个Person类,包含三个成员属性和一个成员方法
  3. class Person{
  4. private $name; //人的名字
  5. private $sex; //人的性别
  6. private $age; //人的年龄
  7. //构造方法为成员属性赋初值
  8. function __construct($name="",$sex="",$age=""){
  9. $this->name = $name;
  10. $this->sex = $sex;
  11. $this->age = $age;
  12. }
  13. //这个人可以说话的方法,说出自己的成员属性
  14. function say(){
  15. echo "我的名字:".$this->name.".性别:".$this->sex.",年龄:".$this->age."<br/>";
  16. }
  17. }

serialize.php

  1. <?php
  2. require "person.class.php"; //在本文件中包含Person类所在的脚本文件
  3. $person = new person("张三","男",20); //通过person类创建一个对象,对象的引用名为$person
  4. $person_string = serialize($person); //进行串行化
  5. file_put_contents("file.txt", $person_string); //将串行化后返回的字符串保存到file.txt文件中

unserialize.php

  1. <?php
  2. require "person.class.php"; //在本文件中包含Person类所在的脚本文件
  3. $person_string = file_get_contents("file.txt"); //将file.txt文件中的字符串读出来并复制给变量$person_string
  4. $person = unserialize($person_string); //进行反串行化操作,形成对象$person
  5. $person->say(); //调用对象中的say()方法,用来测试饭串行化的对象是否成功

6. __sleep()和__wakeup()

__sleep():在调用serialize()函数将对象串行化时,会自动调用对象中的__sleep()方法,用来将对象中的部分成员串行化。
__wake(): 在调用unserizlize()函数反串行化时会自动调用,用来在二进制串重新组成一个对象时,为新对象中的成员属性重新初始化。
__sleep()函数不需要接受任何参数,但需要返回一个数组,在数组中包含需要串行化的属性。未被包含在数组中的属性将在串行化时被忽略。如果没有___sleep()方法,则对象中的所有属性都将被串行化。

  1. <?php
  2. //声明一个Person类
  3. class Person{
  4. private $name;
  5. private $sex;
  6. private $age;
  7. function __construct($name="",$sex = "",$age = ""){
  8. $this->name = $name;
  9. $this->sex = $sex;
  10. $this->age = $age;
  11. }
  12. function say(){
  13. echo "我的名字:".$this->name.",性别:".$this->sex.".年龄:".$this->age."<br/>";
  14. }
  15. //在类中添加如此方法,在串行化时自动调用返回数组
  16. function __sleep(){
  17. $arr = array("name","age"); //数组中的成员$name 和$age 将被串行化,成员sex将被忽略
  18. return $arr;
  19. }
  20. //在反串行化对象时自动调用该方法,没有参数也没有返回值
  21. function __wakeup(){
  22. $this->age = 40; //在重新组织对象时,为新对象中的$age属性重新赋值
  23. }
  24. }
  25. $person1 = new Person("张三","男",20);
  26. //串行化,忽略属性sex
  27. $person_string = serialize($person1);
  28. echo $person_string."<br/>";
  29. //反串行化对象,并自动调用__wakeup()方法重新为新对象$age赋值
  30. $person2 = unserialize($person_string); //反串行化后形成的对象$person2重新赋值$age = 40;
  31. $person2->say(); //已经没有sex属性

结果

  1. O:6:"Person":2:{ s:12:"Personname";s:6:"张三";s:11:"Personage";i:20;}
  2. 我的名字:张三,性别:.年龄:40

发表评论

表情:
评论列表 (有 0 条评论,267人围观)

还没有评论,来说两句吧...

相关阅读

    相关 PHP魔术方法

    PHP 中魔术方法是以下两个划线 “\_\_” 开头的、具有特殊作用的一些方法,可以看作PHP的“语法糖”。 > 语法糖是指那些没有给计算机语言添加新功能,而只是对人类来说更