8.4.2: Doctrine old values after persist and flush

Permalink
I have a Business Listing:
@ORM\OneToMany(targetEntity="BusinessListing\Business\BusinessReview",mappedBy="business",cascade={"persist","remove"}))

and I have Business Reviews:
@ORM\ManyToOne(targetEntity="BusinessListing\Business\Business",inversedBy="reviews",cascade={"persist"})
@ORM\JoinColumn(name="business",referencedColumnName="id",nullable=false)

What I want is after adding a review a total rating score (from all reviews) has to be calculated and saved in the Listing:
public static function saveReview($data, Business $business)
{
    ...
    $review->save();
    $review->updateBusinessRating($business);
    ...
}
public function save()
{
    $em = DatabaseORM::entityManager();
    $em->persist($this);
    $em->flush();
}
public function updateBusinessRating(Business $business)
{

MyFunctions::getBusinessRating:
public static function getBusinessRating($business = null)
{
    $reviews = $business->getReviews()->toArray(); //<- PROBLEM HERE
    if (is_array($reviews) && count($reviews) > 0) {
    ... // calculations
    }
    return round($rating, 0);
}

The problem is that the last review always gets saved in the database, but it's not picked up in the $business->getReviews()->toArray(). It's like the review counting is always one step behind.

Why is this happening? What am I missing?

linuxoid
 
linuxoid replied on at Permalink Reply
linuxoid
I finally got it! 3 days lost...

I don't know what's actually going on behind the scenes in Doctrine, but 1 tiny difference in 2 pieces of code made the whole difference.

Firstly, a working piece of code which has been proven for years, it's working, no problems. This is how I save a State for a Country:
public static function saveState($data)
{
    ...
    if ($data['country'] > 0) {
        $country = LocationCountry::getByID($data['country']); // <- Country ID from form POST
        $state->setCountry($country);
    }
    $state->save();
    return $state;
}
public function save()
{
    $em = DatabaseORM::entityManager();
    $em->persist($this);
    $em->flush();

And now the difference in Review was that I'm passing a Business object directly to the saveReview() method, not from request, and I set the Business in Review right there without any DB query:
public static function saveReview($data, Business $business) // <- HERE
{
    ...
    $review->setBusiness($business); // <- HERE
    $review->save();
    $review->updateBusinessRating();
    return $review;
}
public function save()
{
    $em = DatabaseORM::entityManager();
    $em->persist($this);
    $em->flush();
}

So after the following minor mods - explicit setting of the Review and persisting the Business, it started working the way it should.

In Business:
public function setReviews(BusinessReview $review)
{
    $this->reviews[] = $review;
}

In Review:
public function save()
{
    $em = DatabaseORM::entityManager();
    $em->persist($this);
    $this->business->setReviews($this);
    $em->persist($this->business);
    $em->flush();
}

Again, don't know what the Doctrine engine does there int its black box, but this makes it work.

FFS, 3 days lost! :)