2008-10-10 37 views
9

Một thành ngữ thường được sử dụng trong các ngôn ngữ OO như Python và Ruby đang instantiating một đối tượng và chaining phương pháp mà trả về một tham chiếu đến đối tượng riêng của mình, chẳng hạn như:"Inline" Class Instantiation trong PHP? (Đối với Dễ Phương pháp Chaining)

s = User.new.login.get_db_data.get_session_data 

Trong PHP, nó có thể tái tạo hành vi này như sau:

$u = new User(); 
$s = $u->login()->get_db_data()->get_session_data(); 

Cố gắng kết quả như sau trong syntax error, unexpected T_OBJECT_OPERATOR:

$s = new User()->login()->get_db_data()->get_session_data(); 

Có vẻ như điều này có thể được thực hiện bằng cách sử dụng các phương thức tĩnh, có lẽ là những gì tôi sẽ làm, nhưng tôi muốn kiểm tra lazyweb: Có thực sự một cách đơn giản, sạch sẽ để khởi tạo các lớp PHP "inline" (như được hiển thị trong đoạn mã trên) cho mục đích này?

Nếu tôi quyết định sử dụng các phương pháp tĩnh, là nó quá sorcerous để có một phương thức tĩnh của lớp trả về một instantiation của lớp chính nó? (Hiệu quả viết nhà xây dựng của riêng tôi-đó-không-một-constructor?) Nó cảm thấy loại bẩn, nhưng nếu không có quá nhiều tác dụng phụ đáng sợ, tôi chỉ có thể làm điều đó.

Tôi đoán tôi cũng có thể đặt trước một UserFactory với phương thức get_user(), nhưng tôi tò mò về các giải pháp cho những gì tôi đã hỏi ở trên.

+4

Vì PHP 5.4 các công trình sau: '(new User()) -> login() -> ...', xem [PHP changelog] (http://php.net/ChangeLog-5.php) cho 5.4 .0 * "Đã thêm quyền truy cập thành viên của lớp vào instantiation (ví dụ: (mới foo) -> bar()) hỗ trợ "* – hakre

Trả lời

12

Tất cả những giải pháp đề xuất phức tạp mã của bạn theo thứ tự để bẻ cong PHP để thực hiện một số nguyên tắc cú pháp. Muốn PHP là một cái gì đó nó không (như tốt) là con đường để điên rồ.

Tôi chỉ sẽ sử dụng:

$u = new User(); 
$s = $u->login()->get_db_data()->get_session_data(); 

Rõ ràng, tương đối ngắn gọn và bao gồm không ma thuật đen có thể giới thiệu lỗi.

Và tất nhiên, bạn luôn có thể chuyển sang Ruby hoặc Python. Nó sẽ thay đổi cuộc sống của bạn.

  • Và vâng, tôi khắc nghiệt với PHP. Tôi dùng nó mỗi ngày. Đã sử dụng nó vài năm. Thực tế là nó có accreted, thay vì được thiết kế và nó cho thấy.
+0

Tôi thích Ruby, sau đó là Python, sau đó PHP, nhưng tôi thường xuyên lập trình trong cả ba. –

+1

Vâng ... bài học BIGGEST mà tôi đã học được với PHP là bạn phải cắt bằng hạt. Làm việc với PHP và nó là tuyệt vời, nhưng bắt đầu muốn nó là khác nhau và bạn sẽ đào lỗ của riêng bạn. –

+0

Ít nhất giờ tôi đã xác nhận rằng bạn không thể làm điều này. Bạn có thể chỉ cho tôi đến nơi trong tài liệu tham khảo ngôn ngữ PHP nói rằng tại sao bạn không thể làm điều này? Argh. –

8
<?php 

    class User 
    { 
     function __construct() 
     { 
     } 

     function Login() 
     { 
      return $this; 
     } 

     function GetDbData() 
     { 
      return $this; 
     } 

     function GetSession() 
     { 
      return array("hello" => "world"); 
     } 
    } 

    function Create($name) 
    { 
     return new $name(); 
    } 

    $s = Create("User")->Login()->GetDbData()->GetSession(); 

    var_dump($s); 
?> 

Đây là một giải pháp khả thi :) Tất nhiên, bạn nên chọn một tên tốt hơn cho các chức năng ...

