1 關注者

屬性

在 PHP 中,類別成員變數也稱為屬性。這些變數是類別定義的一部分,用於表示類別實例的狀態(即,區分一個類別實例與另一個類別實例)。在實務中,您可能經常希望以特殊方式處理屬性的讀取或寫入。例如,您可能希望在將字串指派給 label 屬性時,始終修剪字串。您可以使用以下程式碼來達成此任務

$object->label = trim($label);

上述程式碼的缺點是,您必須在程式碼中所有可能設定 label 屬性的地方呼叫 trim()。如果將來 label 屬性有新的需求,例如第一個字母必須大寫,您又必須修改每一段指派值給 label 的程式碼。程式碼的重複會導致錯誤,這是您希望盡可能避免的做法。

為了解決這個問題,Yii 引入了一個名為 yii\base\BaseObject 的基底類別,它支援基於 gettersetter 類別方法定義屬性。如果一個類別需要該功能,它應該從 yii\base\BaseObject 或子類別繼承。

資訊:Yii 框架中幾乎每個核心類別都從 yii\base\BaseObject 或子類別繼承。這表示,每當您在核心類別中看到 getter 或 setter 時,您都可以像屬性一樣使用它。

getter 方法是以單字 get 開頭的方法;setter 方法以 set 開頭。getset 字首後面的名稱定義了屬性的名稱。例如,getter getLabel() 和/或 setter setLabel() 定義了一個名為 label 的屬性,如下面的程式碼所示

namespace app\components;

use yii\base\BaseObject;

class Foo extends BaseObject
{
    private $_label;

    public function getLabel()
    {
        return $this->_label;
    }

    public function setLabel($value)
    {
        $this->_label = trim($value);
    }
}

為了清楚起見,getter 和 setter 方法建立了屬性 label,在本例中,它在內部引用了一個名為 _label 的私有屬性。

由 getter 和 setter 定義的屬性可以像類別成員變數一樣使用。主要區別在於,當讀取此類屬性時,將呼叫相應的 getter 方法;當將值指派給屬性時,將呼叫相應的 setter 方法。例如

// equivalent to $label = $object->getLabel();
$label = $object->label;

// equivalent to $object->setLabel('abc');
$object->label = 'abc';

由沒有 setter 的 getter 定義的屬性是唯讀的。嘗試將值指派給此類屬性將導致 InvalidCallException。同樣地,由沒有 getter 的 setter 定義的屬性是唯寫的,嘗試讀取此類屬性也會導致例外。擁有唯寫屬性並不常見。

對於透過 getter 和 setter 定義的屬性,有幾個特殊的規則和限制

  • 此類屬性的名稱不區分大小寫。例如,$object->label$object->Label 是相同的。這是因為 PHP 中的方法名稱不區分大小寫。
  • 如果此類屬性的名稱與類別成員變數相同,則後者優先。例如,如果上面的 Foo 類別有一個成員變數 label,那麼指派 $object->label = 'abc' 將影響成員變數 label;該行不會呼叫 setLabel() setter 方法。
  • 這些屬性不支援可見性。對於定義 getter 或 setter 方法來說,屬性是 public、protected 或 private 沒有區別。
  • 屬性只能由非靜態 getter 和/或 setter 定義。靜態方法將不會以相同的方式處理。
  • 正常呼叫 property_exists() 無法判斷魔術屬性。您應該分別呼叫 canGetProperty()canSetProperty()

回到本指南開頭描述的問題,現在只需在 setter setLabel() 中調用 trim(),而不是在指派 label 值的所有地方都調用 trim()。如果新的需求使得標籤必須在最初大寫,則可以快速修改 setLabel() 方法,而無需觸及任何其他程式碼。這一個變更將普遍影響對 label 的每次指派。

發現錯字或您認為此頁面需要改進?
在 github 上編輯它 !