I'm new in Laravel and have problem with self relations in eloquent.
I have table users with fields id and referrer, where referrer is foreign key to table users (each user have one referrer which is also users). And table invoice has relation to users.
I want to get all invoices for user and for referrer.
In model I made relations:
public function referrer()
{
return $this->hasOne('User', 'referrer');
}
public function referral()
{
return $this->belongsTo('User','id');
}
public function invoice()
{
return $this->hasMany('invoice', 'user_id');
}
And query:
$this->model->with(['invoice'])
->with(['referrer'=> function($q)
{
$q->with(['invoice']);
}]);
}]);
But this query returns me users and their invoices but do not return referrer just empty array key referrer =>
Updated
I change relations :
public function referrer()
{
return $this->hasOne('User', 'referrer');
}
public function referral()
{
return $this->belongsTo('User','referrer');
}
public function invoice()
{
return $this->hasMany('invoice', 'user_id');
}
And now dumping result I see referrer relation but when I trying to get $user->referrer I got just referrer id instead of referrer object
Try this:
public function referrer()
{
return $this->hasOne('App\User', 'referrer', 'id');
}
public function referral()
{
return $this->belongsTo('App\User','id','referrer');
}
So finally I found solution.
Relations:
public function referrerBelong()
{
return $this->belongsTone('User', 'referrer');
}
public function referral()
{
return $this->hasOne('User','referrer');
}
public function invoice()
{
return $this->hasMany('invoice', 'user_id');
}
Relation should be like that, I change name to referrerBelong, because I have referrer column and it make conflicts and return referrer id instead of referrer object.
Query:
$this->model->with(['invoice'])
->with(['referrerBelong'=> function($q)
{
$q->with(['invoice']);
}]);
}]);
And in controller you can get referrer object using $user-referrerBelong and $user-referrer to get referrer id.
Answer was here : http://laravel.io/forum/01-22-2015-eloquent-belongsto-not-returning-relationships
Related
I am working on a survey system and I have a problem accessing one relationship through another.
I have these models and these relationships
Post
id
survey_id
public function survey()
{
return $this->belongsTo(Survey::class);
}
Surveys
id
survey_type_id
public function surveyOptions()
{
return $this->belongsToMany(Survey_options::class);
}
public function surveyType()
{
return $this->belongsTo(Survey_type::class);
}
public function posts()
{
return $this->hasMany(Post::class);
}
Survey_types
id
public function surveyOptions()
{
return $this->belongsToMany(Survey_options::class);
}
Survey_options
id
survey_type_id
public function values()
{
return $this->hasMany(Option_value::class);
}
options_values
survey_options_id
survey_id
public function surveyOptions()
{
return $this->belongsTo(Survey_options::class);
}
Survey_Survey_options (pivot)
survey_id
survey_options_id
I need to do a query with eadger loading to bring me all the posts with survey, surveyOptions, withCount comments y options_values of each surveyOptions. Something like this:
$post->survey->surveyOptions->options_values_count
I have managed to create this query that works for me everything except fetching the option_values count from each SurveyOption. How can I do it?
$posts = Post::with([
'survey' => function ($query) {
$query->withCount('totalSurveys');
},
'survey.surveyOptions',
'image',
'categories'
])
->withCount('comments')
->get();
I've 2 tables
Users table
id
name
...
Chats table
id
from_id // fk - id on users, the user sent the message
to_id // fk - id on users, intended user
message_body
Now, I'm trying to set up One to Many relation where user has many chat messages but a chat message has two user. from and to user
How can I define this relationship?. I have to user eager loading.
I tried to use Compoships but it didn't work.
My code
User Model
public function chats() {
return $this->hasMany(Chat::class, ['from_id', 'to_id'], 'id');
}
Chat Model
public function user() {
return $this->belongsTo(User::class, ['from_id', 'to_id'], 'id');
}
public function chats() {
return $this->hasMany(Chat::class, 'from_id', 'id') + $this->hasMany(Chat::class,'to_id','id');
}
public function userFrom() {
return $this->belongsTo(User::class, 'from_id', 'id');
}
public function userTo() {
return $this->belongsTo(User::class, 'to_id', 'id');
}
Why don't you do something like that?
On your User model, set up two relationships like this:
public function chatsFrom() {
return $this->hasMany('App\Chat', 'from_id');
}
public function chatsTo() {
return $this->hasMany('App\Chat', 'to_id');
}
Then, on your Chat model, also set up two relationships, one to from and another to to, both referencing a User model. Like this:
public function fromUser() {
return $this->belongsTo('App\User', 'from_id');
}
public function toUser() {
return $this->belongsTo('App\User', 'to_id');
}
This way, you can access the relationships using something like this:
$user->chatsFrom();
$user->chatsTo();
$chat->fromUser();
$chat->toUser();
I have a chat app, and I need to filter those user conversations that have attachment[s] in the groups last message, by using eloquent ORM. I have following DB tables/models:
Groups & Users. Relation is N-N between them, so there's a pivot table between groups and users, named group_user. Although this table has been expanded with some extra fields, as a result group_user have it's own model now.
Messages. Relations are 1-N from both groups and users.
Attachments. Relation is 1-N from messages.
The algorithm of this filtering isn't the problem - take user (because I need specific users groups) and his groups, find all group messages, sort them by date of creation in descending order and take the top one. And then check whether this message have any records in 'attachments' table. Obivously I do have all the relations defined in the respective Models. Right now I have this code, but it returns all groups that have attachments in any of the messages.
Also, I need to sort the query by the last message 'created_at' date.
return $user->user_groups()->whereHas('group', function($query) {
$query->whereHas('messages', function ($query) {
$query->whereHas('attachments');
});
})->with('group')->latest()->paginate($this->group->getPerPage());
Edit.
class User
{
public function messages()
{
return $this->hasMany('App\Models\Message');
}
public function user_groups()
{
return $this->hasMany('App\Models\GroupUser');
}
}
class Message
{
public function attachments()
{
return $this->hasMany('App\Models\Attachment');
}
public function author()
{
return $this->belongsTo('App\Models\User');
}
public function group()
{
return $this->belongsTo('App\Models\Group');
}
}
class Attachment
{
public function message()
{
return $this->belongsTo('App\Models\Message');
}
}
class GroupUser
{
public function user()
{
return $this->belongsTo('App\Models\User');
}
public function group()
{
return $this->belongsTo('App\Models\Group');
}
}
class Group()
{
public function messages()
{
return $this->hasMany('App\Models\Message');
}
public function group_users()
{
return $this->hasMany('App\Models\GroupUser');
}
}
Add a groups relationship to your User model:
public function groups() {
return $this->belongsToMany('App\Models\Group');
}
Then try this:
$user->groups()
->select('groups.*')
->join('messages', function($join) {
$join->on('groups.id', 'messages.group_id')
->where('created_at', function($query) {
$query->selectRaw('max(created_at)')
->from('messages')
->where('group_id', DB::raw('groups.id'));
});
})
->whereExists(function($query) {
$query->from('attachments')
->where('attachments.message_id', DB::raw('messages.id'));
})
->orderByDesc('messages.created_at')
->paginate($this->group->getPerPage());
So i'm a bit confused with this situation, I have the current relations:
User hasmany Favourite
favourites references to a Recipe model
favourites is a pivot table but when I retrieve the favourites for a given user like:
$user->favourites
i get the favourite with the pivot data, but I want to get the fields of the recipe
Recipe.php:
public function favourites()
{
return $this->hasMany('App\Favourite');
}
User.php:
public function favourites()
{
return $this->hasMany('App\Favourite');
}
Favourite.php:
public function user()
{
return $this->belongsTo('App\User','user_id');
}
public function recipes()
{
return $this->belongsTo('App\Recipe','recipe_id');
}
EDIT : there was no problem at all, just needed to call:
#foreach($user->favourites as $favourite)
{{ $favourite->recipe->name }}
#endforeach
You need to set your relation to Has Many Through instead of just has Many.
https://laravel.com/docs/5.2/eloquent-relationships#has-many-through
Recipe.php:
public function favourites()
{
return $this->hasManyThrough('App\Favourite', 'App\User');
}
User.php:
public function favourites()
{
return $this->hasManyThrough('App\Favourite', 'App\Receipe');
}
Favourite.php:
public function user()
{
return $this->hasManyThrough('App\User','App\Receipe');
}
I want to get the username in table user, of post ID in post table and return View::make('post.index'). I need to view in post.index blade.
Database
users table
id
username
post table
id
message
posts_id
Post.php #models folder
public function posts()
{
return $this->belongsTo('User');
}
User.php #models folder
public function post()
{
return $this->hasMany('Post');
}
PostController.php #controller folder
public function index()
{
$posts = Post::with('username')->get();
return View::make('post.index')->with('posts', $posts);
}
post/index.blade.php
the result here
i need to the result of author id become the username
for the best practices:
your model class names should be User and Post. database table names should be users and posts.
in Post.php file ,
public function user()
{
return $this->belongsTo('User');
}
in User.php file,
public function posts()
{
return $this->hasMany('Post');
}
in your PostController.php
public function index()
{
$user_of_the_post = Post::find(postId)->user; //replace the postId //this will return the user object of the specified post
$user_name_of_the_author = $user_of_the_post->username;
**pass the necessary data to the view and print and return the view**
}