3

After reading several other questions, it looks like it's not advisable to have an entity class use a Repository. So given these repositories:

class RestaurantRepository {
    public function findAll() { ... }
}

class ReviewRepository {
    public function findByRestaurant(Restaurant $restaurant) { ... }
}

I should not do this in my class:

class Restaurant {
    public function getReviews() {
        // ...
        return $restaurantRepository->findByRestaurant($this);
    }
}

Buts let's say I have this controller, which gives a list of Restaurants to the view:

class IndexController {
    public function indexAction() {
        $restaurants = $restaurantRepository->findAll();
        $this->view->restaurants = $restaurants;
    }
}

What is the "good practice" to get each restaurant's reviews in the view script? I can therefore not do this:

foreach ($this->restaurants as $restaurant) {
    $reviews = $restaurant->getReviews();
}

And I guess that injecting the ReviewRepository in the view is not what we can call a "best practice" as well...

Any comment welcome!

BenMorel
  • 34,448
  • 50
  • 182
  • 322

1 Answers1

3

If you need to have the reviews with the restaurant, your restaurant repository should (perhaps, optionally) retrieve these with the restaurant. These would be stored in the class instance as a collection of Reviews along with each Restaurants other data. This will allow you to construct a more efficient query that will get all the data in one go and populate the required objects. The design pattern is called aggregate root.

class RestaurantRepository {
    public function findAll($withReviews = 0) { ... }
}

class IndexController {
    public function indexAction() {
        $restaurants = $restaurantRepository->findAll(1);
        $this->view->restaurants = $restaurants;
    }
}

<?php
foreach ($this->restaurants as $restaurant) {
    foreach ($restaurant->reviews as $review) {
       ...
    }
}
?>
Community
  • 1
  • 1
tvanfosson
  • 524,688
  • 99
  • 697
  • 795
  • Thanks for your answer. Actually, both Restaurant and Review are aggregate roots (a Review has a Restaurant and a User, and has its own Repository). A Review can be created outside a Restaurant, so in my understanding it's not part of the Restaurant aggregate. Therefore should a Restaurant's *Review collection* still be populated by the Restaurant repository? – BenMorel Jul 31 '11 at 22:25
  • I finally realized that I didn't need all the reviews for each restaurant, but just a summary of them. I've therefore put review statistics (number of reviews, average rating) in the Restaurant entity, and don't need to access the ReviewRepository anymore. And if I needed to do this, I would just introduce a value object that would contain the restaurant along with its reviews, and pass this to the view. – BenMorel Feb 06 '13 at 21:14