Defining a relation in Eloquent Model Laravel - laravel

I have this query
SELECT * FROM users AS u INNER JOIN branches AS b ON u.branch_id = b.branch_id
This means to every one user there is a branch associated but one branch can be associated with many user.
Can anyone help me how to define this relation?
I did this
I wrote this relation in User model
public function branch()
{
return $this->belongsTo('App\Branch');
}
And it returns null.

You problem seems to be inverse of one to many relationship i.e. Many to One.
Here, in your case Many Users belongs to one Branch. So, you can define Many to One relationship in User model as :
public function branch()
{
return $this->belongsTo('App\Branch','branch_id');
}
Now, you can access branch of a user like this:
$user = User::find($id);
$branch = $user->branch;
Hope you understand.

You should try this:
public function branch()
{
return $this->belongsTo('App\Branch','branch_id');
}
Hope this work for you !!!

Related

Laravel eloquent for four tables

I'm new to Laravel. I am developing a project. and in this project I have 4 tables related to each other
-Users
-Orders
-OrderParcels
-Situations
When listing the parcels of an order, I want to get the information of that order only once, the user information of that order once again, and list the parcels as a table under it. so far everything ok. but I also want to display the status of the parcels listed in the table as names. I couldn't add the 4th table to the query. do you have a suggestion? I'm putting pictures that explain the structure below.
My current working code is
$orderParcels = Orders::whereId($id)
->with('parcels')
->with('users:id,name')
->first();
and my 'orders' model has method
public function parcels(){
return $this->hasMany(OrderParcels::class);
}
public function users(){
return $this->hasOne(User::class,'id','affixer_id');
}
Note[edit]: I already know how to connect like this
$orderParcels = DB::table('order_parcels as op')
->leftjoin('orders as o','op.orders_id','o.id')
->leftjoin('users as u','o.affixer_id','u.id')
->leftjoin('situations as s','op.status','s.id')
->select('op.*','o.*','u.name','s.situations_name')
->where('op.orders_id',$id)->get();
but this is not working for me, for each parcels record it returns me orders and user info. I want once orders info and once user info.
Laravel provides an elegant way to manage relations between models. In your situation, the first step is to create all relations described in your schema :
1. Model Order
class User extends Model {
public function parcels()
{
return $this->hasMany(OrderParcels::class);
}
public function users()
{
return $this->hasOne(User::class,'id','affixer_id');
}
}
2. Model Parcel
class Parcel extends Model {
public function situations()
{
return $this->hasOne(Situation::class, ...);
}
}
Then, you can retrieve all desired informations simply like this :
// Retrieve all users of an order
$users = $order->users; // You get a Collection of User instances
// Retrieve all parcels of an order
$parcels = $order->parcels; // You get a Collection of User instances
// Retrieve the situation for a parcel
$situations = $parcel->situations // You get Situation instance
How it works ?
When you add a relation on your model, you can retrieve the result of this relation by using the property with the same name of the method. Laravel will automatically provide you those properties ! (e.g: parcels() method in your Order Model will generate $order->parcels property.
To finish, in this situation where you have nested relations (as describe in your schema), you should use with() method of your model to eager load all the nested relation of order model like this :
$orders = Orders::with(['users', 'parcels', 'parcels.situations'])->find($id)
I encourage you to read those stubs of Laravel documentation :
Define model relations
Eager loading
Laravel Collection
Good luck !
Use join to make a perfect relations between tables.
$output = Orders::join('users', 'users.id', '=', 'orders.user_id')
->join('order_parcels', 'order_parcels.id', '=', 'orders.parcel_id')
->join('situations', 'situation.id', '=', 'order_parcels.situation_id')
->select([
'orders.id AS order_id',
'users.id AS user_id',
'order.parcels.id AS parcel_id',
'and so on'
])
->where('some row', '=', 'some row or variable')->get();

Laravel pivot with multiple columns

Hi I have a problem with Laravel`s pivot table.
I have the following tables: students, courses and lessons.
The table lessons is connected with courses through a foreign key courses_id, and the tables students and courses are connected through a pivot courses_students.
So I can access the information through students like this:
//Students model
public function courses()
{
return $this->belongsToMany(Courses::class,'courses_students','student_id', 'course_id')
->with('lessons');
}
//Courses model
public function lessons()
{
return $this->hasMany(Lesson::class);
}
This works completely fine for this kind of relationship, but I want to add a third column in the pivot with name lesson_id for the lessons table.
I am doing this because, sometimes I need to get a specific set of lessons from each course for each user.
I succeeded in doing so, by using a model courseStudent for the pivot table.
Using the model for pivot my calls became like this.
Student->with('courseStudent.courses')
->with('courseStudent.lessons')
->get();
This partially does what I need it to do, but I want to maintain the relation ship between courses and students.
Is there a way to achieve that?
Example from docs(go through Many To Many):
return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');
Pivot table is meant to use belongsToMany relationship on both entities.
So your students and courses should have it defined if you want pivot table between that is using eloquent default capacity.
As a side note pay attention on naming convention because that way you will reduce issues on minimum: pivot table should be tableanamesingular_tablebnamesingular where order is set by alphabetical order of tables' names (i.e. post_user Yes, user_post No).
Id fields in pivot table should be tablenamesingular_id.
You can set names however you want but this way you will have less unepected behavior in future using eloquent. All of this you have in documentation page and I recommend you go through it thoroughly.
Other way is to use dynamic properties for getting certain values. Example from docs:
$user = App\User::find(1);
foreach ($user->roles as $role) {
echo $role->pivot->created_at;
}
If you would like to manually change values in pivot table, you should create separate model for it that would be connected with that entity/table (pay attention that pivot model extends Pivot as in example from docs rather than Model):
<?php
namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;
class PostUser extends Pivot
{
// other definitions related
}
You can use join for third relation:
public function courses(){
return $this->belongsToMany(Courses::class,'courses_students','student_id', 'course_id')
->withPivot('lesson_id')
->join('lessons','lesson_id','=','lessons.id')
->select('lessons.id','lessons.title', ...);
}
If you are going to use the same pivot table for courses and lessons, you can to do something like this:
//Students model
public function courses()
{
return $this->belongsToMany(Courses::class,'courses_students','student_id', 'course_id')
->whereNotNull('course_id');
}
public function lessons()
{
return $this->belongsToMany(Lessons::class,'courses_students','student_id', 'lesson_id')
->whereNotNull('lesson_id');
}
Then just use it:
$courses = $student->courses;
$lessons = $student->lessons;

How to get all related items like "with" in Laravel?

I'm sorry, I don't even know how to ask for what I need...
User:
id
MyItem:
id
item_id
user_id
Item:
id
How to get $user->items()?
I guess hasManyThrough() won't help here.
Thank your very much for help.
If you have defined your relationship and have items relation in your User model, you can get them using:
foreach ($user->items as $item) {
echo $item->id;
}
As it's many to many relationship, in class User you need to define your relationship this way:
public function items() {
return $this->belongsToMany('Item');
}
and in Item class this way:
public function users() {
return $this->belongsToMany('User');
}
And your pivot_table should have here name item_user. If it's not, pass your table name as 2nd argument to belongsToMany method
I don't know what you want exactly but
i think you need user relative more information
if you want user relative in formation
so please try this
you get all information about user
$users = User::all();

Laravel - Relationship between a table with two other tables

I have 3 tables: users, pools, permissions. Users and Pools have a pivot table since they have a many-to-many relationship.
Permission entries are created by me only manually. Then, each pool can assign permissions to their own users as they see fit. Therefore, the pivot table for linking users to permissions needs to have both pool_id and user_id and permission_id
So how does this pivot table work? How do I make a three-way pivot table?
EDIT: My question is basically asked here, with no satisfactory answer!
For pivot table linking 3 models you need additional data send when attaching models like in this answer: Laravel - Pivot table for three models - how to insert related models?:
$model->relation()->attach($otherModel, ['thirdModelKeyName' => 'thirdModelKeyValue']);
You can create custom relation class, say ThreeBelongsToMany, that will extend belongsToMany and override attach() method.
Then override belongsToMany() method on your models, that are involved in such relation (or use a Trait there) to return mentioned custom relation class instead of generic belongsToMany when applicable.
The attach() method could look like this:
public function attach($id, array $attributes = array(), $touch = true, $otherId = null)
{
if ( ! is_null($otherId))
{
if ($otherId instanceof Model) $otherId = $otherId->getKey();
$attributes[$this->getThirdKey()] = $otherId;
}
return parent::attach($id, $attributes, $touch);
}
Also you can use some helpers to fetch those related models, like for example (key names should be obtained with methods for flexibility, they are hard coded to make it short):
/**
* Accessor for far related model (thru pivot)
*
* #return mixed
*/
public function getTrackAttribute()
{
if (is_null($this->pivot)) return null;
if (is_null($this->pivot->track_id)) return null;
return ($this->pivot->track) ?: $this->pivot->track = Track::find($this->pivot->track_id);
}

Eloquent push() and save() difference

I have read laravel 4 docs about eloquent and was quite intrigued by the push() part.
It says,
Sometimes you may wish to save not only a model, but also all of its relationships. To do so, you may use the push method:
Saving A Model And Relationships
$user->push();
See link here
Sorry but it's a bit blurry on my part the difference between save() and push().
I am hoping someone can clear this one out for me. Thank you.
Heres the magic behind the scenes...
/**
* Save the model and all of its relationships.
*
* #return bool
*/
public function push()
{
if ( ! $this->save()) return false;
// To sync all of the relationships to the database, we will simply spin through
// the relationships and save each model via this "push" method, which allows
// us to recurse into all of these nested relations for the model instance.
foreach ($this->relations as $models)
{
foreach (Collection::make($models) as $model)
{
if ( ! $model->push()) return false;
}
}
return true;
}
It just shows that push() will update all the models related to the model in question, so if you change any of the relationships, then call push()
It will update that model, and all its relations
Like so...
$user = User::find(32);
$user->name = "TestUser";
$user->state = "Texas";
$user->location->address = "123 test address"; //This line is a pre-defined relationship
If here you just...
$user->save();
Then the address wont be saved into the address model....
But if you..
$user->push();
Then it will save all the data, and also save the address into the address table/model, because you defined that relationship in the User model.
push() will also update all the updated_at timestamps of all related models of whatever user/model you push()
Hopefully that will clear the things....
Let's say you did this:
$user = User::find(1);
$user->phone = '555-0101';
$user->address->zip_code = '99950';
You just made changes to two different tables, to save them you have to:
$user->save();
$user->address->save();
or
$user->push();
push() can only be used to update an existing model instance along side its relations not to create a new one. Simply say: push() updates and not insert.

Resources