So I have two tables Animals and Adoptions
The animal table holds [animalID, name, DOB]
Adoptions hold [id, animalID, userID, approved]
I need to write a statement which would match the animalID in both the tables and would return the name and DOB of the animal where approved is 0.
I have hardly any previous experience with either mySQL or Laravel so my assumption would be that the SQL query would look like this:
SELECT animalName, DOB
FROM animal
INNER JOIN
Adoption ON adoption.animalID = animal.animalID
WHERE
Adoption.approved = 0
Currently I am returning all of the animals in the table. So I need to add the join and do the checking to see if the animalID in the adoptions table has a value of 0
public function available ()
{
//JOIN ANIMAL AND ADOPTION TABLES
//RETURN ALL ANIMALS WHERE APPROVED = 0
$animalQuery = Animal::all();
return view('/available', array('animals'=>$animalQuery));
}
public function available ()
{
//JOIN ANIMAL AND ADOPTION TABLES
//RETURN ALL ANIMALS WHERE APPROVED = 0
$animalQuery = Animal::select('animals.id','animals.name', 'animals.DOB')
->join('adoptions', 'adoptions.animalid', '=', 'animals.id')
->where('adoptions.approved', 0)
->get();
return view('/available', array('animals'=>$animalQuery));
}
This is my answer which worked for me
First of all, you would need two models. An Animal model and an Adoption model. Laravel uses models to access your database table.
Using the Animal model you could create a query like this:
\App\Animal::with('adoption')->select('name','dob')->get();
Then inside your Animal model, you would need to create the relationship between the animal and adoption:
public function adoption()
{
return $this->hasOne('App\Animal', 'animalID', 'animalID');
}
This would be one way to get an animal, with the adoption information.
I really recommend reading through the Laravel documentation for relationships and eloquent, and possibly read up on some SQL.
https://laravel.com/docs/5.8/eloquent
https://laravel.com/docs/5.8/eloquent-relationships
Assuming you have an Adoption model, and adoption relation on your Animal model, you can do the following:
$animals = Animal::select('animalName`, `DOB`)
->with(['adoption' => function($query) {
$query->where('approved', false);
})->get();
Related
at the moment i try to learning Laravel and Laravel Eloquent.
I try to solve a problem using relations in Laravel.
I have following Database Structure in my simple Laravel Project.
table players:
id name
table clubs:
id name icon
table players_x_clubs:
player_id club_id
it's a one to many Relation.
Is it possible to get the full club Object who is combined with the player_id?!
The first try was to add this to my Player Model
public function club()
{
return $this->hasOne('App\PlayersXClub');
}
Here, i only get the PlayersXClub Relation with the player_id and the club_id
but i want to get the full club object from the club table, is it possible in a simple way?
any ideas how i have to realize is it correctly?
my solution was this:
public function getClubRelation()
{
$clubRelation = $this->hasOne('App\PlayersXClub')->get()->first();
$club = Club::whereId($clubRelation->club_id)->get()->first();
return $club;
}
With this solution i can do this in my code $player->getClubRelation()->icon
but i don't know if its correct solved or is there a more simple way to resolve it with Eloquent?
You always have access to objects relations. For example:
$player = Player::find(1);
$club = $player->club;
or better
$player = Player::with('club')->find(1);
However, I believe you don't need an additional table. An additional table would result in a many to many relation which doesn't make much sense here.
A player belongs to a single club and a club can have many players. So it's one to many.
You should add a club_id foreign key to players table.
$table->unsignedBigInteger('club_id');
$table->foreign('club_id')->references('id')->on('clubs')->onDelete('cascade');
Player Class
public function club() {
return $this->belongsTo(Club::class);
}
Club Class
public function players() {
return $this->hasMany(Player::class);
}
I have 3 DB table.
shows
show_genres
show_show_genre
In my show model, i have:
public function genres()
{
return $this->belongsToMany('App\ShowGenre');
}
So when i do:
$show=Show::find(1);
$show->genres give me collection with all genres that have show_id in shows_genres db.
I have also ShowGenre model where is all genres i have and i use.
Becouse i want to use sync for my genres, that names need to be in database.
But how can i find all shows that have genre id.
I couldn't find any way to get that list. Please help, thanks.
Edit:
You should do this other way around:
Have a model for Genre
your relationship method in Genre model should be
public function shows()
{
return $this->belongsToMany('App\Show', 'shows_genres');
}
belongsToMany accepts two parameters, model and pivot table name if not a standard name.
Your solution:
//Get genre 'strict'
//where could be followed by column name example:whereSlug, whereName
$strictGenre = Genre::whereName('strict')->first();
if($strictGenre)
{
//get shows of this genre
$strictShows = $strictGenre->shows;
}
Read manytomany relationships:
https://laravel.com/docs/6.x/eloquent-relationships#many-to-many
You may use
$show->genres()
->wherePivot('column', value)
->get();
By default Pivot table name must be singular : show_genre (without
plural s)
See docs
Assuming you have this relationship in your genres model
public function shows()
{
return $this->belongsToMany('App\Show', 'shows_genres', 'genre_id', 'show_id');
}
Then you can directly get all shows by genres id like this
$shows = Genre::find($id)->shows;
I'm learning Laravel and Laravel eloquent at the moment and now I try to solve a problem using relations in Laravel.
This is what I want to archive:
The database holds many sport clubs. A sport club has a lot of teams. Each team has games. The teams table has a column named club_id. Now I want to create Eloquent relations to get all games of a club.
Here is what I got so far:
Club model
id => PRIMARY
public function games()
{
return $this->hasMany('App\Models\Games')->whereHas('homeTeam')->orWhereHas('guestTeam');
}
Game model
home_id => FOREIGN KEY of team ; guest_id => FOREIGN KEY of team
public function homeTeam()
{
return $this->belongsTo('App\Models\Team','home_id')->where('club_id','=', $club_id);
}
public function guestTeam()
{
return $this->belongsTo('App\Models\Team','guest_id')->where('club_id','=', $club_id);
}
Team model
id => PRIMARY ; club_id => FOREIGN
In my controller all I want to do is Club::findOrFail($id)->games()
Executing the code above returns a SQL error that the games table does not have a column named club_id.
What is the correct way to create this kind of relation?
Thanks!
EDIT
Thanks to Nikola Gavric I've found a way to get all Games - but only where club teams are the home or away team.
Here is the relation:
public function games()
{
return $this->hasManyThrough('App\Models\Game','App\Models\Team','club_id','home_id');
}
How is it possible to get the games where the home_id OR the guest_id matches a team of the club? The last parameter in this function does not allow an array.
There is method to retrieve a "distant relationship with an intermediary" and it is called Has Many Through.
There is also a concrete example on how to use it which includes Post, Country and User, but I think it will be sufficient to give you a hint on how to create games relationship inside of a Club model. Here is a link, but when you open it, search for hasManyThrough keyword and you will see an example.
P.S: With right keys naming you could achieve it with:
public function games()
{
return $this->hasManyThrough('App\Models\Games', 'App\Models\Teams');
}
EDIT #01
Since you have 2 types of teams, you can create 2 different relationships where each relationship will get you one of the type you need. Like this:
public function gamesAsHome()
{
return $this
->hasManyThrough('App\Models\Games', 'App\Models\Teams', 'club_id', 'home_id');
}
public function gamesAsGuests()
{
return $this
->hasManyThrough('App\Models\Games', 'App\Models\Teams', 'club_id', 'guest_id');
}
EDIT #02
Merging Relationships: To merge these 2 relationships, you can use merge() method on the Collection instance, what it will do is, it will append all the records from second collection into the first one.
$gamesHome = $model->gamesAsHome;
$gamesGuests = $model->gamesAsGuests;
$games = $gamesHome->merge($gamesGuests);
return $games->unique()->all();
Thanks to #HCK for pointing out that you might have duplicates after the merge and that unique() is required to get the unique games after the merge.
EDIT #03
sortBy also offers a callable instead of a attribute name in cases where Collection contains numerical indexing. You can sort your Collection like this:
$merged->sortBy(function($game, $key) {
return $game->created_at;
});
When you define that Club hasMany games you are indicating that game has a foreign key called club_id pointing to Club. belongsTo is the same but in the other way. These need to be coherent with what you have on your database, that means that you need to have defined those keys as foreign keys on your tables.
Try this...
Club model
public function games()
{
return $this->hasMany('App\Models\Games');
}
Game model
public function homeTeam()
{
return $this->belongsTo('App\Models\Team','home_id');
}
public function guestTeam()
{
return $this->belongsTo('App\Models\Team','guest_id');
}
Your Query like
Club::where('id',$id)->has('games.guestTeam')->get();
I have Order model with another relation OrderPhoto:
public function OrderPhoto()
{
return $this->hasMany('App\OrderPhoto');
}
In turn OrderPhoto model has relation:
public function Photo()
{
return $this->belongsToMany('App\Photo');
}
So, how to get data from OrderModel with related data from third model Photo?
I guess this:
Order::with("OrderPhoto.Photo")->get();
to retrieve only data from Photo model for each Order
So, each Order has some OrderPhotos. Relationship is one to many.
But one item from OrderPhotos is related with primary key from table Photos. It is one to one relation.
My result query should be:
select `photos`.*, `ordersphoto`.`Orders_Id` from `photos` inner join `ordersphoto` on `ordersphoto`.`Photos_Id` = `photos`.`Id` where `ordersphoto`.`Orders_Id` in (1);
How to use hasManyThrough for this query?
Just having a quick look at your relationships it looks like you could create a hasManyThrough relationship on the order Model.
public function Photo {
return $this->hasManyThrough('App\OrderPhoto', 'App\Photo')
}
You may need to add the table keys to make it work
This will allow you to do:
Order::with("Photo")->get();
You can see more details here https://laravel.com/docs/5.5/eloquent-relationships#has-many-through
Update
Try this
public function Photo {
return $this->hasManyThrough('App\Photo', 'App\OrderPhoto', 'Order_id', 'Photos_id', 'id', 'id')
}
It is a little hard to get my head around your DB structure with this info but you should hopefully be able to work it out. This may also help
https://laravel.com/api/5.7/Illuminate/Database/Eloquent/Concerns/HasRelationships.html#method_hasManyThrough
I'm using laravel and eloquent.
Actually I have problems filtering results from a table based on conditions on another table's attributes.
I have 3 tables:
venue
city
here are the relationships:
a city has many locations and a location belongs to a city.
a location belongs to a venue and a venue has one location.
I have a city_id attribute on locations table, which you may figured out from relationships.
The question is simple:
how can I get those venues which belong to a specific city?
the eloquent query I expect looks like this:
$venues=Venue::with('location')->where('location.city_id',$city->getKey());
Of course that's not gonna work, but seems like this is common task and there would be an eloquent command for it.
Thanks!
A couple of options:
$venues = Venue::whereIn('location_id', Location::whereCityId($city->id)->get->lists('id'))
->get();
Or possibly using whereHas:
$venues = Venue::whereHas('location', function($query) use ($city) {
$query->whereCityId($city->id);
})->get();
It is important to remember that each eloquent query returns a collection, and hence you can use "collection methods" on the result. So as said in other answers, you need a Eager Loading which you ask for the attribute you want to sort on from another table based on your relationship and then on the result, which is a collection, you either use "sortBy" or "sortByDesc" methods.
You can look at an example below:
class Post extends Model {
// imagine timpestamp table: id, publish, delete,
// timestampable_id, timestampble_type
public function timestamp()
{
return $this->morphOne(Timestamp::class, 'timestampable');
}
}
and then in the view side of the stuff:
$posts = App\Post::with('timestamp')->get(); // we make Eager Loading
$posts = $posts->sortByDesc('timestamp.publish');
return view('blog.index', compact('posts'));