详解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执行速度全攻略
Oct 09 PHP
基于mysql的论坛(7)
Oct 09 PHP
php ignore_user_abort与register_shutdown_function 使用方法
Jun 14 PHP
php中几种常见安全设置详解
Apr 06 PHP
ThinkPHP中url隐藏入口文件后接收alipay传值的方法
Dec 09 PHP
PHP统计数值数组中出现频率最多的10个数字的方法
Apr 20 PHP
php封装的单文件(图片)上传类完整实例
Oct 18 PHP
使用PHP下载CSS文件中的所有图片【几行代码即可实现】
Dec 14 PHP
PHP封装的简单连接MongoDB类示例
Feb 13 PHP
Thinkphp5框架ajax接口实现方法分析
Aug 28 PHP
Laravel框架实现文件上传的方法分析
Sep 29 PHP
PHP开发api接口安全验证操作实例详解
Mar 26 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
VOLVO车载收音机
2021/03/02 无线电
PHP 采集获取指定网址的内容
2010/01/05 PHP
学习php笔记 字符串处理
2010/10/19 PHP
php对数组排序的简单实例
2013/12/25 PHP
jQuery弹出层插件简化版代码下载
2008/10/16 Javascript
强大的jquery插件jqeuryUI做网页对话框效果!简单
2011/04/14 Javascript
jQuery实现列表自动循环滚动鼠标悬停时停止滚动
2013/09/06 Javascript
用jquery等比例控制图片宽高的具体实现
2014/01/28 Javascript
纯js和css实现渐变色包括静态渐变和动态渐变
2014/05/29 Javascript
Javascript中For In语句用法实例
2015/05/14 Javascript
javascript精确统计网站访问量实例代码
2015/12/19 Javascript
JS模仿手机端九宫格登录功能实现代码
2016/04/28 Javascript
Bootstrap 表单验证formValidation 实现表单动态验证功能
2017/05/17 Javascript
基于JavaScript实现无缝滚动效果
2017/07/21 Javascript
vue与vue-i18n结合实现后台数据的多语言切换方法
2018/03/08 Javascript
浅谈react性能优化的方法
2018/09/05 Javascript
新手快速上手webpack4打包工具的使用详解
2019/01/28 Javascript
浅谈发布订阅模式与观察者模式
2019/04/09 Javascript
微信小程序实现左滑动删除效果
2020/03/30 Javascript
JS原型和原型链原理与用法实例详解
2020/02/05 Javascript
elementui更改el-dialog关闭按钮的图标d的示例代码
2020/08/04 Javascript
NodeJS模块Buffer原理及使用方法解析
2020/11/11 NodeJs
vue实现广告栏上下滚动效果
2020/11/26 Vue.js
Python读写docx文件的方法
2018/05/08 Python
python查看列的唯一值方法
2018/07/17 Python
Random 在 Python 中的使用方法
2018/08/09 Python
使用python分析统计自己微信朋友的信息
2019/07/19 Python
Django之form组件自动校验数据实现
2020/01/14 Python
django queryset 去重 .distinct()说明
2020/05/19 Python
python利用tkinter实现图片格式转换的示例
2020/09/28 Python
Python xlwings插入Excel图片的实现方法
2021/02/26 Python
应届毕业生专业个人求职自荐信格式
2013/11/20 职场文书
统计岗位职责
2014/02/21 职场文书
大学生入党推荐书范文
2014/05/17 职场文书
开展读书活动总结
2014/06/30 职场文书
安全教育日主题班会
2015/08/13 职场文书