《PHP中的魔术常量和魔术方法总结》

PHP中的魔术方法及魔术常量总结

一、魔术方法
__construct和__destruct(相信大家对这两个应该很熟悉)
构造函数的做法(构造函数的作用就是在实例化一个对象的同时,给该对象初始化成员变量)
注意:构造函数通常是public
实例化时的参数需跟构造函数的参数匹配
如果一个类没有定义构造方法,则会自动调用其父类的构造方法(如果有),则实例化时的参数
需跟父类的构造函数的参数匹配(也可以在当前类的构造方法中调用父类的构造方法parent::__construct())
构造函数是 “创建” 对象的时候会自动调用
析构函数是 “销毁” 对象的时候会自动调用(先创建的对象,后销毁)

通常,PHP程序结束后,所有的对象都会自动销毁(其属于PHP内部垃圾回收机制)
注意:
1,析构方法不能调用
2,析构方法不能有形参
3,析构方法中可以用于清理一些在PHP代码结束后不能清理的数据
(也就是垃圾回收机制不能清理的数据),如生成的文件,连接数据库的资源
4,如果一个类没有定义析构函数,则会自动调用其父类的析构函数(如果有)

会触发构造函数的几种情况
1,脚本程序运行结束,自动销毁
2,明确地unset()一个对象变量,则被销毁
3,改变对象变量的值,也会触发
//构造函数和析构函数在继承中的表现

/*
 * 子类中没有定义构造方法时,会自动调用父类的构造方法。因此实例化子类的时候,需要按照父类的构造方法的形式进行
 * 如果子类定义了自己的构造方法,则不会自动调用父类的构造方法,但可以手动调用:parent::__construct();
 * 析构函数也是这样
 */
举一个例子

 

class C{
    public $p1 = 1;
    public $p3 = 3;
    public function __construct($p1, $p3)
    {
        $this->p1 = $p1;
        $this->p3 = $p3;
    }
}
class D extends C{
    public $p2 = 2;
    public function __construct($p1, $p2, $p3){
        parent::__construct($p1, $p3);
        $this->p2 = $p2;
    }
    public function show()
    {
        echo "p1 = ".$this->p1."<br />";
        echo "p2 = ".$this->p2."<br />";
        echo "p3 = ".$this->p3."<br />";
    }
}
$d1 = new D(10,20,30);//一定要按照父类构造方法的形式创建对象才对
$d1->show();

__get()、__set()、__isset()、__unset()
这四个魔术方法,是在PHP的属性重载中出现的
通常面向对象语言的重载技术,其基本语法是这样的:
 * 在一个类中,有多个同名方法,每个方法的参数不同而已,这种现象就称为重载
 * 参数不同可以是:数量,类型,顺序
 *
 * 但在PHP中,一个类中根本就不可以定义多个同名函数,这是语法错误
 * 实际上php的重载,是另一个概念,其指的是:
 * 属性重载:如果使用一个不存在的属性,就会去自动调用类中预先定义好的某个方法以处理数据
 * 方法重载:如果使用一个不存在的方法,就会去自动调用类中预先定义好的某个方法以处理该行为
 *
 * 属性重载:
 * 属性一般有四种使用情形,(1)取值:$v1 = 对象->属性
 * (2)赋值:对象->属性 = XXX值  (3)判断是否存在:isset(对象->属性) (4)销毁:unset(对象->属性);
 *
 * 所谓属性重载,就是在对上述4中情形的属性应用场景中,该对象如何来应对的问题
 * 如果某属性不存在,但在语法上是使用如下情形
 * 出现第(1)种情形会自动调用类中的__get()方法,出现第(2)种情形会自动调用类中的__set()方法,
 * 出现第(3)种情形会自动调用类中的__isset()方法,出现第(1)种情形会自动调用类中的__unset()方法
 * 前提都是,类中要预先定义好这些方法
 */

 

class A{
    public $p1 = 1;
    public $proArr = array();//用于存储“不存在的属性值”
    function __get( $prop_name ){
        if(isset($this->proArr[$prop_name])){
            return $this->proArr[$prop_name];
        }
        return "不存在属性$prop_name";
    }
    function __set( $prop_name , $value){
        $this->proArr[$prop_name] = $value;
    }
    function __isset($prop_name){
        if(isset($this->proArr[$prop_name])){
            return true;
        }
        return false;
    }
    function __unset($prop_name){
        unset($this->proArr[$prop_name]);
    }
}
$o1 = new A();
echo "<br />o1的p1属性值为:".$o1->p1;
echo "<br />o1的p2属性值为:".$o1->p2;//这是一个不存在的属性  调用__get()
$o1->p2 = 2;//给一个不存在的属性赋值,则会自动调用__set()方法
echo "<br />o1的p2属性值为:".$o1->p2;//调用__get()
echo "<br />";
$s1 = isset($o1->p4);
var_dump($s1);


