Laravel cannot use where on a table connected using belongsToMangy - laravel

I have the following model file which has a belongsToMany relation with the portal_users table.
class Role extends Model
{
use HasFactory;
protected $table = 'portal_roles';
protected $hidden = array('created_at', 'updated_at','deleted_at');
public function users()
{
return $this->belongsToMany(User::class, 'portal_user_roles');
}
}
I am trying to find details of all the users that fits into a particular role using the following query
$recordobj = Role::find(15)->users->where('firstname', 'like', '%' . $searchstring . '%')->get()->keyBy('id');
It is returning empty resultset even though there are users who is having the role id as 15. Can anyone please tell me what is the problem here?

Change users to users():
$recordobj = Role::find(15)->users()->where('firstname', 'like', '%' . $searchstring . '%')->get()->keyBy('id');

Related

find() and delete() not working in laravel 9

find()
This is correct:
$user = Users::where('userid', '=', $id)->get();
return redirect('/register/view');
This is Incorrect:
$user = Users::find($id);
return redirect('/register/view');
delete()
This is Correct:
$user = Users::where('userid', '=', $id)->get();
if(!is_null($user))
{
Users::where('userid', '=', $id)->delete();
}
return redirect('/register/view');
This is Incorrect:
$user = Users::where('userid', '=', $id)->get();
if(!is_null($user))
{
$user->delete();
}
return redirect('/register/view');
Users Modedl:
class Users extends Model
{
use HasFactory;
protected $table = 'users';
protected $primarykey = 'userid';
}
Both codes are correct but not in my case. i don't know why. can anyone tell me what is wrong.
If you're looking for a single record by id (or userid in your case), don't use ->get():
$user = User::where('userid', $id)->first();
// OR
$user = User::find($id);
When deleting, also don't use ->get(). is_null on the result of ->get() will always be false, since ->get() returns a Collection, which isn't null.
$user = User::where('userid', $id)->delete();
// OR
$user = User::findOrFail($id)->delete();
Note: Your Model should be User, and the property to set the primary key in the Database is primaryKey, not primarykey:
class User extends Model {
use HasFactory;
protected $table = 'users';
protected $primaryKey = 'userid';
}
You're misunderstanding and misusing Laravel a lot here. ->get() should never be used for a single record, model names are singular, casing matters, etc etc.

issue in laravel relationship search data

I want to search for usernames from the user's table.
I have used the Laravel relationship(eloquent). I don't search for usernames from users' tables. My code is Below and here I Explain the relationship with All Tablets
I have a query write inside the group controller
public function getGroupsData(Request $request){
$group = Group::with(['memberscount', 'getusername'])->where('groupName', "like", "%" . $request->searchText . "%")
->whereHas('getusername.user', function ($query) use ($request) {
return $query->where('name', 'like', '%'. $request->searchText . '%');
})
->get();
}
memberscount and getusername relationship write-in group model my group model is below
class Group extends Model
{
public function memberscount(){
return $this->hasMany('App\Models\Members', 'group_id', 'id')->where('memberStatus', 'Joined');
}
public function getusername(){
return $this->hasOne('App\Models\Members', 'group_id', 'id')->where('isOwner', 0);
}
}
And user's table relationship in members models. members model is below
class Members extends Model
{
public function user(){
return $this->hasOne('App\User', 'id', 'user_id');
}
/**get group name */
public function group(){
return $this->hasOne('App\Models\Group', 'id', 'group_id');
}
}
I have search user's data this(user) relationship. But I can't search data in a multilevel relationship.
OK, I'm the first step is to rename name relationships in class Group
I think it was more logical names
memberscount -> members
getusername -> owner
And the second step is to search. I write like this:
$group = Group::whereHas('owner', function ($query) use ($request) {
return $query->where('groupName', 'like', '%'. $request->searchText . '%');
})->get();
or more effective and clear code we can save in scope us query like that:
$group = Group::whereHas('owner', function ($query) use ($request) {
return $query->haveGroupName($request->searchText);
})->get();
In the Group model class write code like that:
/**
* Scope a query to only have groupName.
*
* #param \Illuminate\Database\Eloquent\Builder $query
* #param string $param
* #return \Illuminate\Database\Eloquent\Builder
*/
public function scopeHaveGroupName($query, $param)
{
return $query->where('groupName', 'like', '%' . $param . '%');
}

Laravel relationship many to many filtering on pivot field

