php權限控制

權限修飾符
作用: 用來說明 屬性/方法的權限特點
寫在 屬性/方法前面

共有3個權限修飾符
private 私有的 , 保護的最嚴
protected 保護的
public 公共的 ,保護的最鬆

疑問:
public修飾的屬性/方法,可以在哪兒訪問?private 修飾的屬性/方法,可以在哪兒訪問?

如何判斷屬性/方法 有沒有權限訪問?
答:看訪問時的位置!

private的屬性/方法,只能在類定義的大括號內{},才能訪問
public 的屬性, 在任意位置都可以訪問

class Human {
    public $mood = ''; // 心情,公有
    private $money = 1000; // 錢,私有

    public function showMoney() {
        return $this->money;
    }

    private function secret() {
        echo '我小時候偷吃過一塊肉';
    }

    public function tellMe() {
        $this->secret();
    }
}
$lisi = new Human();

$lisi->mood = 'happy';
echo $lisi->mood,'<br />'; // happy;

$lisi->money = 500; // 調用位置在Human類的{}外面 ,因此,調用失敗
echo $lisi->money; // 調用位置在Human類的{}外面 ,因此,調用失敗

echo $lisi->showMoney(),'<br />'; //showMoney是公共的,在此行可以調用,return $this->money; 這一句運行的環境是在 類的{}內部,因此有權限訪問 money屬性。
$lisi->secret();   // 不可以
$lisi->tellMe();    // 可以,因爲是通過$this->secret();調用,即類內調用的.

總結: private權限控制,只能在類的{} 內調用,走出了{}, 誰也調不動.

權限控制的bug

class Human {
    private $money = 1000;

    public function getMoney($people) {
        return $people->money;
    }

    public function setMoney($people) {
        $people->money -= 500;
    }

}

$zhangsan = new Human();
$lisi = new Human(); 

// echo $lisi->money; // 不行

// 讓李四去打探張三的錢
echo $lisi->getMoney($zhangsan),'<br />';

// 讓李四去改變張三的錢
$lisi->setMoney($zhangsan);
echo $lisi->getMoney($zhangsan),'<br />';

print_r($zhangsan);

/**
奇怪之處在於, 
zhangsan的錢,應該有zhangsan來調用getMoney和setMoney才能影響.

但是和我們前一頁面所寫的原則是符合的:
即:
調用 getMoney,public,有權.
getMoney() 又在類的{}內,有權讀取私有屬性money

調用setMoney,public 有權
setMoney()修改zhangsan的money,發生在類的{}內,有權操作

十八哥的總結
李四讀取和改變張三的錢,這如果從生活角度來看,是不合理的

錢私有,是指 “每個對象的錢,針對每個對象私有”;即:張三的錢,由張三->showMoney才能引用.

李四不應該有權直接引用,或者說,李四->showMoney,也只有權引用李四自己的money屬性.

但是,在上面的代碼中,李四卻顯然引用和改爲張三的錢.
這是因爲:
PHP在實現上,並不是以對象爲單位來控制的權限.而是以類爲單位,來控制的權限,所以前一頁,不斷強調 ,類內,類外,而不是說對象內,對象外.

因爲 類聲明一次,而對象卻可能非常多.以類爲單位,簡化了判斷模型.

第三,從代碼的來看
zend引擎
ce==EG(scope)
這一句判斷的是
調用者屬性的類 與 執行上下文所屬的類 是否相等

在我們判斷中:
lisi>>Human lisi->setMoney()函數,也在Human類中,
在同一個類內部,可以調用.

這也說明了,確實是以類爲單位,以類內類外爲界限做的判斷

case ZEND_ACC_PRIVATE:
if ((ce==EG(scope) || property_info->ce == EG(scope)) && EG(scope))
{
return 1;
} else {

第四
從其他語言來看一看這個問題.java c#,也存在此問題

第五: 從面向對象的角度來考試
我們的寫法,也有問題就不應該把一個對象,直接傳給一個方法來使用
而應該 zhangsan borrow錢,應該對應 lisi sent錢
即 應該儘量的來調用對象的方法,而不應該直接把對象當成參數給傳過去.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章