Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

php - Doctrine postLoad event for associations

I currently have an entity which I would like to modify slightly upon load. This modification will be a one time change which will then be persisted in a new field along with the entity.

To clarify my current objective: The entity is a "Location" and forms part of a nested set. It has a name, lft/rgt values and an Id. One computationally expensive task I was performing with this entity was to fetch a full location path and display it as text. For example, with the location entity "Waterloo" I want to display as "Waterloo|London|United Kingdom". This involves traversing through the entire set (to the root node).

To reduce the cost of this I've created a new field on the Location entity that can be stamped with this value (and updated as/when the location (or any location within the tree) name is modified). Considering my application is in a live state I need to avoid running this as a one off process as it would incur quite an intensive one-time hit on the DB, instead I'd like to apply this update as and when each location (without that value) is loaded. I assumed Doctrine's postLoad event mechanism would be perfect for achieving this, however..

The Location entities are not loaded directly by my application, they will always be the inverse side of a relation. With this is mind, and the fact that doctrine's postLoad event:

  • Doesn't load (allow access to) any associated data
  • Is only fired for owning Entities

I have no way of gently making these modifications.

Anyone have any advice, or experience on this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I was able to load the associated Location objects within the postLoad event by using the initializeObject() method on the Entity Manager.

/**
 * Upon loading the object, if the location text isn't set, set it
 * @param DoctrineORMEventLifecycleEventArgs $args
 */
public function postLoad(DoctrineORMEventLifecycleEventArgs $args)
{
    $this->em = $args->getEntityManager();
    $entity = $args->getEntity();

    if ($entity instanceof EntitiesLocation)
    {
        if (is_null($entity->getPathText()))
        {
            $entity->setPathText("new value");
            $this->em->flush($entity);
        }
    } elseif ($entity instanceof {parent Entity})
    {
        $location = $entity->getLocation();
        // This triggers the postLoad event again, but this time with Location as the parent Entity
        $this->em->initializeObject($location);
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...