I have two models ("Films" and "Tags") related in a Many to Many relation. I have therefore Three Tables: "films", "tags" and "film_tag" EDITED: I have belongsToMany relations in place like this:
film.php
public function tags()
{
return $this->belongsToMany('App\Tag', 'film_tag');
}
tag.php
public function films()
{
return $this->belongsToMany('App\Film');
}
I want to get a list of all films that have a tag. I am passing the variable "$tag" which contaings the slug of the tag.
In my Database I have this
Table TAGS:
id Tag
1 BEST
Table FILMS:
id Film
1 Fantomas
2 Minions
Table FILM_TAG
id Film_id Tag_id
1 1 1
2 2 1
So, one tag asigned to two films.
1- Using Laravel Eloquent I did this:
if (isset($tag)) {
$all_element = Film::whereHas('tags', function ($query) {
$query->where('tag', $tag);
})
->get();
}
But I get the following error message:
Undefined variable: tag
QUESTIONS:
2- Using normal laravel queries with DB I did this:
if (isset($tag)) {
$all_element = DB::table('films')
->join('film_tag', 'film_tag.film_id', '=', 'films.id')
->join('tags', 'tags.id', '=', 'film_tag.tag_id')
->select('films.*')
->where('tags.slug', '=', $tag)
->get();
}
In this case I get just the first film repeated the number of times that this relation exist. In this case "Fantomas" two times. If I would have ten related films, I would get the first film repeated ten times.
In the other hand this variant do not give back a collection and therefore is difficult to manipulate the results (since all the methods are build to works with collections of objects)
3- I did a third solution which get the right solution: getting all films and then foreach
$all_element = Film::get();
if (isset($tag)) {
$element_paused = array();
foreach ($all_element as $element) {
if (count($element->tags) > 0) {
foreach ($element->tags as $gat) {
if ($gat->slug === $tag) {
array_push($element_paused, $element);
}
}
}
}
$all_element = $element_paused;
}
but this is a very SLOW solution, since I have more that 700 films in the Database
I would like to implement the first approach, which is very fast, but I get the repeated film all the time. Any help to find the bug would be appreciated
As you are using belongsToMany
relationship this is the best approach to get all your films.
if (isset($tag)) {
$all_element = Film::whereHas('tags', function ($query) use($tag) {
$query->where('slug', $tag);
})
->get();
}
Look you are missing the use($tag)
portion for what you are getting undefined variable: tag
error.