设为首页 收藏本站
查看: 701|回复: 0

[经验分享] PHP魔法方法/函数详解

[复制链接]

尚未签到

发表于 2017-3-23 12:19:54 | 显示全部楼层 |阅读模式
引自:
http://blog.csdn.net/inqihoo/article/details/9235103
在php的语法中,有一些系统自带的方法名,均以双下划线开头,它会在特定的情况下被调用。即所谓的魔法函数。
只有当你已经为一个给定类定义了这些魔法方法时,它们才会起作用。还要注意,这些方法不能直接调用,而只能通过要截获的事件来调用。
它们在面向对向编程中起着至关重要的作用。所以个人觉得很有必要整理一下。下面就php的15个魔法函数做一个详细整理:
1. __construct() 和 __destruct()
__construct() 对象初始化时会调用此方法(对于内核而言是指初始化完成后调用此方法).此方法用得比较多。__destruct() 当对象销毁时会调用此方法.那么什么时候对象会销毁呢?一是用户主动销毁对象,二是当程序结束时由引擎自动销毁
[php] view plaincopy
class People {  
protected $_alive;  
public function __construct()  
{  
$this->_alive = true;   
echo 'Birth'.PHP_EOL;  
}  
public function __destruct()  
{  
$this->_alive = false;  
echo 'Die'.PHP_EOL;  
}  
}  
//主动销毁对象  
$test = new Test();  
unset($test);  
sleep(1);  
//程序完成后自动销毁对象  
$test = new Test();  
sleep(1);  

2. __get() 和 __set()
面向对象编程中使用频率很高的两个方法.当设置和获取对象的属性不允许访问时性,此方法会被调用。一定注意是不存在或不允许被读写时才会被调用。
因此对于一个对象,其属性不确定时,用这两个方法效果很好。
__get($name) 获取对象不存在的属性或无法访问的属性时调用.$name表示要获取的属性名
__set($name, $value) 设置对象不存在的属性或无法访问的属性时调用.$name表示要设置的属性名,$value表示要设置的值.
//例如:我们可以构建一个不确定属性的数据记录类  
class Record {  
protected $_data;   
public function __get($name)  
{  
if (isset($this->_data[$name])) {  
return $this->_data;  
}  
return false;  
}  
public function __set($name, $value)   
{  
$this->_data = $value;  
}  
}  
$record = new Record();  
$record->name = 'andrew';  
echo 'My name is '.$record->name.PHP_EOL;  

3. __isset() 和 __unset()
这两个方法用得比较少些。当调用方法isset()判断对象是否存在某属性, 调用unset()注销某属性时。且当这些属性不存在或不可访问时,会分别调用__isset()和__unset()方法
与前面的__get()和__set()略同。都是某属性不存在或不可访问时被调用
__isset($name) 当调用方法isset()方法判断不可访问的类属性时调用.$name表示属性名.
__unset($name) 当调用方法unset()方法删除不可访问的类属性时调用.$name表示属性名.
//例如:  
class People {  
public $name;  
public $sex;  
private $_age;  
public function __construct($name, $sex, $age)  
{  
$this->name = $name;  
$this->sex  = $sex;  
$this->_age = $age;  
}  
public function __isset($name)  
{  
echo 'The property '.$name.' not exists'.PHP_EOL;  
}  
public function __unset($name)  
{  
echo 'The property '.$name.' can not be unset'.PHP_EOL;  
}  
}  
$people = new People('andrew', 'male', 28);  
isset($people->name);  
isset($people->real_name);  
unset($people->_age);  

