मेरे पास एक बहुत ही सरल इकाई (WpmMenu) है जो एक स्व-संदर्भ संबंध में एक दूसरे से जुड़े मेनू आइटम रखती है (जिसे विज्ञापन कहा जाता है)? तो मेरी इकाई में मेरे पास है:सिद्धांत - आत्म-संदर्भ इकाई - बच्चों की fetching अक्षम करें
protected $id
protected $parent_id
protected $level
protected $name
सभी getters/setters रिश्ते हैं साथ
:
/**
* @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();
}
और सब कुछ ठीक काम करता है। जब मैं मेनू पेड़ प्रस्तुत करता हूं, मुझे भंडार से मूल तत्व मिलता है, अपने बच्चों को प्राप्त होता है, और उसके बाद प्रत्येक बच्चे के माध्यम से लूप मिलता है, अपने बच्चों को प्राप्त करता है और जब तक मैं प्रत्येक आइटम को प्रस्तुत नहीं करता तब तक यह पुनरावृत्तिपूर्वक करता हूं।
क्या होता है (और जो मैं समाधान की तलाश में हूं) यह है: इस समय मेरे पास 5 स्तर = 1 आइटम हैं और इनमें से प्रत्येक आइटम में 3 स्तर = 2 आइटम संलग्न हैं (और भविष्य में मैं स्तर = 3 वस्तुओं का भी उपयोग कर)। मेरे मेनू पेड़ सिद्धांत के सभी तत्वों को प्राप्त करने के लिए निष्पादित करता है: 5 बच्चों को पाने के लिए मूल तत्व के लिए
- 1 क्वेरी +
- 1 क्वेरी (स्तर = 1) मूल तत्व के +
- 5 करने के लिए क्वेरी (स्तर = 2) 3 बच्चों पाने के बच्चों को पाने के लिए स्तर 1 आइटम +
- 15 प्रश्नों (5x3) में से प्रत्येक के प्रत्येक स्तर के (स्तर = 3) 2 आइटम
कुल: 22 प्रश्नों
तो, मुझे इसके लिए एक समाधान खोजने की ज़रूरत है और आदर्श रूप में मैं केवल 1 क्वेरी चाहता हूं। मेरी संस्थाओं भंडार (WpmMenuRepository) मैं queryBuilder का उपयोग में और सभी मेनू आइटम स्तर द्वारा आदेश दिया की एक फ्लैट सरणी मिल:
तो यह कि मैं क्या करने की कोशिश कर रहा हूँ। मूल तत्व (WpmMenu) प्राप्त करें और तत्वों के लोड किए गए सरणी से अपने बच्चों को "मैन्युअल रूप से" जोड़ें। फिर यह बच्चों पर बार-बार करें। इस तरह से मैं एक ही पेड़ हो सकता था लेकिन एक ही प्रश्न के साथ।
तो यह है कि मैं क्या है:
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);
}
और मेरे WpmMenu इकाई में मेरे पास है:
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);
}
और यह क्या होता है:
सब कुछ ठीक काम करता है, लेकिन मैं दो बार मौजूद प्रत्येक मेनू आइटम के साथ समाप्त होता हूं। ;) 22 प्रश्नों के बजाय अब मेरे पास 23 है। इसलिए मैंने वास्तव में इस मामले को और खराब कर दिया।
वास्तव में क्या होता है, मुझे लगता है कि, अगर मैं बच्चों को "मैन्युअल रूप से" जोड़ता हूं, तो WpmMenu इकाई को डेटाबेस के साथ सिंक में नहीं माना जाता है और जैसे ही मैं अपने बच्चों पर फ़ोरैच लूप करता हूं ओआरएम लोडिंग में ट्रिगर किया गया है और वही बच्चों को जोड़ रहा है जो पहले से ही "मैन्युअल" जोड़े गए थे।
क्यू: क्या इस व्यवहार को अवरुद्ध/अक्षम करने का कोई तरीका है और इन इकाइयों को बताएं कि वे डीबी के साथ सिंक में हैं इसलिए कोई अतिरिक्त पूछताछ की आवश्यकता नहीं है?
देखें कि यह मदद करता है: http://docs.doctrine-project.org/en/latest/reference/partial-objects.html – gremo
नहीं। मेरे पास आंशिक वस्तुएं नहीं हैं और ऐसा लगता है कि इस तरह से जाना बहुत बुरा विचार है। – jakabadambalazs