Using multiple Laravel scopes in OR context

laravel scope with parameter
laravel chain scopes
laravel scope join
laravel scope traits
laravel dynamic scope
eloquent update record
laravel model attributes
laravel scope return

I have a Subscription model which contain start_date and end_date attributes in my Laravel app. I have created two query scopes, scopeActive and scopeFuture to find active and future subscriptions (respectively).

I would like to know how I can build a query using both scopes in OR context, so that I can find any active or future subscriptions.

Subscription Model

/**
 * Scope a query to only include active subscriptions.
 *
 * @param \Illuminate\Database\Eloquent\Builder $query
 * @return \Illuminate\Database\Eloquent\Builder
 */
public function scopeActive($query)
{
    return $query->where('start_date', '<', Carbon::now())
                 ->where('end_date', '>', Carbon::now());
}

/**
 * Scope a query to only include future subscriptions.
 *
 * @param \Illuminate\Database\Eloquent\Builder $query
 * @return \Illuminate\Database\Eloquent\Builder
 */
public function scopeFuture($query)
{
    return $query->where('start_date', '>', Carbon::now());
}


public function business()
{
    return $this->belongsTo('App\Business');
}

Business Model

.....
public function subscriptions()
{
    return $this->hasMany('App\Subscription');
}

User Model

public function business()
{
    return $this->hasOne('App\Business');
}

Controller

Subscription::active()->get();

Try this.

$subscriptions = Subscription::where(function ($query) {
    $query->active();
})->orWhere(function ($query) {
    $query->future();
})->get();

Edit : Example as requested in the comment

$subscriptions = auth()->user()
    ->business()
    ->subscriptions()
    ->where(function ($query) {
        $query->active();
    })->orWhere(function ($query) {
        $query->future();
    })->get();

Use multiple scopes as an "or" kind of filter, not an "and , I've used multiple scopes before to filter a set of results, but it filters use orWhereHas() .. https://github.com/laravel/framework/blob/5.3/src/  I have a Subscription model which contain start_date and end_date attributes in my Laravel app. I have created two query scopes, scopeActive and scopeFuture to find active and future subscriptions (respectively). I would like to know how I can build a query using both scopes in OR context, so that I can find any active or future subscriptions.

I'm not trying to answer, just wanted to lay down an example.

public function scopeVisable(Builder $builder){

    $builder->where(function($builder){
            $builder->orWhere(function($builder){
            $builder->isPublic();
        });
        $builder->orWhere(function($builder){
            $builder->isMine();
        });
    });

    return $builder;
}

public function scopeIsPublic(Builder $builder){

    $builder->whereIsPublic(true);

    return $builder;
}

public function scopeIsMine(Builder $builder){

    $user = app(CurrentUser::class);
    $builder->whereAddedByUserId($user->getKey());

    return $builder;
}

The builder's ->toSql() reveals:

select * from channels where (('is_public' = ?) or ('added_by_user_id' = ?))

Understanding Laravel Scopes, My first real experience with Laravel scopes was in project that I have been Removing multiple global scopes is possible aswell using the  Laravel provides an Eloquent also allows you to define global scopes using Closures, which is particularly useful for simple scopes that do not warrant a separate

Take advantage of params. You could try something like...

public function scopeCanceled($query, $scope = 'where')
{
    return $query->$scope('canceled_at');
}

then you can do for example $query->canceled('orWhere')

you can then de-uglify with:

public function scopeOrCanceled($query)
{
    return $this->scopeCanceled($query, 'orWhere');
}

example $query->orCanceled()

in general with scopes, i find it handy to always have some sort of optional value, to make things flexible

public function scopeApproved($query, bool $value = true)
{
    return $query->where('is_approved', $value);
}

adding a third param for this use case can then make sense

public function scopeApproved($query, string $scope = 'where', bool $value = true) {
    return $query->$scope('is_approved', $value);
}

The magic of query scopes in Laravel - DEV, Use query scopes to split your Eloquent queries in smaller building blocks. Tagged with php, laravel, eloquent, queryscopes. 1); }); // Bonus: if multiple models are hideable, this behaviour might // belong in a specific scope for easy reuse I'll have a look where some more context might be useful. Using Eloquent Query Scopes in Laravel Published: Dec 29, 2019 by C.S. Rhymes If you are writing eloquent queries in your Laravel project and find yourself writing the same logic in your queries over and over again then query scopes might be of use to you.

Subscription::active()->orWhere( function($q){
            return $q->future() ;
        } )->get() ;

Using Eloquent Query Scopes in Laravel, Getting started with Eloquent Query Scopes to simplify your queries and keep If you are writing eloquent queries in your Laravel project and find you have multiple queries throughout your project that use this same logic. Applying conditions to queries gives you the power to retrieve and present filtered data in every imaginable manner. Some of these conditions will be used more than others, and Laravel provides a solution for cleanly packaging these conditions into easily readable and reusable statements, known as query scope.

Using multiple Global Scopes on the same Model in Laravel 5.2 , Hey All,. I have a Quote model with a table column boolean('approved') which I want to use to setup two global scopes for "approved" and "not approved" quotes​  At this point, you might consider spitting your query using query scopes for. By breaking your query into building blocks, it becomes easier to read and reuse. A refactor with query scopes Have a look at the following refactor with query scopes from Laravel:

Eloquent: Getting Started - Laravel, To define a scope, prefix an Eloquent model method with scope . Combining multiple Eloquent model scopes via an or query  Laravel multi (auth) authentication- Today we are going to show you, how to create multi auth system in laravel 7/6. Multiple auth system means multiple users can log in in one application according to roles. Multiple authentications are very important in the large application of laravel. Authentication is the process of recognizing user

Laravel Eloquent Builder Vs Scopes, To allow you to reuse this constraint over multiple models you can boot the model with a global scope, allowing you to do this on multiple  Laravel’s Eloquent ORM comes with this unique set of features called “Scopes” which can be used to re-use some of the query constraints onto all the queries of a certain model. This can be useful to minimize the code while writing the query and is an easy way to make sure every query for a given model receives certain constraints.

Comments
  • Could you provide an example of this when querying Subscriptions from a relationship? e.g. Auth::user()->business->subscriptions()->get();
  • @Imran added example in the answer. Also note use business() and not 'business'. Using it like you are will fetch the business and then get the subscriptions on it, using business() will not however and only the subscriptions get fetched from the database. I've also posted this in your other question.
  • Thanks Sandeesh, however the updated query returns Call to undefined method Illuminate\Database\Query\Builder::subscriptions() error. The relationship is definitely defined in the Business model.
  • Can you share the business relationship on user model and subscriptions relation on your business model. You can add it to your question. I'll check once.
  • @Imran i don't see anything wrong with your relationship. You can also try adding a hasmanythrough relationship to make things simpler. You can add this on user model public function subscriptions() { return $this->hasManyThrough('App\Subscription', 'App\Business'); } and try to fetch subscriptions directly from user model