how can we use with method in laravel with where clause? - laravel

i need only those products where variants size field is tiny. what i should do ? above quering giving me all products but with empty variants
$result=$categories->with([
'products' => function ($product) {
return $product->with([
'variants' => function ($variants) {
return $variants->where('size','tiny');
}
]);
}
])->get();

Change your code like this.
$result=$categories->with([
'products' => function ($product) {
return $product->whereHas(
'variants', function ($variants) {
return $variants->where('size','tiny');
}
]);
}
])->get();

Related

Laravel Using nested with

I couldn't do what I wanted to do with Laravel, actually what I want to do is as follows,
I send getTruck id and list truckHistory with witdh, and I want to pull trukInvoice information with truckHistory invoice_id. But i am getting error where am i doing wrong?
Mysql Connection is as follows.
http://localhost:3000/truck/1
"trucks" table column "plate"
"invoice_details" column "plate_no"
"invoice_details" column "invoice_id"
"invoice" column "id"
Truck Controller
public function getTruck($id)
{
$truck = Truck::find($id)->with([
'truckHistory' => function($query){
// return $query->with(['trukInvoice']);
}
])->first();
return $truck;
}
Truck Model
public function companys()
{
return $this->belongsTo(Contact::class, 'company_id', 'id');
}
public function getCompanyNameAttribute()
{
return $this->companys()->first()->name;
}
public function truckHistory(){
return $this->hasMany(InvoiceDetail::class,'plate_no','plate');
}
public function trukInvoice(){
return $this->belongsTo(Invoice::class,'invoice_id','id');
}
Try this:
$truck = Truck::leftJoin('invoices', 'trucks.invoice_id', 'invoices.id')
->leftJoin('invoice_details', 'trucks.plate_no', 'invoice_details.plate')
->select('*')
->first();
or
$truck = Truck::with(['invoices' => function ($query) {
$query->whereHas('invoice_details', function ($q){
$q->whereNotNull('invoice_details.plate');
});
}])->first();
Check the documentation on restraining eager loads.

Is there a way to add exception for admin when querying with "where" in Laravel?

