0

Lets say, I have a class Movie with a Orm\OneToMany relation ship to the class Actors.

I have already a working example of an getter for $movie->getActors(); which will return all actors of that movie.

But how to dynamically modify the query for that? For example, I show a list of all actors of the movie, and allow the user to sort by name, age, gender, whatever.

===== EDIT ======

After learning, that such things belongs to the repository class (thanks to Yoshi, scoolnico), here is the adapted question:

Lets say, I have got a Movie ID 4711. I will fetch the movie:

$movie = $this->getDoctrine()
    ->getRepository("Movie")
    ->find(4711);

And now, I need to get all Actors from this movie sorted by name (as an example).

$actorsOfMovie = $this->getDoctrine()
    ->getRepository("Actor")
    ->findBy(array("movie_id" => 4711), array('name'=>'asc'));

Is this really the correct way? With this version, I need to know in the controller, how the relationship between movie and actors work! Thats a thing, doctrine should handle for me!

And how to use it with multiple movies?

// Controller
$movies = $this->getDoctrine()
    ->getRepository("Movie")
    ->findfindBy(array());
return $this->render("xyz.html.twig", array("movies": $movies));

// Twig: xyz.html.twig
{% for movie in movies %}
    <h1>{% movie.getName() %}</h1>
    <p>Actors: {% for actor in movie.getActorsOrderByName() %}{{ actor.getName() }},{% endfor %}
{% endfor %}
9
  • Queries like that should be on the repository not the entity. That's why it's hard to do. Commented Nov 6, 2015 at 10:09
  • Ah. ok. But how to get the repository from the entity? For example, if i have the entity $movie, how to get the repository of Movie? Commented Nov 6, 2015 at 10:14
  • Ok, no. That's the whole point, your entity should not do such work. If what is initialised by doctrine issn't enough, then do it somewhere else. E.g. In the controller get the repository and have that return the correct entites. Commented Nov 6, 2015 at 10:17
  • i have modified my question Commented Nov 6, 2015 at 10:34
  • So, let me clarify, have you set up a proper associations between Movie/Actor using doctrine's association mapping? If not then, no offence, your question too broad. Because that would really be the first step to do. Done correctly, your movie entity will know what it's actors are. Commented Nov 6, 2015 at 10:36

2 Answers 2

1

You just have to create a specific function in your class Repository:

class MovieRepository extends EntityRepository
{
   public function getActoryByGender($gender)
   { 
       /.../
   }
}

And in your controller:

/.../
$em = $this->getDoctrine()>getManager();
$repository = $em->getRepository('YourBundle:Movie');
$actors = $repository->getActorByGender('male');
/.../
Sign up to request clarification or add additional context in comments.

1 Comment

i have modified my question, since i learned from you (and yoshi), that repositories are the right way, but it doesn't solve my problem
0

I think the best solution for this is to use doctrine's Criteria class (http://docs.doctrine-project.org/en/latest/reference/working-with-associations.html#filtering-collections).

Have a look at https://www.boxuk.com/insight/blog-posts/filtering-associations-with-doctrine-2

Based on this, I can do the following:

// In the Movie Class
/**
 * Get actors
 *
 * @param array $options
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getActors($options = array())
{
    if(!$options) {
        return $this->actors;
    }

    $criteria = Criteria::create();

    if(isset($options["order_by"])) {
        $criteria->orderBy($options["order_by"]);
    }
    if(isset($options["limit"])) {
        $criteria->setMaxResults($options["limit"]);
    }
    if(isset($options["offset"])) {
        $criteria->setFirstResult($options["offset"]);
    }
    // Or I can define other filters or sorting stuff
    if(..) {
        ...
    }

    return $this->actors->matching($criteria);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.