2011-04-25 39 views
7

On Zend Quick Start Guide đây http://framework.zend.com/manual/en/learning.quickstart.create-model.html chúng ta có thể thấy:Phương pháp ma thuật Php __get và __set - tại sao chúng ta cần những phương pháp này ở đây?

class Application_Model_Guestbook 
{ 
    protected $_comment; 
    protected $_created; 
    protected $_email; 
    protected $_id; 

    public function __set($name, $value); 
    public function __get($name); 


    public function setComment($text); 
    public function getComment(); 
... 

Tôi thường tạo getter và setter của tôi mà không bất kỳ phương pháp kỳ diệu. Tôi đã nhìn thấy điều này trên hướng dẫn nhanh, và tôi không hiểu tại sao chúng ta có thể cần điều này.

Có ai có thể giúp tôi không?

Thanks a lot

+7

Nó làm giảm gõ. Đó là nó. –

+0

Vì vậy, trên cùng một vị trí tôi thường làm: $ object-> setComment ('hello'), thay vào đó tôi có thể làm: __set ($ _ comment, 'hello'); ? Tôi tin rằng đây không phải là những gì bạn đang đề cập đến, bởi vì tôi không làm giảm đánh máy. Cảm ơn một lần nữa. – MEM

+3

bạn không gọi trực tiếp '__get' và' __set'. Bạn chỉ cần làm điều này: '$ object -> _ comment = 'hello';' –

Trả lời

10

Bạn (thường) không bao giờ gọi trực tiếp __set hoặc __get. $foo->bar sẽ tự động gọi $foo->__get('bar') nếu bar không hiển thị và __get tồn tại.

Trong hướng dẫn bạn đã liên kết đến, trình getter và setter được thiết lập để tự động gọi các hàm get/set riêng thích hợp. Vì vậy, $foo->comment = 'bar' sẽ gián tiếp gọi $foo->setComment('bar'). Điều này là không cần thiết ... nó chỉ là một sự tiện lợi.

Trong các trường hợp khác, __get có thể hữu ích để tạo ra những gì trông giống như biến chỉ đọc.

1

Các __get__set magic method tồn tại cho HAI lý do:

  1. Vì vậy mà bạn không cần phải dành nhiều thời gian tạo ra các phương pháp vani accessor cho tất cả các tài sản của bạn .

  2. Để cho phép bạn thực hiện quá tải thuộc tính.

Nếu bạn có các thuộc tính cần điều trị đặc biệt, thì phương pháp ma thuật không dành cho bạn. Tuy nhiên, nếu các thuộc tính của bạn chỉ chứa dữ liệu và không có phụ thuộc thì không có lý do gì để KHÔNG sử dụng các phương thức ma thuật.

+0

Bạn có thể vui lòng cung cấp một kịch bản so sánh giữa những trường hợp đó khi chúng tôi sử dụng các phương pháp ma thuật và những khi chúng tôi không sử dụng chúng. (một cái đơn giản). cảm ơn một lần nữa. – MEM

+0

Thành thật mà nói, tôi nghĩ rằng sách hướng dẫn PHP thực hiện một công việc khá tốt để giải thích các phương pháp ma thuật với các ví dụ: http://us2.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members –

+0

I không đồng ý. :(Thật không may là tôi thấy rằng tài liệu khá khó hiểu và vì chúng có rất nhiều khái niệm không được giải thích, họ cho rằng chỉ những người lập trình thử nghiệm mới có thể nói về các phương pháp ma thuật. – MEM

1

Hơn nữa trên hướng dẫn, nó giúp bạn sửa đổi các phương pháp __get()__set() để bạn sẽ thấy lý do tại sao chúng ở đó.

Việc xử lý phép thuật như vậy có thể cho phép bạn thực hiện một số công cụ gọn gàng như thậm chí tạo thuộc tính "chỉ đọc" và có thể ngăn bạn làm đầy lớp học của bạn với tải getter/setters lộn xộn.

9

Nếu bạn "làm cho" của riêng bạn "getters và setters, bạn sẽ thực hiện hai chức năng cho mỗi tài sản: getPropname()setPropname. Bằng cách sử dụng phương thức "magic method" setter/getter của PHP, bạn không viết các phương thức riêng cho mỗi thuộc tính. Bạn có thể đặt/nhận các thuộc tính như thể chúng là công khai. Trong các hàm quá tải, bạn thêm logic cụ thể cho từng thuộc tính. Ví dụ:

public function __set($name, $value) { 
switch ($name) { 
    case 'comments': 
    // do stuff to set comments 
    break; 
    case 'parent_user': 
    // do stuff to set parent user 
    break; 
} 
} 
public function __get($name) { 
switch ($name) { 
    case 'comments': 
    // do stuff to get comments 
    break; 
    case 'parent_user': 
    // do stuff to get parent user 
    break; 
} 
} 

Bây giờ tôi có thể truy cập các nhận xét bằng cách sử dụng $obj->comments để đặt hoặc nhận.

Để đạt được chức năng ở trên mà không sử dụng quá tải, tôi sẽ phải viết 4 phương pháp khác nhau thay thế. Điều này thực sự là nhiều hơn về tổ chức mã, cả về mặt tập tin thực tế và trong việc tạo ra một giao diện chuẩn hóa cho các đối tượng trong một dự án.

Cá nhân tôi thích làm như bạn làm và viết các phương pháp riêng biệt cho mỗi thuộc tính mà tôi cần một trình gỡ rối/thiết lập phức tạp. Đối với tôi, nó được tổ chức rõ ràng hơn, và có sự phân biệt rõ ràng giữa các thuộc tính "đơn giản" của một đối tượng và các thuộc tính có độ phức tạp lớn hơn hoặc các mối quan hệ một-nhiều.

+0

Cảm ơn câu trả lời chi tiết của bạn – MEM

0

Bạn sẽ gặp sự cố khi bạn đã sử dụng __set và muốn ghi đè chức năng setter trong lớp con. Bạn sẽ phải sao chép toàn bộ mã trong __set và thay đổi chỉ một phần cụ thể thay vì chỉ đơn giản là ghi đè lên một chức năng cụ thể setter -> Mã thừa

Vấn đề này có thể tránh được bằng cách gọi cụ thể setter trong __set (nhờ cHao cho tip).

Ví dụ:

class Foo1 { 
    protected $normal; 
    protected $special; 

    public function setSpecial($special) { 
     if ($special == isReallySpecial()) { 
     $this->special = $special; 
     } 
    } 

    public function __set($key, $value) { 
     switch ($key) { 
     case 'normal': 
      $this->normal = $value; 
      break; 
     case 'special': 
      $this->setSpecial($value); 
     } 
    } 
} 

class Foo2 extends Foo1 { 
    public function setSpecial($special) { 
     if ($special == isNotReallySpecial()) { 
     $this->special = $special; 
     } 
    } 
} 
+4

Lưu ý rằng trong trường hợp này, các phương thức '__get' và' __set' có thể chỉ gọi getter hoặc setter, tương ứng, vì chúng cũng được chỉ rõ Trong trường hợp này, bạn có '$ obj-> property' và' $ obj -> {get | set} Property (...) 'nhất quán, và vấn đề này không tồn tại. – cHao

Các vấn đề liên quan