Laravel include relationships with model after update - php

I'm using a role package which stores hasMany relational data in my database. So there is a users table and a user_roles table with foreign keys...etc...
I am updating the model using the following code:
$user = User::findOrFail($id);
$user->update(request()->all());
$user->syncRoles(request()->input('roles', []));
Is there any way I can keep a reference of the roles on the $user variable so they can be used after these lines of code run?
I'm asking because I'm using a logging system after the fact like so:
activity()->on($user)->by(auth()->user())->withProperties([
'user' => $user,
'roles' => request()->input('roles'),
])->log('Updated User');
Which I would like to condense to just:
activity()->on($user)->by(auth()->user())->withProperties($user)->log('Updated User');

You will need to refresh the model data from the database. E.g.
$user = $user->fresh('roles');

For example using lazy loading:
$user = User::findOrFail($id);
$roles = $user->roles;
and on your User Model you would create a HasMany relationship to roles table.
Eager loading:
$user = User::with('roles')->findOrFail($id);

Add the relationship in your User.php model :
public function roles(){
return $this->hasMany(Role::class);
}
Now simply call it in your code to get the roles like so:
$aUser = User::with('roles')->find($id);
$roles = $aUser->roles;

Related

Laravel: How to merge a Model into another Model

I'm using Lumen to create an API which has to handle 2 entities: Gamemaster and Player. Both of them are actually a User of my API since they have to provide a token. So at the end, 'gamemaster' and 'player' are just an 'user' role.
So I manage them using 3 Models that handle informations from the database (I keep it simple for the example):
User:
id
username
email
password
Gamemaster:
user_id (user id as foreign key)
created_games
...
Player:
user_id (user id as foreign key)
registered_games
...
So my question is: Is it possible to merge the Model User into Gamemaster and Player? So that I can for example get a gamemaster email using Gamemaster::find($id)->email. Is there any way or I should each time search in both models to get all infos:
$user = User::find($id);
$userAsGamemaster = Gamemaster::where('user_id', '=', $id)->first();
$gamemasterName = $user->username;
$gamemasterEmail = $user->email;
$gamemasterCreatedGame = $userAsGamemaster->created_games;
use relations on model for this.
As in your case Gamemaster and Player both belongs to User so you can define relation on Gamemaster model and Player Model as following: ->
public function user(){
return this->belongsTo('App\User', 'your_foregin_key', 'Your_local_key');
}
Now You can fetch email as follows: ->
$userAsGamemaster = Gamemaster::where('user_id', '=', $id)->first();
$email = $userAsGamemaster->user->email;
Or by using:
Gamemaster::find($id)->user->email;
That's all.
Okay. I write in an answer what we had been talking about in the comments.
Not answer to the question of merge two models, but you can achive what you want defining the relationship in your models Gamemaster and Player:
public function user()
{
return $this->belongsTo(User::class);
}
So, if you have the User model id in the $id variable, you can do something like this:
$gamemaster = Gamemaster::where('user_id', $id)->first();
$gamemasterName = $gamemaster->user->username;
$gamemasterEmail = $gamemaster->user->email;
$gamemasterCreatedGame = $gamemaster->created_games;
And if in the $id variable you have the Gamemaster model id, you can do something like this:
$gamemaster = Gamemaster::find($id);
$gamemasterName = $gamemaster->user->username;
$gamemasterEmail = $gamemaster->user->email;
$gamemasterCreatedGame = $gamemaster->created_games;
And the same for the Player.

how to access the one to many model relation in laravel,with access all the columns

I am creating a comment table in my Laravel project so that users can comment on products. I want to make a table which can integrate with my user table (like a one-to-many relationship) in Laravel.
Here is my code:
public function buyproduct($id){
$user = Auth::user();
$users_comment = User::with('comments')->get();
$comments =comments::orderBy('id','desc')->get();
$renimage = Clothes::where('id',$id)->first();
return view('pages.products',[
'renimage'=>$renimage,
'google_avater'=>$user,
'comments'=>$users_comment
]);
}
Here I send my data to the view in my project. I don't understand how to access the data which is in my user table along with the data in the comment table.
First comments::orderBy... should be Comments::orderBy... ,
But you don't need that,
It's so simple to get user comments :
First Method: Using with()
Once the relationship has been defined, we can access the collection of comments by accessing the comments property. Remember, since Eloquent provides "dynamic properties", we can access relationship methods as if they were defined as properties on the model:
$books = App\Book::with('author')->get();
foreach ($books as $book) {
echo $book->author->name;
}
Second Method : Direct
Thankfully, we can use eager loading to reduce this operation to just 2 queries. When querying, you may specify which relationships should be eager loaded using the with method:
$comments = App\Post::find(1)->comments;
foreach ($comments as $comment) {
//
}
In your case :
public function buyproduct($id){
$user = Auth::user();
$users_comment = User::with('comments')->get();
//blow line changed
$comments =$users_comment->comments;
$renimage = Clothes::where('id',$id)->first();
return view('pages.products',[
'renimage'=>$renimage,
'google_avater'=>$user,
'comments'=>$users_comment
]);
}
Hope it helps;)

Reverse contains() in laravel?

