常见修饰符和魔术方法

final:

只能被用来修饰类和成员方法。

1. 被final修饰后的类不能被继承。
2. 被final修饰后的方法不能被重载。

<?php

/**

final 只能被用来修饰类和成员方法

被final修饰后的成员方法不能被重载, 类不能被继承.

**/
<span id="more-187"></span>


final class demo
{
   public $name;
   public $age;
   public $sex;
   
   function __construct($name,$age,$sex)
   {
       $this->name=$name;
       $this->age=$age;
       $this->sex=$sex;
   }
   final function say()
   {
       echo "My name is: {$this->name} age: {$this->age} sex: {$this->sex}";
   }
}
class noextends extends demo{
    function __construct($name,$age,$sex,$school){
        parent::__construct($name,$age,$sex);
        $this->school=$school;
    }
    function say()
    {
        parent::say();
        echo "我在{$this->school}上学";
    }
}
$c = new noextends('jimmy','22','man','css');
$c->say();

/**

从子类中实例化一个对象,传入4个参数分别对应相应的变量, 因为要考虑到继承的特点, 所以要用到重载, 原本应该正常输入say方法
里的内容,但是父类有一个final 所以父类就是无法被继承的, 同时方法中也用了final, 所以方法也是无法被重载的。


**/

?>

static

只能被用来修饰成员属性和成员方法。

1. 使用static修饰的方法不能访问非静态成员。
2. 使用static修饰的成员可以被同一类的所有对象共享。

访问方式: 在对象中访问使用self::方法或者属性名,在对象外访问使用类名::方法名

<?php

/**

static可以修饰成员属性和成员方法, 被static修饰的成员可以在同一类的所有对象之间共享,

使用static修饰的方法不能访问非静态成员,未被修饰的方法可以访问静态成员。

**/

class demo
{
    static  $name = 'jimmy';
   
    static function say()
    {
    echo  "My name is:".self::$name;
    }
}
class demo2 extends demo{
   
}
$t1 = new demo; //静态成员不能被对象访问, 所以就不需要实例化对象
echo demo::$name; //在对象外使用类名::方法名访问静态成员属性。
demo::say();  //访问静态成员方法。
demo2::say();

?>

const

const只能被用来修饰成员属性(创建一个常量成员属性)
在类内部访问使用self::常量名,在类外访问使用类名::常量名

常量成员属性不可以被修改,比如

<?php

class demo
{
    const name= 'jimmy';
   
    function say()
    {
        echo self::name;
    }
}

$t = new demo;
$t->say();
$t->name='eric cartman'; //常量属性无法被修改,修改后的结果还是输出原名jimmy
$t->say();

?>

魔术方法

__construct 对象实例化的时候会被自动加载

__destruct 程序执行结束的时候会被自动加载

__call 调用对象中不存在的方法的时候会被自动加载

<?php

class demo
{
    public $name;
   
    function __construct()
    {
        echo "对象被实例化了!";
    }
    function say()
    {
        echo "jst a test";
    }
    function __call($methodName,$args)
    {
        echo "你调用的方法{$methodName},参数:";
        print_r($args);
        echo "不存在";
    }
}

$t = new demo;
$t->say1('1a2311');



?>

__autoload 实例化对象类,如果类名不存在会被自动加载

当实例化对象类名不存在时, 会把类名作为参数传入, 然后去寻找是否存在包含类名的文件,如果存在, 就保存到当前空间, 用户可以决定是否加载。

<?php

    function __autoload($fName)
    {
        include $fName.".php";
    }

$m = new demo;


?>

虽然严格来说, 为了保证可维护性, 包含类名文件中的类必须与文件名相同, 但是实际可以名字不同, 具体要看工程类型, 比如该例, 实例化对象时, demo不存在,demo就会被当作参数传入__autoload函数中,autoload找到了,就按照classname.php的形式去包含, 如果classname.php里的是一个phpinfo(),一样会被执行。 这个时候, 如果用户对实例化类名可控同时包含时又没有做好限制,就是一个典型的本地文件包含漏洞了,如果可以控制上传和控制包含的任意类型+实例化类名, 就可以造成代码执行的效果。