4. __call() 和 __callStatic()
前面,我们发现,在获取对象的属性时,如果此属性不存在会调用__get()方法。那么如果调用此对象的方法时,如果此方法不存在呢?php引擎会自动调用__call()方法。
同样,如果调用的是静态方法,且不存在时会调用__callStatic()方法。需要注意的是,__callStatic()使用时是一个静态方法,且仅在php5.3以上版本才支持.
__call($method, $args) 调用对象方法不存在或不允许被调用时此方法会被调用。$method表示调用的方法名,$args表示调用的参数
__callStatic($method, $args) 调用对象的静态方法不存在或不允许被调用时此方法会被调用。$method表示调用的方法名,$args表示调用的参数.
[php] view plaincopy
//例如:我们假定人只有跳走两种行为  
class People {  
public function jump()  
{  
echo 'I can jump'.PHP_EOL;  
}  
public function walk()  
{  
echo 'I can walk'.PHP_EOL;  
}  
public function __call($method, $args)  
{  
echo 'I can not '.$method.PHP_EOL;  
}  
//此方法必须是静态方法,且在php5.3版本下可用  
public static function __callStatic($method, $args)  
{  
echo 'We can not'.$method.PHP_EOL;  
}  
}  
$people = new People();  
$people->jump();  
$people->walk();  
$people->fly();  
People::fly();  

5. __sleep() 和 __wakeup()
这两个方法,咋一看,就是睡觉和唤醒嘛。那跟对象有什么关系?有时候该用的时候也想不起来。其实,我们简单点记,在php中有一个让对象睡觉的方法,叫searialize(),
它会将对象的各属性序列化以方便保存起来。而unsearialize()方法是将保存的序列化的数据解开变成对象。也叫唤醒。相对应的,当睡觉时,php会调用__sleep()方法,它
的返回值必须是一个数组,表示需要保存的属性项, 对于文件句柄,数据库连接等资源类型的数据是不能被序列化保存的。同理唤醒对象时,php会调用__wakeup()方法,
但与__sleep()不同的是,它返回值为空。被保存的属性都会被解开。那它有什么用呢?刚我们说了,searialize是不能保存资源的。那么唤醒时如果我们想用到这些资源怎么
办?回答很肯定,重新创建?那在哪里创建合适呢?当然是__wakeup()方法里面,因为每次唤醒时都会调用此方法嘛。这下我们很清楚这两个方法的用途了。
__sleep() 当调用searialize()方法时调用,返回值为数组,表示需要序列化的数据项.
__wakeup() 当调用unsearizlie()方法时调用。一般用来在唤醒时初始化资源对象.
[php] view plaincopy
//例如我们有一个用户类,用户名和性别都是类属性。用户的密码存在文件中  
Class User {  
public $username;  
public $sex;  
public $passFile;  
private $_password;  
public function __construct($username, $sex, $passFile)  
{  
$this->username = $username;  
$this->sex      = $sex;  
$this->passFile = $passFile;  
$this->_password = file_get_contents($passFile);  
}  
public function getPassword()  
{  
return $this->_password;  
}  
public function __sleep()  
{  
return array(  
'username', 'sex', 'passFile',  
);  
}  
public function __wakeup()  
{  
$this->_password = file_get_contents($this->passFile);  
}  
}  
$user = new User('andrew', 'male', 'pass.data');  
$serializeData =  serialize($user);  
echo $serializeData.PHP_EOL;  
$user = unserialize($serializeData);  
echo $user->getPassword().PHP_EOL;  

6. __toString()
当对象在需要转换成字符串时,会调用此方法。例如,echo对象时,将对象强制转换为string类型时, 用于字符串参数的函数中.注意:此方法的返回值必须为字符串。
[php] view plaincopy
//例如:  
class Info {  
public function __toString()  
{  
return "info";  
}  
}  
$info = new Info();  
echo $info.PHP_EOL;  
echo md5($info).PHP_EOL;  
echo (String) $info.PHP_EOL;  
echo substr($info, 0, 2).PHP_EOL;  


