魔术方法
系统在特定的时机自动调用的方法
1、__get
- 触发时机:对象在外部访问私有成员或者受保护属性时调用
- 该方法有一个参数:参数就是属性名
2、__set
- 触发时机:对象在外部设置私有或者受保护成员属性值得时候调用
- 该方法有两个参数:
- 参数1:成员属性名
- 参数2:要设置的值
class Person
{
public $data = [];
public function __set($name,$value)
{
echo "设置'$name'为$value";
$this->data[$name] = $value;
}
public function __get($name)
{
echo "获取'$name'的值";
if( array_key_exists($name,$this->data) ){
return $this->data[$name];
}
}
}
$person = new Person();
$person->username = 'jack';
echo $person->age;
3、__unset
- 触发时机:对象在外部销毁私有或者受保护成员属性的时候调用
- 该方法有一个参数:参数就是私有的成员属性名
4、__isset
- 触发时机:对象在外部判断私有或者受保护成员属性的时候调用
- 该方法有一个参数:参数就是私有的成员属性名
class Person
{
private $data = [];
public function __isset($name){
return isset($this->data[$name])
}
public function unset($name){
unset($this->data[$name]);
}
}
5、__construct
构造方法
- 触发时机:在创建对象的时候自动调用
6、__destruct
析构方法
- 当对象被销毁的时候
class FileRead
{
protected $handle = NULL;
function __construct(){
$this->handle = fopen(…);
}
function __destruct(){
fclose($this->handle);
}
}
7、__toString
- 触发时机:echo 一个对象的时候触发
- 该函数需要return一个字符串
class Person
{
public $data = [];
public function __toString()
{
return "我是一个对象你偏要echo我";
}
}
$person = new Person();
echo $person;
8、__call
- 触发时机:当调用一个不存在的对象方法的时候触发
- 参数1:函数名
- 参数2 数组 函数中的参数都被存放到这个数组中
class Person
{
public $data = [];
public function __call($func,$array)
{
var_dump($func,$array);
}
}
$person = new Person();
$person->mm('a','b','c');
9、_callStatic
- 触发时机:当调用一个不存在的静态方法的时候
class Person
{
public $data = [];
public static function __callStatic($func,$array)
{
var_dump($func,$array);
}
}
Person::mm('a','b','c');
10、 __sleep
序列化对象,保存对象
- 触发时机:在序列化一个对象的时候调用
- 返回值:数组,数组里你想要的序列的成员属性名
class Person
{
public $name = 'xxx';
public $age = 18;
public $info = '出来浪啊';
public function __sleep()
{
return ['info'];
}
}
$p = new Person();
var_dump(serialize($p));
11、__wakeup
- 触发时机:在反序列化一个对象的时候调用 反序列化成功后,想要让对象执行一些初始化方法,可以写到这个函数中
class Person
{
public $name = 'xxx';
public $age = 18;
public $info = '出来浪啊';
public function __sleep()
{
return ['info'];
}
public function __wakeup(){
$this->def();
}
public function def(){
echo '你们都出去浪吧 不用管我';
}
}
$p = new Person();
$strp = serialize($p);
$obj = unserialize($strp);
12、__clone
- 触发时机:在克隆一个对象的时候调用 在这里可以对克隆出来的对象的属性做一些操作
在PHP5中,当我们创建一个对象的副本的时候,PHP其实只是创建了这个对象的一个引用,而不是复制整个新对象。换句话说,这两个变量会指向相同的东西,通过一个对象对其值得修改会影响到另一个对象
class Person
{
public $name = '聂哥';
}
$nie = new Person();
echo $nie->name; //聂哥
$copy_nie = $nie;
echo $copy_nie->name; //聂哥
echo '<hr/>';
$clone_nie = clone $nie;
$nie->name = '老聂';
echo $copy_nie->name; //老聂
echo $clone_nie->name; //聂哥
事实证明PHP使用引用来传递参数,而不是使用值。PHP这样做是考虑到性能的因素,因为如果复制整个对象为多个副本,在不必要的时候会显得很浪费。 如果我们真正需要分开的、完全独立的对象。我们就需要对象的克隆:
class Person
{
//下面是人的成员属性
public $name; //人的名子
public $sex; //人的性别
public $age; //人的年龄
//定义一个构造方法参数为属性姓名$name、性别$sex和年龄$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>";
}
//对象克隆时自动调用的方法, 如果想在克隆后改变原对象的内容,需要在__clone()中重写原本的属性和方法
function __clone() {
//$this指的复本p2, 而$that是指向原本p1,这样就在本方法里,改变了复本的属性。
$this->name = "我是假的 $that->name";
$this->age = 30;
}
}
$p1 = new Person("张三", "男", 20);
$p2 = clone $p1;
$p1->say();
$p2->say();
13、__invoke
当尝试以调用函数的方式调用一个对象时,__invoke
方法会被自动调用。
class CallableClass
{
function __invoke($x) {
var_dump($x);
}
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));