How to get related collection in model in Laravel4 - laravel

Suppose I have a model called User where several relations are defined (role and permissions). How can I get directly in my User model related role collection or related permissions collection ?
What I am trying to do :
controller:
if (Auth::user()->hasPermission('test'))
{ // code goes here}
and my model:
public function hasPermission($name)
{
$permission = \Permission::where('name', '=', $name)->get();
$list = ($this->overwrite_permission) ? $this->permissions : $this->role->permissions;
//here I want to have a collection to use contains()
if ($list->contains($permission))
{
return true;
}
return false;
}

You can do this instead of checking collection:
public function hasPermission($name)
{
return ($this->overwrite_permission)
? (bool) $this->permissions()->whereName($name)->first()
: (bool) $this->role->permissions()->whereName($name)->first();
}
First() will fetch the permission model if it's in the related permissions (to the user or the role appropriately) or return null, thus casting to boolean will do the job.
If you want to use your code anyway, this is the line to change:
// it returns Collection, while you need Model (or its id) for contains() method
$permission = \Permission::where('name', '=', $name)->get();
// change to:
$permission = \Permission::where('name', '=', $name)->first();
Rest of the code is ok, $list is indeed a Collection (unless you have not setup relations to permissions correctly)

Related

How to use custom model function in eloquent

I want to get all user's online friends, how can I call a custom model function inside the eloquent condition?
this is my code
$friends = $user->friends()->where(function (Builder $query){
$query->where('friend', 'yes');
})
->get();
and this is my function in model
public function getIsOnlineAttribute(): bool
{
// check if the user is online or not
return $this->is_online;
}
I can access is_online after eloquent by foreach, but in my case, I want to check everything in one step ( inside where condition in eloquent). how can I do that???
You can't use conditions for eloquent accessors, in this case you can use (assume 1 is database column value):
$friends = $user->friends()->where('is_online', 1)->get();
or
$friends = $user->friends()->whereIsOnline(1)->get();
or you can create eloquent scope on your model:
public function scopeIsOnline($query) {
$query->where('is_online',1);
}
and you can use this eloquent scope on your controller in this way:
$friends = $user->friends()->isOnline()->get();
this worked for me :)
$friends = $user->friends()
->simplePaginate()
->reject(function ($friend) {
return $friend->is_online === false;
});

Trying to count record by user id

I am trying to get record by user id.This is working for login user .
But I am Trying to get details for all users .Not only.
Here is model
public function referrer()
{
return $this->belongsTo('App\User', 'referred_by');
}
public function referrals()
{
return $this->hasMany('App\User', 'referred_by');
}
Now I am Getting refferals no from this code.
$referrals=auth()->user()->referrals()->count();
BUt I am Nedd to get same result for every user listing ..
means I need to change this query.by user_id.
This case you must be use withCount() method
$users = User::withCount('referrals')->get();
foreach ($users as $user) {
dd($user->referrals_count);
}
Pass the user_id to an eloquent query
$user_id = request()->get('id'); // Your user_id here
$referrals_count = \App\User::find($user_id)->referrals()->count();
Hope this helps

Error : Method Illuminate\Database\Eloquent\Collection::StudentInfo does not exist. (Laravel 5.6)

I am new to make join tables with Eloquent. I want to join 3 tables. But it shows me error. What's my mistake, if anyone notice it will be helpful for me. Here is tables....
In 1st table Applications(id,u_id,program_name) 2nd table StudentInfos(id,u_id,.....) 3rd table users(id,.....)
in Application model
public function StudentInfo()
{
return $this->hasOne('App\StudentInfo', 'u_id', 'u_id');
}
in StudentInfo model
public function User()
{
return $this->hasOne('App\user', 'u_id', 'id');
}
From controller
public function view_application($id)
{
$vu_data = Application::where('id', $id)->get();
$vu_data2 = $vu_data->StudentInfo()->get();
return $vu_data2;
}
$vu_data2 = $vu_data->StudentInfo()->get();
is returning a collection and not just a single Application Model. Change "get()" to "first()", and this will fix your first error. So change:
$vu_data = Application::where('id', $id)->get();
to
$vu_data = Application::where('id', $id)->first();
When you do get(), it returns a collection. You can do :
$vu_data = Application::findOrFail($id);
$student = $vu_data->StudentInfo;
$user = $student->User;

Laravel oneToMany accessor usage in eloquent and datatables

