In Laravel I have this models:
class User {
public function sites(){
return $this->belongsToMany(Site::class);
}
}
and
class Site extends Model {
public function users(){
return $this->belongsToMany(User::class);
}
}
In DB after migrations I have the table site_user with fields: user_id and sites_id.
Now, how can I retrieve for each users the sites al linked to him?
Thanks for the reply.
Use eager loading
$users = App\User::with('sites')->get();
Please check the link below you need to pass the method name on query like below:
$users = App\Users::with('sites')->get();
for more information please visit:
https://laravel.com/docs/5.4/eloquent-relationships#eager-loading
also this will help you to reduce the load on your query.
Related
To keep things simple, I'll give an example in code to what I'm trying to Achieve.
Let's assume that we have a model called User with the following code:
class User
{
public function posts()
{
return $this->hasOne(Post::class);
}
}
And the Post model look something like this.
class Post
{
public function comments()
{
return $this->hasMany(Comment::class);
}
}
And now what I want to be able to do is for example:
$user = Auth::user();
$comments = $user->post->comments; //here, I only want the "comment_id" and "comment_content" fields to be included, not all the Comment Model fields !
you can simply use hasManyThrough in user model to connect comments table.
read about hasManyThrough here: docs
and after having a relation between user and comments (hasManyThrough)
you can use load (Lazy eager loading) method
there is an piece of code you can use here
$user->load(["comments" => function($q){
$q->select("comment_id","comment_content");
}]);
read more about Lazy eager loading: docs
I have three tables, a user table, documents table, and a favourites table. The idea is a user can favourite a document, but I can't understand the best way to query this using Eloquent.
User.php
class User extends Authenticatable
{
public function documents()
{
return $this->hasMany('App\Document');
}
public function favourites()
{
return $this->hasMany('App\Favourite');
}
}
Document.php
class Document extends Model
{
public function user()
{
return $this->belongsTo('App\User');
}
}
Favourite.php
class Favourite extends Model
{
public function user()
{
return $this->belongsTo('App\User');
}
public function document()
{
return $this->belongsTo('App\Document');
}
}
The favourite table is a simple 2 column table with the user_id and the document_id linking each user to an article they have favourited.
Now I can use a method to get the users favourite articles like so:
App\User::with('favourites')->find(1);
The problem is this brings back the two id's from the favourites table when I want the data from the documents table such as the title and id of the document.
It looks like the "has-many-through" relationship is what I might need to achieve this query, but I'm unsure how to implement it in this use case or even if the "has-many-through" relationship is the correct way to do this?
As your relationship is being setup, you can have a user that has multiple documents, and he can also make multiple documents to be his favorites. So it will always return an array. In order to load all the documents for the user that are his favorites, you can do that the same as you started:
$favoriteDocuments = App\User::with('favourites.document')->find($userId = 1)->get();
// this will contain all the favorite documents for the user, so you can the iterate over them:
foreach($favoriteDocuments as $favoriteDocument)
{
// $favoriteDocument->document; is the object you are looking for.
}
Has many through relationship is used in order to get item from a table to which you don't have access to directly. But to both of your tables you have direct connection to the user.
You are correct with has-many-through, so on User:
return $this->hasManyThrough('App\Document', 'App\Favourite');
And on Document:
return $this->hasManyThrough('App\User', 'App\Favourite');
Eloquent Docs
Your favorites table is a Pivot table. You don't need a favorites model.
User.php
public function favoriteDocuments()
{
return $this->BelongsToMany('App\Document', 'favorite_documents');
}
Now you can call $user->favoriteDocuments to get the users documents.
See the docs about many to many relationships. https://laravel.com/docs/5.7/eloquent-relationships#many-to-many.
My comments table has the following columns:
id, user_id, image_id, comment
Currently I'm getting all comments that belong to a specific image like this:
$comments = Comment::where('image_id', $id)->get();
And then I can easily display the comments on the view to which I pass the $comments variable. However, I can only display the id of the user who has posted the comment but that wouldn't make much sense so I'm trying to display the username instead.
Since I don't save the username of the user who has posted a comment in the comments table, I can't access it from $comments as of now. Is there a way to somehow add an extra key-value pair to $comments that would contain the username of the user based on his id?
Comment model:
class Comment extends Model
{
public function images(){
return $this->belongsTo('App\Image');
}
public function users(){
return $this->belongsTo('App\User');
}
}
User model:
class User extends Model implements Authenticatable
{
public function comments(){
return $this->hasMany('App\Comment');
}
}
I guess that you should have a table/model for the User objects.
If so, you can Eager Load the relationship. To accomplish this, define the relationship in your model:
app/Comment.php
public function users()
{
return $this->belongsTo(User::class);
}
Note: given that this is the reverse of a hasMany relationship (belongsTo), you should name this functions in singular: a Comment belongs to a unique User.
Then in your controller:
$comments = Comment::with('users')->where('image_id', $id)->get();
This will include the user object inside every comment. Of course, you can limit the user attributes returned to the view but you get te idea.
To know more about this, check the documentation.
Make a Join similar to connect both tables!
$comments = DB::table('comment')
->join('user', 'comment.user_id', '=', 'user.id')
->select('comment.*', 'user.name')
->where(image_id, $id)
->get();
A related question with eloquent specifics
How to join three table by laravel eloquent model
Database
I'm kind of new to databases and I made this small database, but I have problems fetching data from it.
Im trying to get all the racers from the logged in user, and it works properly, but if I enter $pigeons = $user->racer I only get back the racer table. I would like to know the attributes of the racers from the pigeons table aswell. I've made it work with query builder left joining the tables but I'm not sure why I set up this relationship if I can't use Laravel inner method.
In the User model I have these relationships:
public function pigeons(){
return $this->hasMany('App\Pigeon');
}
public function racers(){
return $this->hasManyThrough('App\Racer', 'App\Pigeon');
}
This is the Pigeon model:
public function user(){
return $this->belongsTo('App\User');
}
public function racer(){
return $this->hasMany('App\Racer');
}
}
And this is the Event model:
public function race(){
return $this->hasOne('App\Race');
}
public function racers(){
return $this->hasMany('App\Racer');
}
And this is what my EventsController looks like with the working alternative method and the commented not working.
public function upcoming(){
$id = auth()->user()->id;
$user = User::find($id);
$pigeons = DB::table('racers')->leftJoin('pigeons', 'racers.pigeon_id', '=', 'pigeons.id')->where('pigeons.user_id', '=', $id)->get();
//$pigeons = $user->racers;
return view('events.upcoming')->with('pigeons', $pigeons);
}
This is what I get with $user->racers or $user->racers()->get():
[{"id":1,"pigeon_id":14,"user_id":4,"event_id":1,"position":0,"created_at":null,"updated_at":null},{"id":2,"pigeon_id":15,"user_id":4,"event_id":1,"position":0,"created_at":null,"updated_at":null},{"id":3,"pigeon_id":16,"user_id":4,"event_id":1,"position":0,"created_at":null,"updated_at":null}]
And this is what I want to get, its not correct either since I should get id:1 but I want to pass to view these additional datas aswell like gender, color, ability (but they are in pigeons table not in racers).
[{"id":14,"pigeon_id":14,"user_id":4,"event_id":1,"position":0,"created_at":"2018-09-27 10:01:04","updated_at":"2018-09-27
10:01:04","gender":"hen","color":"blue","ability":38},{"id":15,"pigeon_id":15,"user_id":4,"event_id":1,"position":0,"created_at":"2018-09-27 10:01:04","updated_at":"2018-09-27
10:01:04","gender":"hen","color":"blue","ability":48},{"id":16,"pigeon_id":16,"user_id":4,"event_id":1,"position":0,"created_at":"2018-09-27 10:01:04","updated_at":"2018-09-27
10:01:04","gender":"cock","color":"blue","ability":11}]
To get the pigeons, what you would have to do is $pigeons = $user->racers()->get();. You can see an example of this in Laravel's official documentation https://laravel.com/docs/5.5/eloquent-relationships#introduction.
I have the following schema set up:
users:
id
departments:
id
department_user:
id
department_id
user_id
I also have the following relationships set up:
User Model
public function departments()
{
return $this->belongsToMany('App\Resources\Eloquent\Models\Department', 'department_users');
}
Department Model
public function users()
{
return $this->belongsToMany(User::class, 'department_users');
}
For some reason, when I am trying to access through the user model $user->departments, it doesn't work - but $department->users does.
Outputting the eloquent query is as follows:
select `departments`.*, `department_users`.`user_id` as `pivot_user_id`, `department_users`.`department_id` as `pivot_department_id` from `departments` inner join `department_users` on `departments`.`id` = `department_users`.`department_id` where `department_users`.`user_id` is null
I can't seem to figure out why it is looking to see if department_users.user_id is null, when it should be looking for the user's id.
Any ideas?
Why don't you set up your models like it is suggested in the documentation here:
So your models would look something like this:
User Model
public function departments()
{
return $this->belongsToMany('path\to\your\model\Department');
}
Department Model
public function users()
{
return $this->belongsToMany(path\to\your\model\User);
}
Eloquent will join the two related model names in alphabetical order.So you don't need extra arguments when defining your relationship and Laravel also by default, makes model keys present on the pivot object. And then you can do something like this:
$department = path\to\your\model\Department::find(1);
foreach ($department->users as $user) {
echo $user;
}
For some reason, if I make the relationship the following - it works.
return $this->belongsToMany(Department::class, 'department_users')->orWhere('department_users.user_id', $this->id);
If anyone knows why, please let me know