Hoặc nếu bạn không nhớ một chút chi phí:

<?php 

    class User 
    { 
     function __construct($test) 
     { 
      echo $test; 
     } 
... 
    } 

    function CreateArgs($name) 
    { 
     $ref = new ReflectionClass($name); 
     return $ref->newInstanceArgs(array_slice(func_get_args(), 1)); 
    } 

    $s = CreateArgs("User", "hi")->Login()->GetDbData()->GetSession(); 

    var_dump($s); 
?> 
+0

Cảm ơn bạn! Tôi chấp nhận câu trả lời của người khác, nhưng nếu tôi có thể chấp nhận hai câu trả lời, tôi cũng chấp nhận lời của bạn. –

5

Cách duy nhất bạn có thể nhận được một cái gì đó tương tự là với một nhà máy hoặc phương pháp tĩnh singleton. Ví dụ:

class User 
{ 
    //... 
    /** 
    * 
    * @return User 
    */ 
    public static function instance() 
    { 
     $args = func_get_args(); 
     $class = new ReflectionClass(__CLASS__); 
     return $class->newInstanceArgs($args); 
    } 
    //... 
} 

Đó sử dụng API PHP5 phản ánh để tạo một đối tượng mới (sử dụng bất kỳ args gửi đến :: instance()) và trả về nó cho phép bạn thực hiện chain:

$s = User::instance()->login()->get_db_data()->get_session_data(); 

Bằng cách mã đó đủ linh hoạt, điều duy nhất bạn sẽ phải thay đổi khi sao chép phương thức tĩnh đó là @return của PHPDoc.


Nếu bạn muốn sớm tối ưu hóa mã của bạn như bạn của chúng tôi Nelson bạn có thể thay thế nội dung của người dùng :: instance() với:

return new self(); 
+1

Sử dụng sự phản chiếu không đáng giá khi thực hiện phương pháp tiếp cận tĩnh. Bạn không nên thêm phí trên không yêu cầu;) – nlaq

+0

Hoặc chúng ta có thể tuân thủ các tiêu chuẩn để gửi các đối số bạn không cần phải cập nhật liên tục phương thức instance() khi bạn thay đổi __construct() – dcousineau

+0

Nó đơn giản là ngu xuẩn để làm điều gì đó biết rằng cùng một thứ có thể được thực hiện nhanh hơn "tối ưu hóa sớm" khác với "sử dụng thông thường. "Và giải pháp của tôi cũng không yêu cầu sao chép và dán mã. Tuy nhiên, tôi đặt cược cả hai đều đồng ý rằng một mẫu nhà máy nên được sử dụng anyway :) – nlaq

5

Không có lý do gì để liên kết với nhau một hack (để giải quyết vấn đề cú pháp) và mã tạo đối tượng.

Kể từ khi mới thể hiện không thể được sử dụng như các thành viên bên trái của nhà khai thác đối tượng của bạn, nhưng một biểu hiện chức năng cuộc gọi có thể, bạn chỉ cần quấn đối tượng của bạn trong một cuộc gọi đến một hàm trả về lập luận riêng của mình:

function hack($obj) { return $obj; } 

$mail = hack(new Zend_Mail()) 
    -> setBodyText('This is the text of the mail.') 
    -> setFrom('[email protected]', 'Some Sender') 
    -> addTo('[email protected]', 'Some Recipient') 
    -> setSubject('TestSubject'); 
+0

Phương pháp này hoạt động khá tốt ... – Nick

3

Một phím tắt đơn giản để

$Obj = new ClassName(); 
$result = $Obj->memberFunction(); 

$result = (new ClassName())->memberFunction(); 
1
<?php 
//PHP 5.4+ class member access on instantiation support. 
$s = (new User())->login()->get_db_data()->get_session_data(); 
Các vấn đề liên quan