Tôi có một thực thể rất đơn giản (WpmMenu) chứa các mục menu được kết nối với nhau trong mối quan hệ tự tham khảo (danh sách phụ đề được gọi)? như vậy trong thực thể của tôi, tôi có:Học thuyết - tự tham chiếu thực thể - vô hiệu hóa việc tìm nạp trẻ em
protected $id
protected $parent_id
protected $level
protected $name
với tất cả các getters/setters các mối quan hệ là:
/**
* @ORM\OneToMany(targetEntity="WpmMenu", mappedBy="parent")
*/
protected $children;
/**
* @ORM\ManyToOne(targetEntity="WpmMenu", inversedBy="children", fetch="LAZY")
* @ORM\JoinColumn(name="parent_id", referencedColumnName="id", onUpdate="CASCADE", onDelete="CASCADE")
*/
protected $parent;
public function __construct() {
$this->children = new ArrayCollection();
}
Và tất cả mọi thứ hoạt động tốt. Khi tôi vẽ cây menu, tôi lấy phần tử gốc từ kho lưu trữ, lấy con của nó, và sau đó lặp qua mỗi đứa trẻ, nhận con của nó và làm điều này đệ quy cho đến khi tôi đã trả về mỗi mục.
Điều gì xảy ra (và cho những gì tôi đang tìm kiếm giải pháp) là: Hiện tại tôi có 5 cấp = 1 mục và mỗi mục này có 3 cấp = 2 mục đính kèm (và trong tương lai tôi sẽ sử dụng cấp = 3 mục). Để có được tất cả các yếu tố của thuyết cây đơn của tôi thực hiện:
- 1 truy vấn cho các phần tử gốc +
- 1 truy vấn để có được 5 trẻ em (level = 1) của phần tử gốc +
- 5 truy vấn để có 3 trẻ em (level = 2) của mỗi cấp 1 mặt hàng +
- 15 câu truy vấn (5x3) để có được những đứa trẻ (level = 3) của mỗi cấp 2 mục
TỔNG: 22 truy vấn
Vì vậy, tôi cần phải tìm một giải pháp cho điều này và lý tưởng tôi chỉ muốn có 1 truy vấn.
Vì vậy, đây là những gì tôi đang cố gắng để làm: Trong kho thực thể của tôi (WpmMenuRepository) Tôi sử dụng queryBuilder và có được một mảng phẳng của tất cả các mục trong menu lệnh theo trình độ. Lấy phần tử gốc (WpmMenu) và thêm "thủ công" con của nó từ mảng các phần tử đã tải. Sau đó làm điều này đệ quy về trẻ em. Làm theo cách này tôi có thể có cùng một cây nhưng với một truy vấn duy nhất.
Vì vậy, đây là những gì tôi có:
WpmMenuRepository:
public function setupTree() {
$qb = $this->createQueryBuilder("res");
/** @var Array */
$res = $qb->select("res")->orderBy('res.level', 'DESC')->addOrderBy('res.name','DESC')->getQuery()->getResult();
/** @var WpmMenu */
$treeRoot = array_pop($res);
$treeRoot->setupTreeFromFlatCollection($res);
return($treeRoot);
}
và trong thực thể WpmMenu của tôi, tôi có:
function setupTreeFromFlatCollection(Array $flattenedDoctrineCollection){
//ADDING IMMEDIATE CHILDREN
for ($i=count($flattenedDoctrineCollection)-1 ; $i>=0; $i--) {
/** @var WpmMenu */
$docRec = $flattenedDoctrineCollection[$i];
if (($docRec->getLevel()-1) == $this->getLevel()) {
if ($docRec->getParentId() == $this->getId()) {
$docRec->setParent($this);
$this->addChild($docRec);
array_splice($flattenedDoctrineCollection, $i, 1);
}
}
}
//CALLING CHILDREN RECURSIVELY TO ADD REST
foreach ($this->children as &$child) {
if ($child->getLevel() > 0) {
if (count($flattenedDoctrineCollection) > 0) {
$flattenedDoctrineCollection = $child->setupTreeFromFlatCollection($flattenedDoctrineCollection);
} else {
break;
}
}
}
return($flattenedDoctrineCollection);
}
Và đây là những gì sẽ xảy ra:
Mọi thứ hoạt động tốt, NHƯNG, tôi kết thúc với từng mục trình bày hai lần. ;) Thay vì 22 truy vấn bây giờ tôi có 23. Vì vậy, tôi thực sự xấu đi trường hợp. Điều thực sự xảy ra, tôi nghĩ, là ngay cả khi tôi thêm trẻ em thêm "thủ công", thực thể WpmMenu KHÔNG được xem là đồng bộ với cơ sở dữ liệu và ngay sau khi tôi lặp lại vòng lặp cho trẻ em của nó được kích hoạt trong tải ORM và thêm các con tương tự đã được thêm "thủ công".
Q: Có cách nào để chặn/tắt hành vi này và nói với các thực thể này rằng chúng ĐƯỢC đồng bộ hóa với db để không cần truy vấn thêm?
Xem điều này có giúp ích: http://docs.doctrine-project.org/en/latest/reference/partial-objects.html – gremo
Không. Tôi không có một số đối tượng và có vẻ như là một ý tưởng tồi để đi theo cách đó. – jakabadambalazs