2012-09-03 11 views
8

Tôi đang sử dụng Propel 1.6 và tôi không chắc chắn làm thế nào để có được một đối tượng (cho giá trị thuộc tính "id" của nó) từ một bộ sưu tập đối tượng propel. Tôi không thể tìm thấy câu trả lời thẳng trong tài liệu của Propel (PropelCollection methods dường như không áp dụng được?). Ví dụ: phép nói rằng tôi có một "Người" bảng với lược đồ sau:Cách lấy đối tượng bằng "id" từ bộ sưu tập đối tượng propel?

<table name="person"> 
    <column name="id" type="INTEGER" primaryKey="true" autoIncrement="true" required="true"/> 
    <column name="name" type="VARCHAR" size="100" required="true"/> 
</table> 

tôi làm các truy vấn sau đây để có được một bộ sưu tập của "Người" đối tượng:

$persons = PersonQuery::create()->find(); 

Sau đó, tôi muốn tìm đối tượng "Người" với "id" đã cho (ví dụ: "Người" có "id = 3"), mà không cần tạo truy vấn mới vào cơ sở dữ liệu. Tôi làm nó như thế nào?

$persons->get(...?)? 

Nói cách khác, tôi không muốn làm:

$personX = PersonQuery::create()->findOneById(3); 

Bối cảnh:

Tôi muốn để ngăn chặn thực hiện một truy vấn cơ sở dữ liệu để cải thiện hiệu suất. Câu lệnh sẽ được chèn vào bên trong một tuyên bố foreach mà nếu không sẽ dẫn đến nhiều kết nối cơ sở dữ liệu, như sau:

foreach ($books as $book) { 
    $book['author_name'] = PersonQuery::create()->findOneById($book['author_id'])->getName(); 
} 

Trả lời

4

Vâng, điều đó sẽ không hiệu quả lắm, nhưng bạn có thể đi qua bộ sưu tập để tìm nó .

$persons = PersonQuery::create()->find(); 
foreach ($persons as $person) 
{ 
    if (3 == $person->getId()) 
    { 
    break; 
    } 
} 

// now you have your person with id = 3 
var_dump($person->getId()); 
+1

Bạn có thể làm điều đó trong một cách thanh lịch hơn với 'array_filter()' :-) – Florent

+0

@ j0k: Tôi đã cố gắng để tránh một vòng lặp foreach, nhưng tôi đoán, như bạn đề nghị, tôi không thể tránh nó. Tôi nghĩ rằng đi với vòng lặp sẽ vẫn hiệu quả hơn việc tạo nhiều kết nối cơ sở dữ liệu. Cảm ơn câu trả lời của bạn! – RayOnAir

+1

@Florent: Tôi không chắc chắn cách triển khai hàm [array_filter] (http://php.net/manual/en/function.array-filter.php) trong trường hợp này, nhưng tôi sẽ điều tra ... cảm ơn! – RayOnAir

3

Kể từ Propel không nhớ cache đúng truy vấn kết quả, bạn cần phải lặp bộ sưu tập (như @ j0k nói). Thay vì sử dụng vòng kết nối foreach, bạn có thể gọi số array_filter qua việc đóng cửa (với PHP 5.3).

// Request the persons 
$persons = PersonQuery::create()->find(); 

// Filter the persons whose ID equals 3 
$filteredPersons = array_filter($persons, function ($person) { 
    return 3 === $person->getId(); 
}); 

// Get the first result 
$person = empty($filteredPersons) ? null : $filteredPersons[0]; 

Nếu bạn chắc chắn rằng người đó sẽ được tìm thấy, bạn cũng có thể viết (với PHP 5.4) các dòng sau:

// Filter the person whose ID equals 3 
$person = array_filter($persons, function ($person) { 
    return 3 === $person->getId(); 
})[0]; 
+0

cảm ơn bạn đã chia sẻ một giải pháp thay thế bằng cách sử dụng array_filter! Liệu giải pháp này có tốt hơn từ một điểm đứng hiệu suất, so với việc sử dụng vòng lặp foreach? Nếu vậy, bạn có thể chia sẻ trực giác đằng sau? – RayOnAir

+1

Với PHP 5.4, 'foreach' nhanh gấp 3 lần' array_filter() '. Hơn nữa bằng cách sử dụng 'foreach' bạn có thể' phá vỡ' khi mục nhập của bạn được tìm thấy. Nhưng theo ý kiến ​​của tôi 'array_filter()' là nhiều _aesthetic_. – Florent

+0

Tôi sẽ ghi nhớ điều đó. cảm ơn! – RayOnAir

2

nếu bạn thiết lập Propel :: isInstancePoolingEnabled() là đúng (theo mặc định), bạn có thể

// Request the persons 
$persons = PersonQuery::create()->find(); 
// get person from pool 
$person = PersonPeer::getInstanceFromPool(3); 

xin lỗi về tiếng anh của tôi.

1

Cách khác với Propel> = 1.5 để trả lời user2663223 của sẽ là:

$persons = PersonQuery::create()->find() 

$person = PersonQuery::create()->findPk(3); 

này có lợi thế của hồ bơi dụ. Bên trong nó sử dụng: getInstanceFromPool, nếu truy vấn sql đã được thực hiện trước đó.

Mọi chi tiết, tham khảo ý kiến:

http://propelorm.org/documentation/03-basic-crud.html#propel-instance-pool

7

Một lựa chọn khác, đặc biệt là nếu bạn cần phải tìm kiếm nhiều lần là để có được mảng của các đối tượng bằng id với $ collection-> getArrayCopy ('Id').

$persons = PersonQuery::create()->find(); 
$personsById = $persons->getArrayCopy('Id'); 

Sau đó, bạn có thể làm

$person = $personsById[3]; 

hoặc

if (isset($personsById[3])) { 
    $person = $personsById[3]; 
    ... 
}