I'm new to laravel,
I'm trying to get a row from a table according to it's Many-to-Many relationship with another table.
You know when you pass multiple ids in contain() to check if they have relationship with that row or not, like this:
$row->contains([4,6,9]);
i want to reverse this, where i can use the ids [4,6,9] to get any row from the other table linked with them.
Let's say you have this two models: User and Role that makes many-to-many relationship.
If you defined your relationships properly:
/** User.php */
public function roles()
{
return $this->belongsToMany(Role::class);
}
-
/** Role.php */
public function users()
{
return $this->belongsToMany(User::class);
}
Then you could use the relationship to accomplish what you are trying to do.
From the related object:
$user = User::find(1);
// getting all the roles attached with a user:
$roles = $user->roles;
// getting all the roles attached with a user that has certain ids:
$roles = $user->roles()->whereIn('id', [2, 4, 6])->get();
Also, you could find your desired related model using the collection instance that return the relationship:
$user = User::find(1);
// getting all the roles attached with a user:
$roles = $user->roles;
// getting a specific role attached to a user:
$specific_role = $roles->where('id', 6)->first();

Understanding Eloquent in Laravel

Previously I have worked with bog standard PHP and have recently made the move over to Laravel. One thing I cannot grasp is SQL queries in Laravel Eloquent.
For instance I have a roles and a users table. The roles table contains roles and IDs for each role. The users table contains various user details as well as a role_id to reference the role of the user.
What I have tried in my user model
public function role()
{
// return $this->hasOne('App\Phone', 'foreign_key', 'local_key');
return $this->hasOne('App\Role', 'id', 'role_id');
}
What I have tried in my role model
public function users()
{
return $this->hasMany('App\User', 'role_id', 'id');
}
Then in my controller
public function index()
{
$var = User::find()->role->get();
return view('article',
array(
'var' => $var
));
}
But now how do I access the fields in both tables as I would in ordinary PHP? I would rather use standard SQL but am trying to properly learn this framework.
Any advice?
You can access table fields via eloquent model attributes.
If you have fields like name, email you can fetch them like
$user = User::find(1);
$name = $user->name;
$email = $user->email;
$roleName = $user->role->name;
Note that you do not really have to call get() method on relation. Accessing it will call it automatically.
Laravel docs are pretty helpful in this matter. Laravel 5.2 Eloquent: Getting Started and Laravel 5.2 Eloquent: Relationships
Try it with eager loading
$var = User::with('role')->find($userId)->get();

Creating an Eloquent Object with relation included

I'm pretty much new to opps and laravel both
So, to insert the values into my users and profiles table which hav OneToOne relationship, Here is how my store() method looks like
public function store(Requests\StoreNewUser $request)
{
// crate an objct of user model
$user = new \App\User;
// now request and assign validated input to array of column names in user table
$user->first_name = $request->input('first_name');
$user->last_name = $request->input('last_name');
$user->email = $request->input('email');
$user->password = $request->input('password');
/* want to assign request input to profile table's columns in one go
*/
$user->profile()->user_id = $user->id; // foreign key in profiles table
$user->profile()->mobile_no = $request->input('mobile');
dd($user); // nothing related to profile is returned
}
I'm creating the new record, hence dd() never returns anything related to profile table.
Is this Because the $user object is not including relationship by default?
If yes Can i create the $user object which includes the associated relations in User Model ?
Or do i have to create two separate objects of each table and save() the data But then what is the significance of push() method ?
EDIT 1
P.S. yes, the relationships are already defined in User & Profile model
You may try something like the following. At first save the parent model like this:
$user = new \App\User;
$user->first_name = $request->input('first_name');
// ...
$user->save();
Then create and save the related model using something like this:
$profile = new \App\Profile(['mobile_no' => $request->input('mobile')]);
$user->profile()->save($profile);
Also make sure you have created the profile method in User model:
public function profile()
{
return $this->hasOne('App\Profile');
}
I thought i'd update this answer and make it applicable to Laravel 5 onwards. I'll use #The Alpha answer as a basis.
$profile = new \App\Profile(['mobile_no' => $request->input('mobile')]);
$user->profile()->associate($profile); // You can no longer call 'save' here
$user->profile()->save();
The reason for this is you can no longer call save on the belongsTo relation (or any other), this now returns an instance of Illuminate\Database\Query\Builder.
The clean way to do it now would be having on your User Class file:
public function profile()
{
return $this->hasOne(App\Profile::class);
}
and in your User Controller, the following store method:
public function store(Requests\StoreNewUser $request)
{
$user = App\User::create(
$request->only(
[
'first_name',
'last_name',
'email'
]
)
);
$user->password = Illuminate\Support\Facades\Hash::make($request->password);
//or $user->password = bcrypt($request->password);
$user->profile()->create(
[
'mobile_no' => $request->mobile;
]
);
dd($user);
}
I didn know if u were saving plain text password to you database or using a mutator on password attribute, anyhow the suggested above is a good practice I think
Is this Because the $user object is not including relationship by default? If yes Can i create the $user object which includes the associated relations in User Model ?
Yes you should create the relationship, they're not included by default.
In your User model you'd want to do something like this:
public function profile()
{
return $this->hasOne('App\Profile'); // or whatever your namespace is
}
This would also require you to have a Profile model created.
This would definitely answer your questions regarding inserting related models: http://laravel.com/docs/5.1/eloquent-relationships#inserting-related-models
As The Alpha mentioned, and you also eluded to, I think you need to save your user model first then you can add via relationship.

Categories