__cal()和__callstatic()
这个是在PHP的方法重载时用到的
/**
 * 方法重载:
 *就是如果调用了没有定义过的方法,会自动调用__call(string $name,array $argument)方法第一个参数是方法名,第二个参数是传给$name函数的参数
 * 如果调用了没有定义的静态方法,会自动调用__callstatic()方法
 * 用法可以到php手册中的“类与对象中找”
 */

 

function f1(){
    echo "我是类外的f1函数";
}
function f2($x,$y){
    echo "我是类外的f2函数<br />";
    return $x+$y;
}
class A{
    public $p1 = 1;
    function __call($name,$array){
        if($name == 'f1'){
            f1();
        }else{
            f2($array[0],$array[2]);
        }
    }
}
$o1 = new A();
$o1->f1();
echo "<br />";
$v1 = $o1->f2(1,2);
echo $v1;


(顺便帮大家温习了一下重载,哈哈…)
__autoload()
“当程序需要一个类”的时候,就会去调用该函数;该函数我们需要自己去定义并在其中写好加载类文件的通用语句。
这个函数不是我们程序中去调用,而是在“需要类的时候”自动调用。而且此时就会传入一个实参进来,是所需要的类的类名

 

function __autoload($className){
    require "./library/" . $className . ".class.php";
}
$o1 = new A();
echo $o1->a;


__sleep()和__wakeup()
当对一个对象进行“序列化”操作的时候,会自动调用类中的__sleep()方法
* 当“反序列化”一个对象的时候,会自动调用对应类中的__wakeup()方法
__sleep()方法中可以进行一些数据(资源)的清理工作,并返回一个数组,该数组可以存储一些想要进行序列化的对象的属性
* __wakeup()方法中,可以在进行反序列化操作的时候进行某些有用的“数据恢复工作”,比如:连接数据库
__tostring()和invoke()
__tostring()方法:当把一个对象当做一个“字符串”来看待(处理)的时候,会自动调用该魔术方法。通过该方法,可以返回“合适”的字符串
* 也可以认为就是对象转换为字符串的结果。如果没有该方法会出错
* __invoke()方法:当对象当做一个“方法”(函数)的时候,会自动调用该魔术方法。比如:$v1 = obj(1,2)//这里$obj是一个对象
//__tostring()

 

class U{
    public $p1 = 1;
    private $p2 = 2;
    function __tostring(){
        return $this->p1 . "," . $this->p2;
    }
}
$o1 = new U();
//echo "<br />" . $o1;//这种直接把对象当字符串使用,如果没有__tostring()方法会报错
echo $o1;

 

class U{
    public $p1 = 1;
    private $p2 = 2;
    function __invoke(){
        echo "<br />对象不应该当函数使用";
        echo "<br />你是否是想调用该对象的方法sum()?";
    }
    function sum($x, $y){
        return $x+$y;
    }
}
$o1 = new U();
$o1(1,2);


二、魔术常量
__LINE__、__FILE__、__CLASS__、__METHOD__、__DIR__
__LINE__:显示文件中的当前行号
__FILE__:文件的完整路径和文件名。如果用在被包含文件中,则返回被包含的文件名。自 PHP 4.0.2 起,__FILE__ 总是包含一个绝对路径(如果是符号连接,则是解析后的绝对路径),而在此之前的版本有时会包含一个相对路径。
__CLASS__:类的名称(PHP 4.3.0 新加)。自 PHP 5 起本常量返回该类被定义时的名字(区分大小写)。在 PHP 4 中该值总是小写字母的。类名包括其被声明的作用区域(例如 Foo\Bar)。注意自 PHP 5.4 起 __CLASS__ 对 trait 也起作用。当用在 trait 方法中时,__CLASS__ 是调用 trait 方法的类的名字。
__METHOD__:类的方法名(PHP 5.0.0 新加)。返回该方法被定义时的名字(区分大小写)。
__DIR__:文件所在的目录。如果用在被包括文件中,则返回被包括的文件所在的目录。它等价于dirname(__FILE__)。除非是根目录,否则目录中名不包括末尾的斜杠。(PHP 5.3.0中新增) =

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值