PHP面向对象 1.7 常见的魔术方法及应用
1. __clone()
该方法是在对象克隆时自动调用的,所以就可以通过此方法对克隆后的副本进行重新初始化。
__clone()方法不需要任何参数,该方法中自动包含
$this
和$that
两个对象的引用。$this
是副本对象的引用,$that
是原本对象的引用。
<?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()方法一定要有一个字符串作为返回值。通常在此方法中返回的字符串是使用对象中多个属性值链接而成的。
<?php
//声明一个Myclass类,在类中声明一个常量和一个成员方法
class TestClass {
private $foo; //在类中声明一个成员方法
function __construct($foo) {
$this->foo = $foo;
}
public function __toString() {
return $this->foo;
}
}
$obj = new TestClass('Hello world!');
echo $obj;//直接输出__toString中的返回值Hello world!
3. __call()方法
调用对象中不存在的方法时会自动调用该方法,并且程序也会继续向下执行
需要两个参数:第一个参数是调用不存在的方法时,接收这个方法名称的字符串,而参数列表则以数组的形式传递到__call()方法的第二个参数中
魔术方法call的高级应用:连贯操作
<?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会用一个参数来调用它,即类的名称。
/*这个例子中假设当前目录下每个文件对应一个类,当脚本尝试来创建一个类User()实例时,PHP会自动执行__autoload()函数,脚本假设user.class.php中定义有User类,不管调用时是大写还是小写,PHP将会返回名称的小写。。在组织定义类的文件名时一定要注意规则。*/
<?php
//声明一个自动加载类的魔术方法__autoload()
function __autoload($className) {
//在方法中使用include包含所在的文件
include(strtolower($className) . ".class.php");
}
$obj = new User(); //User类不存在,则自动调用__autoload()函数,将类名"User"作为参数传入
$obj2 = new Shop(); //Shop类不存在则自动调用__autoload()函数,将类名"shop"作为参数传入
5. 对象串行化
对象会随着生成对象的程序的终止而终止,有时候需要将对象的状态记录下来,需要时再进行恢复。串行化就是把整个对象转化成为二进制字符串。
对象需要在网络中传输时,将对象串行化成二进制串后在网络中传输
对象需要持久保存时,将对象串行化写入文件或是数据库中
serialize()函数进行串行化一个对象,参数为对象的引用名,返回值为一个被串行化的字符串。
unserialize()函数进行反串行化,把串行化后的二进制字符串再转化为对象。
person.class.php
<?php
// 声明一个Person类,包含三个成员属性和一个成员方法
class Person{
private $name; //人的名字
private $sex; //人的性别
private $age; //人的年龄
//构造方法为成员属性赋初值
function __construct($name="",$sex="",$age=""){
$this->name = $name;
$this->sex = $sex;
$this->age = $age;
}
//这个人可以说话的方法,说出自己的成员属性
function say(){
echo "我的名字:".$this->name.".性别:".$this->sex.",年龄:".$this->age."<br/>";
}
}
serialize.php
<?php
require "person.class.php"; //在本文件中包含Person类所在的脚本文件
$person = new person("张三","男",20); //通过person类创建一个对象,对象的引用名为$person
$person_string = serialize($person); //进行串行化
file_put_contents("file.txt", $person_string); //将串行化后返回的字符串保存到file.txt文件中
unserialize.php
<?php
require "person.class.php"; //在本文件中包含Person类所在的脚本文件
$person_string = file_get_contents("file.txt"); //将file.txt文件中的字符串读出来并复制给变量$person_string
$person = unserialize($person_string); //进行反串行化操作,形成对象$person
$person->say(); //调用对象中的say()方法,用来测试饭串行化的对象是否成功
6. __sleep()和__wakeup()
__sleep():在调用serialize()函数将对象串行化时,会自动调用对象中的__sleep()方法,用来将对象中的部分成员串行化。
__wake(): 在调用unserizlize()函数反串行化时会自动调用,用来在二进制串重新组成一个对象时,为新对象中的成员属性重新初始化。
__sleep()函数不需要接受任何参数,但需要返回一个数组,在数组中包含需要串行化的属性。未被包含在数组中的属性将在串行化时被忽略。如果没有___sleep()方法,则对象中的所有属性都将被串行化。
<?php
//声明一个Person类
class Person{
private $name;
private $sex;
private $age;
function __construct($name="",$sex = "",$age = ""){
$this->name = $name;
$this->sex = $sex;
$this->age = $age;
}
function say(){
echo "我的名字:".$this->name.",性别:".$this->sex.".年龄:".$this->age."<br/>";
}
//在类中添加如此方法,在串行化时自动调用返回数组
function __sleep(){
$arr = array("name","age"); //数组中的成员$name 和$age 将被串行化,成员sex将被忽略
return $arr;
}
//在反串行化对象时自动调用该方法,没有参数也没有返回值
function __wakeup(){
$this->age = 40; //在重新组织对象时,为新对象中的$age属性重新赋值
}
}
$person1 = new Person("张三","男",20);
//串行化,忽略属性sex
$person_string = serialize($person1);
echo $person_string."<br/>";
//反串行化对象,并自动调用__wakeup()方法重新为新对象$age赋值
$person2 = unserialize($person_string); //反串行化后形成的对象$person2重新赋值$age = 40;
$person2->say(); //已经没有sex属性
结果
O:6:"Person":2:{ s:12:"Personname";s:6:"张三";s:11:"Personage";i:20;}
我的名字:张三,性别:.年龄:40
还没有评论,来说两句吧...