2010-02-26 23 views

Trả lời

19

Tôi cho rằng một giải pháp, đối với thuộc tính của lớp, sẽ được:

  • không xác định một thuộc tính với tên mà bạn quan tâm
  • sử dụng sự kỳ diệu __get phương pháp để truy cập vào tài sản đó, bằng cách sử dụng Tên "giả"
  • xác định phương thức __set để nó ném ngoại lệ khi cố gắng đặt thuộc tính đó.
  • Xem Overloading, để biết thêm thông tin về các phương pháp ma thuật.

Đối với các biến, tôi không nghĩ rằng có thể có biến chỉ đọc mà PHP sẽ ném một ngoại lệ khi bạn đang cố ghi vào nó.


Ví dụ, hãy xem xét lớp ít này:

class MyClass { 
    protected $_data = array(
     'myVar' => 'test' 
    ); 

    public function __get($name) { 
     if (isset($this->_data[$name])) { 
      return $this->_data[$name]; 
     } else { 
      // non-existant property 
      // => up to you to decide what to do 
     } 
    } 

    public function __set($name, $value) { 
     if ($name === 'myVar') { 
      throw new Exception("not allowed : $name"); 
     } else { 
      // => up to you to decide what to do 
     } 
    } 
} 

Instanciating lớp và cố gắng đọc tài sản:

$a = new MyClass(); 
echo $a->myVar . '<br />'; 

sẽ giúp bạn có được sản lượng dự kiến:

test 

Trong khi cố gắng viết cho phù hợp ty:

$a->myVar = 10; 

sẽ giúp bạn có một ngoại lệ:

Exception: not allowed : myVar in /.../temp.php on line 19 
+0

Câu trả lời hay! BTW, '__call' dùng để làm gì? – user198729

+0

'__call' được gọi khi bạn đang cố gắng gọi một phương thức không thoát trong lớp (như' __get' được gọi khi bạn đang cố đọc một thuộc tính không tồn tại trong lớp) - xem http://fr2.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.methods –

+0

@Pascal MARTIN, cảm ơn! Tôi cũng biết rằng bạn là một người dùng có kinh nghiệm về symfony/doctrine , bạn có thể xem bài đăng này: http: //stackoverflow.com/questions/2339800/how-can-i-fetch-the-entire-tree-in-a-single-query-with-doctrine không? – user198729

13
class test { 
    const CANT_CHANGE_ME = 1; 
} 

và bạn giới thiệu nó như test::CANT_CHANGE_ME

+0

Bạn sẽ ném ngoại lệ tùy chỉnh như thế nào? – user198729

+0

nó sẽ không ném một ngoại lệ, nhưng một lỗi phân tích cú pháp ... –

+3

@ user198729 Tại sao bạn muốn * để ném một ngoại lệ tùy chỉnh? – meagar

3

Sử dụng một hằng số. Từ khoá const

0

Tôi biết đây là một câu hỏi cũ, nhưng câu trả lời của PASCAL thực sự giúp tôi và tôi muốn thêm vào đó một chút.

__get() không chỉ kích hoạt trên các thuộc tính không tồn tại, mà còn không thể truy cập được, ví dụ: những người được bảo vệ. Điều này giúp dễ dàng tạo các thuộc tính chỉ đọc!

class MyClass { 
    protected $this; 
    protected $that; 
    protected $theOther; 

    public function __get($name) { 
     if (isset($this->$name)) { 
      return $this->$name; 
     } else { 
      throw new Exception("Call to nonexistent '$name' property of MyClass class"); 
      return false; 
     } 
    } 

    public function __set($name) { 
     if (isset($this->$name)) { 
      throw new Exception("Tried to set nonexistent '$name' property of MyClass class"); 
      return false; 
     } else { 
      throw new Exception("Tried to set read-only '$name' property of MyClass class"); 
      return false; 
     } 
    } 
}