Khi cố gắng thay đổi, hãy ném một ngoại lệ.Làm cách nào để triển khai biến thành viên chỉ đọc trong PHP?
Trả lời
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
class test {
const CANT_CHANGE_ME = 1;
}
và bạn giới thiệu nó như test::CANT_CHANGE_ME
Bạn sẽ ném ngoại lệ tùy chỉnh như thế nào? – user198729
nó sẽ không ném một ngoại lệ, nhưng một lỗi phân tích cú pháp ... –
@ user198729 Tại sao bạn muốn * để ném một ngoại lệ tùy chỉnh? – meagar
Sử dụng một hằng số. Từ khoá const
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;
}
}
}
Câu trả lời hay! BTW, '__call' dùng để làm gì? – user198729
'__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 –
@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