On my User model I have the following:
public function isOnline()
{
return $this->hasMany('App\Accounting', 'userid')->select('rtype')->latest('ts');
}
The accounting table has activity records and I'd like this to return the latest value for field 'rtype' for a userid when used.
In my controller I am doing the following:
$builder = App\User::query()
->select(...fields I want...)
->with('isOnline')
->ofType($realm);
return $datatables->eloquent($builder)
->addColumn('info', function ($user) {
return $user->isOnline;
}
})
However I don't get the value of 'rtype' for the users in the table and no errors.
It looks like you're not defining your relationship correctly. Your isOnline method creates a HasMany relation but runs the select method and then the latest method on it, which will end up returning a Builder object.
The correct approach is to only return the HasMany object from your method and it will be treated as a relation.
public function accounts()
{
return $this->hasMany('App\Accounting', 'userid');
}
Then if you want an isOnline helper method in your App\User class you can add one like this:
public function isOnline()
{
// This gives you a collection of \App\Accounting objects
$usersAccounts = $this->accounts;
// Do something with the user's accounts, e.g. grab the last "account"
$lastAccount = $usersAccounts->last();
if ($lastAccount) {
// If we found an account, return the rtype column
return $lastAccount->rtype;
}
// Return something else
return false;
}
Then in your controller you can eager load the relationship:
$users = User::with('accounts')->get(['field_one', 'field_two]);
Then you can do whatever you want with each App\User object, such as calling the isOnline method.
Edit
After some further digging, it seems to be the select on your relationship that is causing the problem. I did a similar thing in one of my own projects and found that no results were returned for my relation. Adding latest seemed to work alright though.
So you should remove the select part at very least in your relation definition. When you only want to retrieve certain fields when eager loading your relation you should be able to specify them when using with like this:
// Should bring back Accounting instances ONLY with rtype field present
User::with('accounts:rtype');
This is the case for Laravel 5.5 at least, I am not sure about previous versions. See here for more information, under the heading labelled Eager Loading Specific Columns
Thanks Jonathon
USER MODEL
public function accounting()
{
return $this->hasMany('App\Accounting', 'userid', 'userid');
}
public function isOnline()
{
$rtype = $this->accounting()
->latest('ts')
->limit(1)
->pluck('rtype')
->first();
if ($rtype == 'Alive') {
return true;
}
return false;
}
CONTROLLER
$builder = App\User::with('accounting:rtype')->ofType($filterRealm);
return $datatables->eloquent($builder)
->addColumn('info', function (App\User $user) {
/*
THIS HAS BEEN SUCCINCTLY TRIMMED TO BE AS RELEVANT AS POSSIBLE.
ARRAY IS USED AS OTHER VALUES ARE ADDED, JUST NOT SHOWN HERE
*/
$info[];
if ($user->isOnline()) {
$info[] = 'Online';
} else {
$info[] = 'Offline';
}
return implode(' ', $info);
})->make();

Call to undefined method Illuminate\Database\Query\Builder::intersect()

I want to make Laravel Authorization using gate..Where In user model
User.php
public function hasPermission($name)
{
$permission = Permission::where('name','=', $name)->first();
$permissions = \DB::table('role_permission')
->join('permissions', 'permissions.id', '=', 'role_permission.permission_id')
->select('role_permission.*')
->where('role_permission.permission_id', '=',$permission->id)
->get();
if(! $permissions) {
return false;
}
return !! $permission->intersect($this->$permission)->count();
}
In AuthserviceProvider
public function boot(GateContract $gate)
{
$this->registerPolicies($gate);
$gate->before(function($user, $ability) {
return $user->hasPermission($ability);
});
}
My Table structure like.
User has name,email,password,id
permission has name,id
role has name,id
role_permission has role_id,permission_id
can anyone help me to find out what's the error here?
intersect method belongs to Collection class. You can't use intersect method on Model. You may try by:
return !! collect([$permission])->intersect($this->$permission)->count();
$this->$permission should be an array or collection
I guess that's because you can apply intersect to a collection, while you're getting an error saying you that you're calling it over Illuminate\Database\Query\Builder.
I see you're calling it on $permission, that's currently a record (a model) of Permission. Probably that's just a typo, and you want to use $permissions instead of $permission.
Anyway, try to explain better what's the behaviour you're looking for, because it's not clear.

Resources