7. __clone()
此方法在复制对象时被调用。我们知道在php中.$a为一个对象,$b=$a时。$b为$a的引用。当$a发生改变时。$b也会随之发生变化。那么为了使$b不发生变化,我们需要用$b=clone $a;
那么,当$a在调用clone的时候,引擎会自动调用__clone()方法
[php] view plaincopy
//例如:以下一个简单的例子  
class Data {  
public $value;  
public function __clone()  
{  
echo "Clone myself".PHP_EOL;  
}  
}  
$data = new Data();  
$data->value = 4;  
$newData = clone $data;  
$data->value = 5;  
echo "The data value is: ".$data->value.PHP_EOL;  
echo "The new data value is: ".$newData->value.PHP_EOL;  
//对面向对象比较熟的同学,一定对单例模式不陌生。PHP做单例模式的时候要记住把clone方法给禁掉。因为在单例模式中,是不允许复制对象的。如下例  
class OnlyOne {  
//单例对象  
private static $_instance;  
//不允许外部和子类调用初始化方法  
private function __construct()  
{}  
//不允许复制  
public function __clone()  
{  
throw new Exception('Not allow to clone me');  
}  
//获取单例对象  
public static function getInstance()  
{  
if (self::$_instance != null) {  
return self::$_instance;  
}  
self::$_instance = new self();  
return self::$_instance;  
}  
}  
$onlyOne = OnlyOne::getInstance();  
$newOne  = clone $onlyOne;  

8.  __autoload()
autoload顾名思义就是自动加载。它主要用来自动加载类。那如何自动加载呢?我们都知道在php中,要使用另外一个文件中的类需要用require或include方法
(包括require_once和include_one)导入进来。那么如果我要使用的类未被导入,则引擎会自动调用__autoload()方法。利用此特性,当我们的类名和类文件有规律
地存放时,我们可以使用__autoload()方法,根据需导入的类名,让程序自动导入文件。此函数在许多的MVC框架中起着重要的作用。
__autoload($name) $name表示需要自动导入的类名
[php] view plaincopy
//我们制订规则类名以目录名加下载线拼接而成。例如:类Model_Config_Xml表示Model/Config/Normal.php文件.我们如何实现自动加载  
//有类文件Model/Config/Normal.php内包含类如下:  
class Model_Config_Normal {  
public function __construct()  
{  
echo "Init Model_Config_Normal".PHP_EOL;  
}  
}  

function __autoload($name)  
{  
$classPath = str_replace('_', DIRECTORY_SEPARATOR, $name);  
require_once("$classPath.php");  
}  
//此时将无需再require('Model/Config/Normal.php')  
$config = new Model_Config_Normal();  

9. __set_state()
这个方法用得不多。了解这个方法前,需要先知道var_export()函数,var_export()和var_dump()类似,输出一个变量的字符串表示。他与var_dump的区别在于它的返回结果的是合法的
php代码.此代码可以被eval执行. 注意:此方法是一个静态方法,且在php5.1以上版本才支持。
[php] view plaincopy
//例如:  
class Test {  
public $name;  
public $age;  
public static function __set_state($data)  
{  
$obj = new Test();  
$obj->name = $data['name'];  
$obj->age  = $data['age'] + 1;  
return $obj;  
}  
}  
$test = new Test();  
$test->name = 'andrew';  
$test->age  = 27;  
$code =var_export($test, true);  
echo $code.PHP_EOL;  
eval('$new='.$code.';');  
var_dump($new);  


10. __invoke()
这个方法我刚开始接触的时候,一眼望去,真看不出来它到底干嘛的。主要是不明白invoke是啥意思。后来查了字典才明白。意思是呼叫。英语差伤不起呀。
在php中这个方法用于,把对象当方法用的时候。此方法会被调用。很简单。注意,此方法仅5.3以上版本支持。
[php] view plaincopy
class Invoke {  
public function __invoke()  
{  
echo 'I can run'.PHP_EOL;  
}  
}  
$invoke = new Invoke();  
$invoke();

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-354151-1-1.html 上篇帖子: php http_build_query 下篇帖子: 如何选择PHP培训机构
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表