2010-09-21 35 views
9

Tôi đã thấy một cái gì đó như thế này trong một ORM:Đối tượng hoạt động như một mảng? (PHP)

$b = new Book(); 
    $b->limit(5)->get(); 

    echo 'ID: ' . $b->id . '<br />'; 
    echo 'Name: ' . $b->title . '<br />'; 
    echo 'Description: ' . $b->description . '<br />'; 
    echo 'Year: ' . $b->year . '<br />'; 

    foreach ($b as $book) 
    { 
     echo 'ID: ' . $book->id . '<br />'; 
     echo 'Name: ' . $book->title . '<br />'; 
     echo 'Description: ' . $book->description . '<br />'; 
     echo 'Year: ' . $book->year . '<br />'; 
     echo '<br />'; 
    } 

Làm thế nào là nó có thể là một đối tượng đóng vai trò như cả hai mảng và đối tượng? Làm thế nào tôi có thể thực hiện điều đó? Tôi đã hy vọng sẽ thấy một phương pháp __magic mới hoặc một cái gì đó trong lớp cha của Book, nhưng tôi không thể tìm thấy bất cứ điều gì, vì vậy có thể có một cái gì đó thực sự cơ bản về các đối tượng php mà tôi không biết.

Mọi suy nghĩ? Cảm ơn trước

Trả lời

12

Đối tượng mà thực hiện giao diện Traversable (thông qua Iterator hoặc IteratorAggregate) hỗ trợ foreach xây dựng, nếu đó là những gì bạn có nghĩa là bằng cách "đóng vai trò như một mảng." Ví dụ:

class theClass implements Iterator { 
    // implement iterator here 
} 

// now you can do 
$obj = new theClass; 

foreach ($obj as $value) { 
    // do something 
} 
+1

Gotta yêu này! :) – balupton

+0

Vâng đó là những gì tôi xin cảm ơn! –

+6

Trên thực tế mọi đối tượng có thể được truy cập với foreach, nhưng nó sẽ truy cập tất cả các thuộc tính công cộng.Bạn cần triển khai 'Iterator' nếu bạn muốn thay đổi hành vi này. Một giao diện khác mà bạn có thể quan tâm là 'ArrayAccess' – Mchl

5

Bạn không phải làm bất cứ điều gì đặc biệt để sử dụng foreach với các đối tượng.

Từ PHP manual on Object Iteration:

PHP 5 cung cấp một cách cho các đối tượng được xác định do đó nó có thể lặp thông qua một danh sách các mục, với, ví dụ một tuyên bố foreach. Theo mặc định, tất cả các thuộc tính hiển thị sẽ được sử dụng cho lặp lại.

Ví dụ:

class Foo 
{ 
    public $foo = 1; 
    protected $bar = 2; 
    private $baz = 3; 
} 

foreach(new Foo as $prop) echo $prop; // outputs 1 only 

lớp học của bạn không nhất thiết phải thực hiện Traversable như đề xuất ở nơi khác và trong thực tế, lớp trên không:

var_dump (new Foo instanceof Traversable); // FALSE 

Bạn thể thực hiện một của số Iterator hoặc IteratorAggregate nếu bạn cần kiểm soát nhiều hơn về cách lặp lại hoạt động:

class Foo implements IteratorAggregate 
{ 
    public $foo = 1; 
    protected $bar = 2; 
    private $baz = 3; 

    public function getIterator() 
    { 
     return new ArrayIterator((array) $this); 
    } 
} 

foreach(new Foo as $prop) echo $prop; // outputs 123 

IteratorIteratorAggregate mở rộng Traversable, lớp học của bạn sẽ bây giờ cũng là một thể hiện của Traversable, nhưng cũng giống như trình bày ở trên, nó không cần thiết cho iterating đối tượng.

var_dump (new Foo instanceof Traversable); // TRUE 

Bạn cũng có thể sử dụng ArrayObject để làm cho đối tượng hoạt động như lai giữa lớp và đối tượng. Hoặc bạn có thể thực hiện ArrayAccess để cho phép truy cập lớp học bằng dấu ngoặc vuông. Bạn cũng có thể phân lớp lớp là one of the Iterators PHP cung cấp.

Đọc thêm:

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