Adding extra queries to whereHas - laravel-5

I am selecting all the broadcasts that belong to the same organization as the authenticated user, this works perfectly with ->whereHas() but what if i wanted to add a filter to display only the broadcasts where is_published is true.
public static function indexQuery(NovaRequest $request, $query)
{
if (Auth::user()->isAdmin()) {
return $query;
}else{
return $query->whereHas('organizations', function($q){
$q->where('organization_id', Auth::user()->organization_id);
});
}
}
models
public function organizations()
{
return $this->belongsToMany('App\Models\Organization');
}
public function broadcasts()
{
return $this->belongsToMany('App\Models\Broadcast');
}

You can add a query scope to your Broadcast model which will query only broadcasts where is_published is true (This is good for future queries in your application where you need published broadcasts):
Broadcast.php (or model file)
public scopePublished($query)
{
return $query->where('is_published', true);
}
Then in your code, and the ->published() scope to your query:
public static function indexQuery(NovaRequest $request, $query)
{
if (Auth::user()->isAdmin()) {
return $query;
} else {
return $query->published()
->whereHas('organizations', function($q){
$q->where('organization_id', Auth::user()->organization_id);
});
}
}

Related

How would I edit the Laravel Nova indexQuery for a Resource to only show records through multiple relationships?

firstly thank you in advance.
I have the following Models , User , Location, Listing, Offer.
The relationships are:
User Model:
public function location()
{
return $this->hasOne(Location::class);
}
Location Model:
public function listings()
{
return $this->hasMany(Listing::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
Listing Model:
public function offers()
{
return $this->hasMany(Offer::class);
}
public function location()
{
return $this->belongsTo(Location::class);
}
Offer Model:
public function listing()
{
return $this->belongsTo(Listing::class);
}
In my Offer Resourse I would like to show only the offers that belongTo the listings that in turn belongsTo the location that in turn belongTo the authenticated user. I have tried the following.
public static function indexQuery(NovaRequest $request, $query)
{
$user = Auth::user();
if ($user->is_admin === 1){
return $query;
}elseif($user->is_admin === 0) {
return $user->location->listings->offers;
}
}
But get an error Property [offers] does not exist on this collection instance. Any assistance will be greatly appreciated.
I would try something like this.
More information here on querying relationship existence:
https://laravel.com/docs/9.x/eloquent-relationships#querying-relationship-existence
public static function indexQuery(NovaRequest $request, $query) {
$user = Auth::user();
if (!$user->is_admin) {
$query = $query->whereHas('listings.location.user', function ($builder) use ($user) {
return $builder->where('id', $user->id);
});
}
return $query;
}
The reason you are getting the "Property does not exist" error is due to you not pulling it from database.
Two alternative solutions include
Querying them separately: ...->listings()->offers()
Eager loading: ->with(['location.listings.offers']);

How to join 2 collection in query laravel

I have StudentEducation model and in this model i got
public function student_education_countries()
{
return $this->hasMany(StudentEducationCountry::class, 'education_id');
}
and
public function student_education_education_types()
{
return $this->hasMany(StudentEducationEducationType::class, 'education_id');
}
in StudentEducationCountry model i got
public function student_education()
{
return $this->belongsTo(StudentEducation::class, 'education_id');
}
public function student_country()
{
return $this->belongsTo(StudentCountry::class, 'country_id');
}
and in StudentEducationEducationType model i got
public function student_education()
{
return $this->belongsTo(StudentEducation::class, 'education_id');
}
public function student_educationcategory()
{
return $this->belongsTo(StudentEducationcategory::class, 'educationcategory_id');
}
The question is how should i join for to take all educations where country_id is 2 and type is secondary
Simple with whereHas()
$educations = StudentEducation::query()->whereHas('student_education_countries', function (Builder $query) {
$query->where('id', 2);
})->whereHas('student_education_education_types', function (Builder $query) {
//maybe here you need another columns
$query->where('type', 'secondary');
})->get();

Laravel 5.5. Many-to-Many. Receive the latest instance

I have such models (Many-to-Many)
class Driver
{
public function cars()
{
return $this->belongsToMany(Car::class);
}
}
class Car
{
public function drivers()
{
return $this->belongsToMany(Driver::class);
}
}
My Car has activated_at column, that can be null.
How can I retrieve the latest activated car per drivers in a specific parking?
Something like this
Parking::find(2)->drivers()->lastActivatedCars...?
You can just create a scope for the car.
// Car.php
public function scopeActivated($query)
{
return $query->whereNotNull('activated_at')->orderBy('activated_at', 'DESC');
}
And then in your Driver.php:
// Driver.php
public function latestActivatedCar()
{
return $this->cars()->activated()->first();
}
Then you can just:
$latest = $driver->latestActivatedCar();
Or you can create a relationship, so you can eager load.
// Driver.php
public function latestActivatedCar()
{
return $this->belongsToMany(Car::class)
->whereNotNull('activated_at')
->orderBy('activated_at', 'DESC')
->limit(1);
}
Then you can just:
$drivers = Parking::find(2)->drivers;
$drivers->load('latestActivatedCar');
I hope this would help:
Parking::with(['drivers' => function ($driverQuery) {
$driverQuery->with(['cars' => function ($carsQuery) {
$carsQuery->orderBy('activated', 'desc')
->limit(1);
}]);
}])->find(2);

Add a filter function on laravel query builder

I am getting some data from a model like:
public function getExternalCodes()
{
return ExternalService::get()->pluck('add_id')->toArray();
}
Now before this I want to apply a function to filter the data by date:
public function getExternalCodes()
{
$query = ExternalService::get()->pluck('add_id')->toArray();
return $query->filterByDate($query, new ExternalServce);
}
My filter by date function
private function filterByDate(Builder $query, Model $model)
{
if (!request()->has('interval')) {
return $query;
}
$period = json_decode(request()->get('interval'));
if ($period->from) {
$query->where("{$model->getTable()}.created_at", ">=", Carbon::parse($period->from)->startOfDay());
}
if ($period->to) {
$query->where("{$model->getTable()}.created_at", "<=", Carbon::parse($period->to)->endOfDay());
}
return $query;
}
However I can not do it right now since I am calling get() before applying the filter. Any idea how to go about it ?
And yes dont add a question to filter with where since I can not do that
Since you're using Eloquent models, use a local scope for that:
private function scopeFilterByDate($query)
{
....
}
Then use the scope with:
public function getExternalCodes()
{
return ExternalService::filterByDate()->pluck('add_id')->toArray();
}

How to use wherePivot method in a scope?

I have two models with a pivot.
Domain
{
public function projects()
{
return $this->belongsToMany('Project')->withPivot('is_live');
}
}
Project
{
public function domains()
{
return $this->belongsToMany('Domain')->withPivot('is_live');
}
}
Then I try to create the scope "Domains which have Projects and is_live = true" like that Laravel Scope by pivot data values
public function scopeHasLiveProjects($query)
{
$pivotTable = $this->projects()->getTable();
return $query->whereHas('projects', function ($q) use ($pivotTable) {
$q->where($pivotTable . '.is_live', true);
});
}
But how I can use eloquent method wherePivot('is_live', '=', true) in the scope? Is it possible?!
public function scopeHasLiveProjects($query)
{
return $query->whereHas('projects', function ($q) {
$q->where('is_live', true);
});
}
should do the needed

Resources