Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 9005177
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 16, 20262026-06-16T01:04:35+00:00 2026-06-16T01:04:35+00:00

I have a very simple entity(WpmMenu) that holds menu items connected to one another

  • 0

I have a very simple entity(WpmMenu) that holds menu items connected to one another in a self-referencing relationship (adjecent list it’s called)?
so in my entity I have:

protected $id
protected $parent_id
protected $level
protected $name

with all the getters/setters the relationships are:

/**
* @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();
}

And everything works fine. When I render the menu tree, I get the root element from the repository, get its children, and then loop through each child, get its children and do this recursively until I have rendered each item.

What happens (and for what I am seeking a solution)is this:
At the moment I have 5 level=1 items and each of these items have 3 level=2 items attached (and in the future I will be using level=3 items as well). To get all elements of my menu tree Doctrine executes:

  • 1 query for the root element +
  • 1 query to get the 5 children(level=1) of the root element +
  • 5 queries to get the 3 children(level=2) of each of the level 1 items +
  • 15 queries (5×3) to get the children(level=3) of each level 2 items

TOTAL: 22 queries

So, I need to find a solution for this and ideally I would like to have 1 query only.

So this is what I am trying to do:
In my entities repository(WpmMenuRepository) I use queryBuilder and get a flat array of all menu items ordered by level. Get the root element(WpmMenu) and add “manually” its children from the loaded array of elements. Then do this recursively on children. Doing this way I could have the same tree but with a single query.

So this is what I have:

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);
}

and in my WpmMenu entity I have:

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);
}

And this is what happens:

Everything works out fine, BUT I end up with each menu items present twice. 😉 Instead of 22 queries now I have 23. So I actually worsened the case.

What really happens, I think, is that even if I add the children added “manually”, the WpmMenu entity is NOT considered in-sync with the database and as soon as I do the foreach loop on its children the loading is triggered in ORM loading and adding the same children that were added already “manually”.

Q: Is there a way to block/disable this behaviour and tell these entities they they ARE in sync with the db so no additional querying is needed?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-16T01:04:36+00:00Added an answer on June 16, 2026 at 1:04 am

    With immense relief (and a lots of learning about Doctrine Hydration and UnitOfWork) I found the answer to this question. And as with lots of things once you find the answer you realize that you can achieve this with a few lines of code. I am still testing this for unknown side-effects but it seems to be working correctly.
    I had quite a lot of difficulties to identify what the problem was – once I did it was much easier to search for an answer.

    So the problem is this: Since this is a self-referencing entity where the entire tree is loaded as a flat array of elements and then they are “fed manually” to the $children array of each element by the setupTreeFromFlatCollection method – when the getChildren() method is called on any of the entities in the tree (including the root element), Doctrine (NOT knowing about this ‘manual’ approach) sees the element as “NOT INITIALIZED” and so executes an SQL to fetch all its related children from the database.

    So I dissected the ObjectHydrator class (\Doctrine\ORM\Internal\Hydration\ObjectHydrator) and I followed (sort of) the dehydration process and I got to a $reflFieldValue->setInitialized(true); @line:369 which is a method on the \Doctrine\ORM\PersistentCollection class setting the $initialized property on the class true/false. So I tried and IT WORKS!!!

    Doing a ->setInitialized(true) on each of the entities returned by the getResult() method of the queryBuilder (using the HYDRATE_OBJECT === ObjectHydrator) and then calling ->getChildren() on the entities now do NOT trigger any further SQLs!!!

    Integrating it in the code of WpmMenuRepository, it becomes:

    public function setupTree() {
      $qb = $this->createQueryBuilder("res");
      /** @var $res Array */
      $res = $qb->select("res")->orderBy('res.level', 'DESC')->addOrderBy('res.name','DESC')->getQuery()->getResult();
      /** @var $prop ReflectionProperty */
      $prop = $this->getClassMetadata()->reflFields["children"];
      foreach($res as &$entity) {
        $prop->getValue($entity)->setInitialized(true);//getValue will return a \Doctrine\ORM\PersistentCollection
      }
      /** @var $treeRoot WpmMenu */
      $treeRoot = array_pop($res);
      $treeRoot->setupTreeFromFlatCollection($res);
      return($treeRoot);
    }
    

    And that’s all!

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a very simple app that has one CoreData Entity with a circular
I have 2 very simple queries in entity framework that group by a column
I have a very simple query: The variable '_dc' is the Entity Framework Code
I have very simple window where I have 2 buttons - one for cancel,
I have a very simple script that creates a user: <?php include 'mysqlserver.php'; session_start();
I have a very simple JPA entity. It features some simple metadata fields, and
I have created a very simple Entity Framework 4.0 model using VS2010 Professional. Ignore
I have a very simple mockup I'm making for a client that uses the
I have a terrible problem that hopefully has a very simple answer. I am
I have a very simple repository I'm playing around with, using Entity Framework v4

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.