详解php魔术方法(Magic methods)的使用方法


Posted in PHP onFebruary 14, 2016

PHP中把以两个下划线__开头的方法称为魔术方法,这些方法在PHP中充当了举足轻重的作用。 魔术方法包括:

  • __construct(),类的构造函数
  • __destruct(),类的析构函数
  • __call(),在对象中调用一个不可访问方法时调用
  • __callStatic(),用静态方式中调用一个不可访问方法时调用
  • __get(),获得一个类的成员变量时调用
  • __set(),设置一个类的成员变量时调用
  • __isset(),当对不可访问属性调用isset()或empty()时调用
  • __unset(),当对不可访问属性调用unset()时被调用。
  • __sleep(),执行serialize()时,先会调用这个函数
  • __wakeup(),执行unserialize()时,先会调用这个函数
  • __toString(),类被当成字符串时的回应方法
  • __invoke(),调用函数的方式调用一个对象时的回应方法
  • __set_state(),调用var_export()导出类时,此静态方法会被调用。
  • __clone(),当对象复制完成时调用

__construct()和__destruct()

构造函数和析构函数应该不陌生,他们在对象创建和消亡时被调用。例如我们需要打开一个文件,在对象创建时打开,对象消亡时关闭

<?php 
class FileRead
{
 protected $handle = NULL;

 function __construct(){
  $this->handle = fopen(...);
 }

 function __destruct(){
  fclose($this->handle);
 }
}
?>

这两个方法在继承时可以扩展,例如:

<?php 
class TmpFileRead extends FileRead
{
 function __construct(){
  parent::__construct();
 }

 function __destruct(){
  parent::__destruct();
 }
}
?>

__call()和__callStatic()

在对象中调用一个不可访问方法时会调用这两个方法,后者为静态方法。这两个方法我们在可变方法(Variable functions)调用中可能会用到。

<?php
class MethodTest 
{
 public function __call ($name, $arguments) {
  echo "Calling object method '$name' ". implode(', ', $arguments). "\n";
 }

 public static function __callStatic ($name, $arguments) {
  echo "Calling static method '$name' ". implode(', ', $arguments). "\n";
 }
}

$obj = new MethodTest;
$obj->runTest('in object context');
MethodTest::runTest('in static context');
?>

__get(),__set(),__isset()和__unset()

当get/set一个类的成员变量时调用这两个函数。例如我们将对象变量保存在另外一个数组中,而不是对象本身的成员变量

<?php 
class MethodTest
{
 private $data = array();

 public function __set($name, $value){
  $this->data[$name] = $value;
 }

 public function __get($name){
  if(array_key_exists($name, $this->data))
   return $this->data[$name];
  return NULL;
 }

 public function __isset($name){
  return isset($this->data[$name])
 }

 public function unset($name){
  unset($this->data[$name]);
 }
}
?>

__sleep()和__wakeup()

当我们在执行serialize()和unserialize()时,会先调用这两个函数。例如我们在序列化一个对象时,这个对象有一个数据库链接,想要在反序列化中恢复链接状态,则可以通过重构这两个函数来实现链接的恢复。例子如下:

<?php
class Connection 
{
 protected $link;
 private $server, $username, $password, $db;

 public function __construct($server, $username, $password, $db)
 {
  $this->server = $server;
  $this->username = $username;
  $this->password = $password;
  $this->db = $db;
  $this->connect();
 }

 private function connect()
 {
  $this->link = mysql_connect($this->server, $this->username, $this->password);
  mysql_select_db($this->db, $this->link);
 }

 public function __sleep()
 {
  return array('server', 'username', 'password', 'db');
 }

 public function __wakeup()
 {
  $this->connect();
 }
}
?>

__toString()

对象当成字符串时的回应方法。例如使用echo $obj;来输出一个对象

<?php
// Declare a simple class
class TestClass
{
 public function __toString() {
  return 'this is a object';
 }
}

$class = new TestClass();
echo $class;
?>

这个方法只能返回字符串,而且不可以在这个方法中抛出异常,否则会出现致命错误。

__invoke()

调用函数的方式调用一个对象时的回应方法。如下

<?php
class CallableClass 
{
 function __invoke() {
  echo 'this is a object';
 }
}
$obj = new CallableClass;
var_dump(is_callable($obj));
?>

__set_state()

调用var_export()导出类时,此静态方法会被调用。

<?php
class A
{
 public $var1;
 public $var2;

 public static function __set_state ($an_array) {
  $obj = new A;
  $obj->var1 = $an_array['var1'];
  $obj->var2 = $an_array['var2'];
  return $obj;
 }
}

$a = new A;
$a->var1 = 5;
$a->var2 = 'foo';
var_dump(var_export($a));
?>

__clone()

当对象复制完成时调用。例如在设计模式详解及PHP实现:单例模式一文中提到的单例模式实现方式,利用这个函数来防止对象被克隆。

<?php 
public class Singleton {
 private static $_instance = NULL;

 // 私有构造方法 
 private function __construct() {}

