42、PHP面向对象中的魔术方法

阅读() @2019-03-17 16:05:05

1、一个对象克隆另一个对象的时候,类里边的__clone方法自动执行。

只要一个对象一诞生,就要有初始化的动作。如果副本对象和原来的对象一模一样就会有问题,所以,这个时候需要调用__clone()方法。__clone()里边的$this代表副本中的对象。$that代表原对象。

class A{
	public $num = 1;
	public function show(){
		echo $this->num;//1
	}
	function __clone(){
		echo ++$this->num;//2
	}
}
$a = new A();

	$b = $a;
	echo intval($a===$b);//1

echo $a->show();
$b = clone $a;
//echo intval($a===$b);//0,内容虽然一样,但是在内存中的地址不同

2、实例化的对象不可以直接用echo输出,但是如果类中有__toString方法,就可以输出相应的信息。

class B{
	private $host;
	private $dbname;
	private $user;
	private $pwd;
	function __construct($host,$dbname,$user,$pwd){
		$this->host = $host;
		$this->dbname = $dbname;
		$this->user = $user;
		$this->pwd = $pwd;
	}
	public function connect(){
		echo '连接数据库';
	}
	public function gettable(){
		echo '获得表名';
	}
	public function insert(){
		echo '插入数据库';
	}
	function __toString(){
		$method = get_class_methods(__CLASS__);//获得当前类的所有方法(数组形式)
		$methodString = implode('、',$method);
		//return $methodString;//__construct、connect、gettable、insert、__toString
		
		$vars = get_object_vars($this);//获得当前对象的所有属性(数组形式)
		$varsString = implode('、',$vars);
		return $varsString;//localhost、mydb、admin、admin
	}
}
$b = new B('localhost','mydb','admin','admin');
echo $b;//如果类中没有__toString方法会报错

如果没有toString()方法,直接输出对象对发生致命性错误。

输出对象时应注意:echo或print_r函数后面直接跟输出的对象,中间不要加其他多余的字符,否则__toString()方法不会被执行,例如这种情况:echo '输出对象'.$obj;

3、实例化的对象执行没有定义的方法或无权限访问的方法会报错,但是通过__call方法可以避免报错,并输出一些提示信息!

class C{
	public function show(){
		echo 'show';
	}
	function __call($methodName/*方法名*/,$args/*参数*/){
		echo $methodName;
	}
}
$c = new C();
$c->go();

4、__get():当我们调用一个权限上不允许调用的属性或不存在的属性时,__get魔术方法会自动调用,并且自动传参,参数值是属性名。

class Person{
	public $name = 'zym';
	protected $age = 23;
	private $sex = 'man';
	function __get($var){
		echo '你想访问我的'.$var.'属性';
	}
}
$person = new Person();
echo $person->name;//zym
echo $person->age;//你想访问我的age属性
echo $person->sex;//你想访问我的sex属性
echo '<pre/>';
print_r($person);

5、__set():当我们给一个权限上不允许直接访问或者是不存在的属性设置属性值时,__set魔术方法会自动调用,并且自动传参,第一个参数数属性名,第二个参数是属性值。

class Person{
	public $name;
	protected $age;
	private $sex;
	public function __set($a,$b){
		echo '你想给我的'.$a.'赋值'.'并且值是'.$b.'<br/>';
	}
}
$person = new Person();
$person->name = 'zym';//zym
$person->age = '23';//你想给我的age赋值并且值是23
$person->sex = 'man';//你想给我的sex赋值并且值是man
echo $person->name.'<br/>';

6、用isset()判断某个某个属性属性是否存在时,__isset()自动执行。

用unset()清除一个权限上不允许访问或者是不存在的属性时,__unset()自动执行。

class Person{
	public $name = 'zym';
	protected $age = '23';
	private $sex = 'man';
	function __isset($a){
		echo '你想判断我的'.$a.'值是否存在'.'<br/>';
	}
	function __unset($b){
		echo '你想删除我的'.$b.'属性值'.'<br/>';
	}
}
$person = new Person();
if(isset($person->name)){
	echo $person->name.'<br/>';
}
if(isset($person->sex)){
	echo '有这个值'.'<br/>';
}else{
	echo '没有这个值'.'<br/>';
}
unset($person->age);
/*
//运行结果如下:
zym
你想判断我的sex值是否存在
没有这个值
 你想删除我的age属性值
*/

7、__sleep():在使用serialize()函数时,如果实例化的对象包含__sleep()方法,则会先执行__sleep()方法,这个方法返回一个数组,数组元素就是类属性,可以包括全部的类属性,也可以随便包括其中的几个。

__wakeup():unserialize()函数可以重新还原一个被serialize()函数序列化的对象,__wakeup()方法则是恢复在序列中可能丢失的数据库连接及相关工作!

class Person{
	public $name;
	public $sex;
	private $age;
	public function __construct($name,$sex,$age){
		$this->name = $name;
		$this->sex = $sex;
		$this->age = $age;
	}
	public function __sleep(){
		return array('name','age');
	}
	public function __wakeup(){
		$age+=1;
		return $this->name;
	}
}
$person = new Person('zym','man',23);
$p1 = serialize($person);
echo $p1.'<br/>';
$p2 = unserialize($p1);
echo $p2->name;

因为对象是存储在内存中的,为了提高程序运行效率,当某个对象使用完成之后,就会被垃圾回收机制回收,所以它不可能永久的保存在内存中,这样的话如果其他页面也需要用到这个对象,就比较困难了,这个时候可以把对象利用serialiaze()方法序列化,然后保存在到一个或数据库中,这样的话其他页面就可以随时调用了,然后想要删除这个序列化的对象也是很简单的。

8、__autoload()方法:

其他的魔术方法都是在类中添加起作用,这是一个唯一不在类中添加的方法。

只要在页面中使用到一个类,只要用到类名,就会自动将类名传给__autoload()的参数。

这里用到4个文件:test.php、OneAction.class.php、TwoAction.class.php、ThreeAction.class.php。

test.php文件中的代码是:

function __autoload($className){
	include $className.'.class.php';
}
$one = new OneAction();
$two = new TwoAction();
$three = new ThreeAction();

OneAction.class.php文件中的代码是:

<?php
	class OneAction{
		public function __construct(){
			echo 'oneAction'.'<br/>';
		}
	}
?>

TwoAction.class.php文件中的代码是:

<?php
	class TwoAction{
		public function __construct(){
			echo 'twoAction'.'<br/>';
		}
	}
?>

ThreeAction.class.php文件中的代码是:

<?php
	class ThreeAction{
		public function __construct(){
			echo 'threeAction'.'<br/>';
		}
	}
?>

需要注意的是:__autoload()方法中的参数是类名,当本脚本中实例化对象的时候找不到某个类,就会自动调用autoload魔术方法,所以魔术方法内部的inlude文件地址与类的名称要相对应!

微信二维码
锐壳主机