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