I have a relationship between Invoice and Shift.
Invoice model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Invoice extends Model
{
public $primaryKey = 'id';
protected $fillable = [
'user_id',
'date_ins',
'closeco',
'closedrh',
'lvl',
'new',
];
public function user()
{
return $this->hasOne(User::class,'id','user_id');
}
/**
* The roles that belong to the invoice.
*/
public function shifts()
{
return $this->belongsToMany(Shift::class, 'invoice_shift')
->withPivot([
'invoice_id', 'shift_id', 'shift_taken_id', 'shift_swapped_date', 'shift_taken_date', 'tas',
'status_tas', 'status_co', 'status_drh', 'back_co',
'msg', 'msg_co', 'msg_drh'
])
->orderBy('status_drh', 'ASC')
->orderBy('status_co', 'ASC');
}
}
Shift model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Shift extends Model
{
public $primaryKey = 'id';
protected $fillable = [
'code',
'description',
];
/**
* The users that belong to the role.
*/
public function invoices()
{
return $this->belongsToMany(Invoice::class, 'invoice_shift')
->orderBy('status_drh', 'ASC')
->orderBy('status_co', 'ASC');
}
}
So I have a pivot table called Invoice_shift.
I cannot extract, starting from invoices table, just invoices that have tas (in invoice_shift table) = current logged user.
I cannot filter as a static value in Invoice model definition with wherepivot because it is dynamic value, every time logged user id is different.
I tried to do this in controller
$invoices = Invoice::with('shifts.invoices')
->orderBy('date_ins', 'DESC')->get();
$filter = $invoices->shifts()
->wherePivot('tas', '=', $user_id)
->get();
but I get an error because I think invoices are a collection ... I tried to insert a foreach...but it doesn't work.
The error message:
Method Illuminate\Database\Eloquent\Collection::shifts does not exist
How can I do this?
Thanks
$invoices is an instance of Illuminate\Database\Eloquent\Collection and therefore relationship shifts() cannot be used..
Maybe you need the correct Eloquent builder to filter invoices using whereHas("relationship", fn)
$filteredInvoices = Invoice::with('shifts.invoices')
->whereHas("shifts", function($query) use ($user_id) {
$query->wherePivot('tas', $user_id)
})
->orderBy('date_ins', 'DESC')
->get();

Laravel Eloquent How Can I Select Using Condition "where" for pivot table

I have three database tables called user(id,name), group(id,name) and user_group(user_id, group_id,valid_before) with relations many to many.
class User extends Model
{
protected $table = 'user';
public function groups()
{
return $this->belongsToMany(Group::class, 'user_group')
->withPivot('valid_before');
}
}
class Group extends Model
{
protected $table = 'group';
public $timestamps = false;
public function user()
{
return $this->belongsToMany(User::class, 'user_group');
}
}
How can I select all users (using Eloquent) who have
valid_before < $some_date
?
There are many ways to achieve this goal. I'll show you an example using query scopes.
In your User class you have to make a little update:
class User extends Model
{
protected $table = 'user';
public function groups()
{
return $this->belongsToMany(Group::class, 'user_group')
//->withPivot('valid_before'); <-- Remove this
}
}
and create a scope in your Group model:
class Group extends Model
{
protected $table = 'group';
public $timestamps = false;
public function user()
{
return $this->belongsToMany(User::class, 'user_group');
}
/**
* This scope gets as input the date you want to query and returns the users collection
*
* #param \Illuminate\Database\Eloquent\Builder $query
* #param string $date
* #return \Illuminate\Database\Eloquent\Builder
*/
public function scopeUsersValidBefore($query, $date)
{
return $query->users()->wherePivot('valid_before', '<', $date);
}
}
Now, I imagine you have a GroupController that somewhere creates a query to retrieve the valid before users. Something like:
// [...]
$users = Group::usersValidBefore($yourDate)->get();
// [...]
If you want to create the query from the other side, I mean you want to use the User model and list all the Users that has a pivot relation with valid_before populated, than the right approach is creating a UserGroup intermediate model that can be easily used to create a query.
If you are using Laravel 8.x.x
It's much easier with Inline Relationship Existence Queries
If you would like to query for a relationship's existence with a single, simple where condition attached to the relationship query, you may find it more convenient to use the whereRelation and whereMorphRelation methods. For example, we may query for all posts that have unapproved comments:
use App\Models\Post;
$posts = Post::whereRelation('comments', 'is_approved', false)->get();
Of course, like calls to the query builder's where method, you may also specify an operator:
$posts = Post::whereRelation(
'comments', 'created_at', '>=', now()->subHour()
)->get();

Laravel Eloquent how to override the base query?

I have 2 models shared a same table.
Table name: books, I separate normal book & novel by an attribute called type
Book model
class Book extends \Illuminate\Database\Eloquent\Model
{
protected $table = 'books';
}
Novel model
class Novel extends Book
{
protected $table = 'books';
// Is such a method available?
protected function someMethodToOverride()
{
$this->where('type', 'novel');
}
}
What I want to achieve here is
$results = Novel::where('title', 'LIKE', '%' . $title . '%')->get();
from this query, I want it to pre-set the condition
where('type', 'novel')
Is there any function I can override to achieve this?
use Anonymous Global Scopes and add this boot method in Novel Model
protected static function boot()
{
parent::boot();
static::addGlobalScope('type', function (\Illuminate\Database\Eloquent\Builder $builder) {
$builder->where('type', 'novel');
});
}
now it will automatically add query
$results = Novel::where('title', 'LIKE', '%' . $title . '%')->get();
now If you would like to remove a global scope for a given query, you
may use the withoutGlobalScope method.
Novel::withoutGlobalScope('type')->get();
for more information read this article
In Model You can use scope:
public function scopeOfType($query, $type)
{
return $query->where('type', $type);
}
And pass the parameters when calling the scope:
Model::ofType('novel')
->where('title', 'LIKE', '%' . $title . '%')
->get();
refer link Laravel Scope

Resources