So i have this query that i am filtering with "where" to display only results assigned to certain user, this is code :
public function showAll()
{
return $this->where('owner_id' , Auth::id())->with([
'contactType:id,name,class',
'owner:id,first_name,last_name',
'CreatedBy:id,first_name,last_name',
'tags:id,name,color_code',
'customFields',
'persons',
'country'
// 'email.type',
// 'phone.type'
]);
Now I want to add exception to admin user with id(1), so that user with ID 1 will have all the results diplsplayed. I have baseuser with isAdmin and ID of 1
Why not simply assign auth ID to a var and the check if it is one?
Something like;
public function showAll()
{
$query = $this->with([
'contactType:id,name,class',
'owner:id,first_name,last_name',
'CreatedBy:id,first_name,last_name',
'tags:id,name,color_code',
'customFields',
'persons',
'country'
]);
$authId = Auth::id();
if (1 !== $authId) {
$query->where('owner_id' , $authId);
}
return $query;
}
You want to use when(). You only add the query inside when the condition is true.
return $this->when(!$isAdmin, function($query) {
$query->where('owner_id' , Auth::id());
})
->with([
'contactType:id,name,class',
'owner:id,first_name,last_name',
'CreatedBy:id,first_name,last_name',
'tags:id,name,color_code',
'customFields',
'persons',
'country'
// 'email.type',
// 'phone.type'
]);
Above, it will only add where() to the query when !$isAdmin is true i.e. $isAdmin is false.

Laravel - Get array with relationship

I have an ajax call that returns an array:
$reports = Report::where('submission_id', $submissionID)
->where('status', 'pending')
->get(['description','rule']);
return [
'message' => 'Success.',
'reports' => $reports,
];
From this array, I only want to return the fields 'description' and 'rule'. However I also want to return the owner() relationship from the Report model. How could I do this? Do I have to load the relationship and do some kind of array push, or is there a more elegant solution?
You can use with() to eager load related model
$reports = Report::with('owner')
->where('submission_id', $submissionID)
->where('status', 'pending')
->get(['id','description','rule']);
Note you need to include id in get() from report model to map (owner) related model
you will have probably one to many relationship with Reports and owners table like below
Report Model
public function owner() {
return $this->belongsTo('App\Owner');
}
Owner Model
public function reports() {
return $this->hasMany('App\Report');
}
your controller code
$reports = Report::with('owner')->
where('submission_id', $submissionID)->where('status', 'pending')->get()
return [
'message' => 'Success.',
'reports' => $reports,
];
This is what I ended up going with:
$reports = Report::
with(['owner' => function($q)
{
$q->select('username', 'id');
}])
->where('submission_id', $submissionID)
->where('status', 'pending')
->select('description', 'rule','created_by')
->get();
The other answers were right, I needed to load in the ID of the user. But I had to use a function for it to work.

laravel collection nested query

I'm new with laravel collection . i just want to make this query with collection
DB::select(SELECT id, user_id, created_at,latitude,longitude
FROM coordinates
WHERE created_at IN (
SELECT MAX(created_at)
FROM coordinates
GROUP BY user_id));
according to the document https://laravel.com/docs/6.x/collections
this what i did and it gives me all the data
$this->data['information'] = collect($response->json()['items']);
Edit:
simply i need to produce that query (that i mentioned above) by using Collection.
This is the contents of $response->json()['items']
"#items: array:17 [▼ 0 => array:9 [▼ "id" => 977777779 "platform_id" => "msaeed" "platform_type" => 1 "status" => 1 "longitude" => 1.1 "latitude" => 1.1 "created_by" => "NMF" "created_at" => "2019-10-27T21:00:00Z" "updated_at" => "2019-10-28T07:58:36Z""
any help would be appreciated
Here is the query.
$data = collect($response->json()['items']);
$data = $data->whereIn('created_at', $data->sortByDesc('created_at')
->groupBy('user_id')
->pluck('0.created_at'))
->onlyKeys(['id', 'user_id', 'created_at', 'latitude', 'longitude']);
The equivalent for the subquery:
SELECT MAX(created_at)
FROM coordinates
GROUP BY user_id
is
$data->sortByDesc('created_at') // we use sortByDesc to produce the same result as `MAX`.
->groupBy('user_id')
->pluck('0.created_at') // then to get the max value, just get the first array after grouping.
To achieve the select statement, we need to create a little macro, i've named it onlyKeys:
use Illuminate\Support\Arr;
Collection::macro('onlyKeys', function ($keys) {
return $this->map(function ($value) use ($keys) {
$tmpValue = (array) $value;
if (is_array($tmpValue)) {
$value = Arr::only($tmpValue, $keys);
}
return $value;
});
});
You can register the macro in your AppServiceProvider.php.
PS. Why you need to querying using Collection? Is that data not come from DB?
You want to collect array recursive
Unfortunately laravel does not have this feature:
you can write it on your own.
if you have helpers file you can write this method:
function recursive_collect($array){
foreach ($array as $key => $value) {
if (is_array($value)) {
$value = recursive_collect($value);
$array[$key] = $value;
}
}
return collect($array);
}
Or You can implement macro in your AppServiceProvider:
\Illuminate\Support\Collection::macro('recursive', function () {
return $this->map(function ($value) {
if (is_array($value) || is_object($value)) {
return collect($value)->recursive();
}
return $value;
});
});
Hope this helps you

backpack crud filters by pivot table

PLease, somebody, help me with filters.
I have 3 tables: complaint, frontend_tag, frontendtags_complaints
I heed to filter complaints by frontend_tag
here is my filter code:
$this->crud->addFilter([
'name' => 'frontendtags',
'type' => 'select2',
'label'=> 'FE Tag'
], function() {
return \App\Models\FrontendTags::all()->pluck('name', 'id')->toArray();
}, function($value) {
return $this->crud->query->whereHas('frontendtags', function ($q) use ($value) {
$q->where('tag_id', $value);
});
});
here is my relation code:
public function frontendtags()
{
return $this->belongsToMany('App\Models\FrontendTags', 'frontendtags_complaints', 'complaint_id', 'tag_id');
}
The filter is not working.
Replace
$q->where('tag_id', $value);
With
$q->where('frontend_tag.id', $value);
The where condition is applied on the related table, in this case frontend_tag.

Resources