2009-02-10 45 views
12

Làm thế nào tôi có thể làm điều này trong PHPLàm thế nào để thực hiện một lớp lồng nhau PHP hoặc các phương thức lồng nhau?

$myDBClass->users()->limit(5);//output you limited users to 5 
$myDBClass->comments()->limit(3);//output you limited comments to 3 

những gì tôi có nghĩa là phương pháp lồng nhau hoặc lớp lồng nhau (Tôi không biết!) vì vậy khi tôi gọi phương thức hạn như một đứa trẻ của người sử dụng nó sẽ biết rằng Tôi đang gọi nó từ phương thức "người dùng" - hay lớp - và khi tôi gọi phương thức giới hạn -hoặc lớp - từ nhận xét Nó cũng biết điều đó.

cấu trúc có thể có của lớp PHP để làm việc này là gì?


lý do cho câu hỏi này bởi vì tôi đang làm việc trên lớp của riêng mình cho cơ sở dữ liệu để tôi có thể dễ dàng sử dụng một cái gì đó như thế này

 $DB->comments()->id(" > 3")->limit(10); 

để tạo mã sql "select * from comments nơi id> 3 giới hạn 10 " Cảm ơn

+4

Dude this is ** chaining **, không làm tổ. – Pacerier

Trả lời

17

Có phương pháp trả về đối tượng bằng các phương pháp được mô tả và bạn sẽ có được những gì bạn đang làm.

Vì vậy, miễn là $DB là một đối tượng có một phương thức comments(), thì phần đó là hợp lệ. Nếu điều đó comments() trả về một đối tượng có một phương thức id(), thì phần đó cũng hợp lệ. Sau đó, id() cần trả lại đối tượng có phương thức limit().

Trong trường hợp cụ thể của bạn, bạn có thể muốn làm một cái gì đó như thế này:

class DB { 
    public function comments() { 
    // do preparations that make the object select the "comments"-table... 
    return $this; 
    } 

    public function id($string) { 
    // handle this too... 
    return $this; 
    } 

    public function limit($int) { 
    // also this 
    return $this; 
    } 

    public function execute() { 
    $success = try_to_execute_accumulated_db_commands(); 
    return $success; 
    } 
} 

$DB = new DB(); 

Trong ví dụ của tôi, mọi phương pháp (cũng không được mô tả ở đây) sẽ trả lại đối tượng riêng của mình, do đó các lệnh có thể được xích lại với nhau . Khi việc xây dựng truy vấn cơ sở dữ liệu được thực hiện, bạn thực sự đánh giá truy vấn bằng cách gọi execute() rằng (trong trường hợp của tôi) sẽ trả về một boolean đại diện cho sự thành công của việc thực thi cơ sở dữ liệu.

Biệt hiệu người dùng gợi ý rằng điều này được gọi là fluent interface. Tôi phải thừa nhận rằng đây là một thuật ngữ mới đối với tôi, nhưng điều đó có thể nói với nhiều kiến ​​thức của tôi hơn là sử dụng thuật ngữ đó. ("Tôi chỉ viết mã, bạn biết ...")

Lưu ý:$this là một 'ma thuật' biến trỏ đến đối tượng đang hoạt động. Như tên cho thấy, nó chỉ trả về chính nó như là giá trị trả về cho phương thức.

+0

Ví dụ tuyệt vời. Tôi sắp sửa viết một cái gì đó giống hệt nhau. Có thể muốn đề cập đến điều này được gọi là giao diện thông thạo: http://en.wikipedia.org/wiki/Fluent_interface – nickohrn

+0

Điều này được sử dụng trong ExtPHP http://nexus.zteo.com/2008/03/04/extphp-an- extjs-converterwrapper-for-php-developers / – Seiti

9

Quy ước chuẩn cho việc này là trả về phiên bản $ this ở cuối mỗi cuộc gọi phương thức. Vì vậy, khi quay trở lại người gọi, chúng tôi chỉ đề cập đến một cuộc gọi phương thức khác.

class Foo 
{ 
    public function do_something() 
    { 
    return $this; 
    } 

public function do_something_else() 
{ 
    return $this; 
    } 
} 

$foo->do_something()->do_something_else(); 
0

Một đơn giản để thực hiện phương pháp để giúp bạn bắt đầu có thể đi như:

class db 
{ 
    public function __call($function, $arguments) 
    { 
    switch($function) { 
     // implement table handling here 
     case 'user': 
     //do something 
     return $something; 
     break; 
    } 
    } 
} 

Tùy thuộc vào hay không, bạn muốn đi phức tạp, nhưng rắn hoặc đơn giản, nhưng ít linh hoạt bạn có thể thực hiện hai chiến lược khác nhau. chiến lược đơn giản có thể đi như vậy:

class db 
{ 

    protected $operatingTable; 

    public function limit($limitNumber) 
    { 
    return $this->executeQuery("SELECT * FROM ".$this->operatingTable." LIMIT ".$limitNumber); // where executeQuery is a function that runs a query 
    } 

    public function __call($function, $arguments) 
    { 
    switch($function) { 
     // implement table handling here 
     case 'user': 
     $this->operatingTable='user'; // alternately, but less secure: $this->operatingTable=$function; 
     return $this; 
     break; 
    } 
    } 
} 

Cách khác, nhưng mạnh mẽ hơn:

class db 
{ 
    protected $operatingTable; 

    public function limit($limitNumber) 
    { 
    return $this->executeQuery("SELECT * FROM ".$this->operatingTable." LIMIT ".$limitNumber); // where executeQuery is a function that runs a query 
    } 

    public function __call($function, $arguments) 
    { 
    switch($function) { 
     // implement table handling here 
     case 'user': 
     $user = new user($this); // pass in the database to the object, so the table object can have a reference to the db 
     return $user; 
     break; 
    } 
    } 
} 

class baseTableClass 
{ 
    protected $db; // an instance of class db 

    function limit($limitNumber) 
    { 
    $db->execute($aStatementDerivedFromThisClassesInformation); // execute a sql command, based on information about the table in the class 
    } 

} 

class user extends baseTableClass 
{ 
    public function __construct($db) { 
    $this->db = $db; 
    } 
} 

Bạn nhận được các ý tưởng. Hoặc là quá tải đối tượng db hoặc tạo đối tượng db cơ sở và đối tượng bảng, đặt nhiều thông minh vào đối tượng bảng, đảm bảo rằng khi được tạo, đối tượng bảng lưu trữ tham chiếu đến đối tượng db

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