 public static function getInstance() {
  if (is_null(self::$_instance)) {
   self::$_instance = new Singleton();
  }
  return self::$_instance;
 }

 // 防止克隆实例
 public function __clone(){
  die('Clone is not allowed.' . E_USER_ERROR);
 }
}
?>

魔术常量(Magic constants)

PHP中的常量大部分都是不变的,但是有8个常量会随着他们所在代码位置的变化而变化,这8个常量被称为魔术常量。

  • __LINE__,文件中的当前行号
  • __FILE__,文件的完整路径和文件名
  • __DIR__,文件所在的目录
  • __FUNCTION__,函数名称
  • __CLASS__,类的名称
  • __TRAIT__,Trait的名字
  • __METHOD__,类的方法名
  • __NAMESPACE__,当前命名空间的名称

这些魔术常量常常被用于获得当前环境信息或者记录日志。

以上就是本文的全部内容,希望对大家的学习有所帮助。

PHP 相关文章推荐
用php实现像JSP,ASP里Application那样的全局变量
Jan 12 PHP
附件名前加网站名
Mar 23 PHP
php中判断数组是一维,二维,还是多维的解决方法
May 04 PHP
Laravel 5框架学习之Laravel入门和新建项目
Apr 07 PHP
PHP实现QQ空间自动回复说说的方法
Dec 02 PHP
ThinkPHP使用Ueditor的方法详解
May 20 PHP
PHP Socket网络操作类定义与用法示例
Aug 30 PHP
ThinkPHP开发--使用七牛云储存
Sep 14 PHP
php/JS实现的生成随机密码(验证码)功能示例
Jun 06 PHP
PHP大文件切割上传并带进度条功能示例
Jul 01 PHP
ThinkPHP5+UEditor图片上传到阿里云对象存储OSS功能示例
Aug 05 PHP
tp5递归 无限级分类详解
Oct 18 PHP
PHP浮点比较大小的方法
Feb 14 #PHP
PHP魔术方法使用方法汇总
Feb 14 #PHP
PHP函数超时处理方法
Feb 14 #PHP
PHP使用file_get_content设置头信息的方法
Feb 14 #PHP
PHP下使用mysqli的函数连接mysql出现warning: mysqli::real_connect(): (hy000/1040): ...
Feb 14 #PHP
PHP缓冲区用法总结
Feb 14 #PHP
PHP二维数组排序简单实现方法
Feb 14 #PHP
You might like
不用GD库生成当前时间的PNG格式图象的程序
2006/10/09 PHP
PHP中date()日期函数有关参数整理
2011/07/19 PHP
PHP fopen()和 file_get_contents()应用与差异介绍
2014/03/19 PHP
php数组指针操作详解
2017/02/14 PHP
ext监听事件方法[初级篇]
2008/04/27 Javascript
jQuery 1.7.2中getAll方法的疑惑分析
2012/05/23 Javascript
jQuery的text()方法用法分析
2014/12/20 Javascript
小米公司JavaScript面试题
2014/12/29 Javascript
jQuery UI设置固定日期选择特效代码分享
2015/08/27 Javascript
JS设置下拉列表框当前所选值的方法
2015/12/22 Javascript
表单中单选框添加选项和移除选项
2016/07/04 Javascript
基于Bootstrap实现的下拉菜单手机端不能选择菜单项的原因附解决办法
2016/07/22 Javascript
jQuery实现图片滑动效果
2017/03/08 Javascript
JavaScript 用fetch 实现异步下载文件功能
2017/07/21 Javascript
[02:27]《DAC最前线》之附加赛征程
2015/01/29 DOTA
Python __setattr__、 __getattr__、 __delattr__、__call__用法示例
2015/03/06 Python
Python聊天室实例程序分享
2016/01/05 Python
python直接访问私有属性的简单方法
2016/07/25 Python
Python实现的弹球小游戏示例
2017/08/01 Python
Python subprocess模块功能与常见用法实例详解
2018/06/28 Python
Python requests库用法实例详解
2018/08/14 Python
详解Python的三种可变参数
2019/05/08 Python
python多线程并发实例及其优化
2019/06/27 Python
线程安全及Python中的GIL原理分析
2019/10/29 Python
python实现word文档批量转成自定义格式的excel文档的思路及实例代码
2020/02/21 Python
tensorflow 动态获取 BatchSzie 的大小实例
2020/06/30 Python
加拿大最大的钻石商店:Peoples Jewellers
2018/01/01 全球购物
法国二手MacBook销售网站:Okamac
2019/03/18 全球购物
捷克街头、运动和滑板一站式商店:BoardStar.cz
2019/10/06 全球购物
大学生最常用的自我评价
2013/12/07 职场文书
高中毕业生生活的自我评价
2013/12/08 职场文书
渔夫的故事教学反思
2014/02/14 职场文书
党支部特色活动方案
2014/08/20 职场文书
工资证明范本
2015/06/12 职场文书
2016年春季运动会广播稿
2015/08/19 职场文书
《颐和园》教学反思
2016/02/19 职场文书