Provides a Eloquent query builder for Laravel or Lumen

Overview

Provides a Eloquent query builder for Laravel or Lumen

alt text

Build Status Coverage Status Test Status Code Style Status Total Downloads License

This package allows you to build eloquent queries, based on request parameters. It greatly reduces the complexity of the queries and conditions, which will make your code clean and maintainable.

Basic Usage

Suppose you want to get the list of the users with the requested parameters as follows:

//Get api/user/search?age_more_than=25&gender=male&has_published_post=true
[
    'age_more_than'  => '25',
    'gender'         => 'male',
    'has_published_post' => 'true',
]

In a common implementation, following code will be expected:



namespace App\Http\Controllers;

use App\User;
use Illuminate\Http\Request;

class UserController extends Controller
{
    public function index(Request $request)
    {
        $users = User::where('is_active', true);

        if ($request->has('age_more_than')) {
            $users->where('age', '>', $request->age_more_than);
        }

        if ($request->has('gender')) {
            $users->where('gender', $request->gender);
        }

        // A User model may have an infinite numbers of Post(One-To-Many).
        if ($request->has('has_published_post')) {
            $users->where(function ($query) use ($request) {
                $query->whereHas('posts', function ($query) use ($request) {
                    $query->where('is_published', $request->has_published_post);
                });
            });
        }

        return $users->get();
    }
}

But after using the EloquentBuilder, the above code will turns into this:



namespace App\Http\Controllers;

use App\User;
use EloquentBuilder;
use Illuminate\Http\Request;

class UserController extends Controller
{
    public function index(Request $request)
    {
        $users = EloquentBuilder::to(User::class, $request->all());

        return $users->get();
    }
}

You just need to define a filter for each parameter that you want to add to the query.

Installation

Laravel

You can install the package via composer:

composer require mohammad-fouladgar/eloquent-builder

Laravel 5.5 uses Package Auto-Discovery, so you are not required to add ServiceProvider manually.

Lumen

You can install the package via composer:

composer require mohammad-fouladgar/eloquent-builder

For Lumen, add the LumenServiceProvider to the bootstrap/app.php file

/*
|--------------------------------------------------------------------------
| Register Service Providers...
|--------------------------------------------------------------------------
*/

$app->register(\Fouladgar\EloquentBuilder\LumenServiceProvider::class);

For using the facade you have to uncomment the line $app->withFacades(); in the bootstrap/app.php file

After uncommenting this line you have the EloquentBuilder facade enabled

$app->withFacades();

Publish the configuration file

php artisan eloquent-builder:publish

and add the configuration to the bootstrap/app.php file

$app->configure('eloquent-builder');
...
$app->register(\Fouladgar\EloquentBuilder\LumenServiceProvider::class);

Important : this needs to be before the registration of the service provider.

Filters Namespace

The default namespace for all filters is App\EloquentFilters with the base name of the Model. For example, the filters namespace will be App\EloquentFilters\User for the User model:

├── app
├── Console
│   └── Kernel.php
├── EloquentFilters
│   └── User
│       ├── AgeMoreThanFilter.php
│       └── GenderFilter.php
└── Exceptions
    └── Handler.php

Customize via Config file

You can optionally publish the config file with:

php artisan vendor:publish --provider="Fouladgar\EloquentBuilder\ServiceProvider" --tag="config"

And set the namespace for your model filters which will reside in:

return [
    /*
     |--------------------------------------------------------------------------
     | Eloquent Filter Settings
     |--------------------------------------------------------------------------
     |
     | This is the namespace all you Eloquent Model Filters will reside
     |
     */
    'namespace' => 'App\\EloquentFilters\\',
];

Customize per domain/module

When you have a laravel project with custom directory structure, you might need to have multiple filters in multiple directories. For this purpose, you can use setFilterNamespace() method and pass the desired namespace to it.

For example, let's assume you have a project which implement a domain based structure:

.
├── app
├── bootstrap
├── config
├── database
├── Domains
│   ├── Store
│   │   ├── database
│   │   │   └── migrations
│   │   ├── src
│   │       ├── Filters // we put our Store domain filters here!
│   │       │   └── StoreFilter.php
│   │       ├── Entities
│   │       ├── Http
│   │          └── Controllers
│   │       ├── routes
│   │       └── Services
│   ├── User
│   │   ├── database
│   │   │   └── migrations
│   │   ├── src
│   │       ├── Filters // we put our User domain filters here!
│   │       │   └── UserFilter.php
│   │       ├── Entities
│   │       ├── Http
│   │          └── Controllers
│   │       ├── routes
│   │       └── Services
...

In the above example, each domain has its own filters directory. So we can set and use filters custom namespace as following:

$stores = EloquentBuilder::setFilterNamespace('Domains\\Store\\Filters')
                        ->to(\Domains\Entities\Store::class, $filters)->get();

Note: When using setFilterNamespace(), default namespace and config file will be ignored.

Define a Filter

Writing a filter is simple. Define a class that extends the Fouladgar\EloquentBuilder\Support\Foundation\Contracts\Filter abstract class. This class requires you to implement one method: apply. The apply method may add where constraints to the query as needed. Each filter class should be suffixed with the word Filter.

For example, take a look at the filter defined below:



namespace App\EloquentFilters\User;

use Fouladgar\EloquentBuilder\Support\Foundation\Contracts\Filter;
use Illuminate\Database\Eloquent\Builder;

class AgeMoreThanFilter extends Filter
{
    /**
     * Apply the age condition to the query.
     *
     * @param Builder $builder
     * @param mixed   $value
     *
     * @return Builder
     */
    public function apply(Builder $builder, $value): Builder
    {
        return $builder->where('age', '>', $value);
    }
}

Tip: Also, you can easily use local scopes in your filter. Because they are instance of the query builder.

Define filter[s] by artisan command

If you want to create a filter easily, you can use eloquent-builder:make artisan command. This command will accept at least two arguments which are Model and Filter:

php artisan eloquent-builder:make user age_more_than

There is also a possibility of creating multiple filters at the same time. To achieve this goal, you should pass multiple names to Filter argument:

php artisan eloquent-builder:make user age_more_than gender

Use a filter

You can use filters in multiple approaches:



// Use by a model class name
$users = EloquentBuilder::to(\App\User::class, request()->all())->get();

// Use by existing query
$query = \App\User::where('is_active', true);
$users = EloquentBuilder::to($query, request()->all())->where('city', 'london')->get();

// Use by instance of a model
$users = EloquentBuilder::to(new \App\User(), request()->filter)->get();

Tip: It's recommended to put your query params inside a filter key as below:

user/search?filter[age_more_than]=25&filter[gender]=male

And then use them this way: request()->filter.

Authorizing Filter

The filter class also contains an authorize method. Within this method, you may check if the authenticated user actually has the authority to apply a given filter. For example, you may determine if a user has a premium account, can apply the StatusFilter to get listing the online or offline people:

/**
 * Determine if the user is authorized to make this filter.
 *
 * @return bool
 */
 public function authorize(): bool
 {
     if(auth()->user()->hasPremiumAccount()){
        return true;
     }

    return false;
 }

By default, you do not need to implement the authorize method and the filter applies to your query builder. If the authorize method returns false, a HTTP response with a 403 status code will automatically be returned.

Ignore Filters on null value

Filter parameters are ignored if contain empty or null values.

Suppose you have a request something like this:

//Get api/user/search?filter[name]&filter[gender]=null&filter[age_more_than]=''&filter[published_post]=true

EloquentBuilder::to(User::class, $request->filter);

// filters result will be:
$filters = [
    'published_post' => true
];

Only the "published_post" filter will be applied on your query.

Use as Dependency Injection

You may need to use the EloquentBuilder as DependencyInjection in a construct or a function method.

Suppose you have an UserController and you want get a list of the users with applying some filters on them:



namespace App\Controllers;

use App\Models\User;
use App\Http\Resources\UserResource;
use Fouladgar\EloquentBuilder\EloquentBuilder as Builder;
use Fouladgar\EloquentBuilder\Exceptions\NotFoundFilterException;
use Illuminate\Http\Request;

class UserController
{
    public function index(Request $request, User $user, Builder $builder)
    {
        $users = $user->newQuery()->where('is_active', true);
        try {
            $builder->to($users, $request->filter);
        } catch (NotFoundFilterException $filterException) {
            //...
        }

        return UserResource::collection($users->get());
    }
}

That's it.

Testing

composer test

Contributing

Please see CONTRIBUTING for details.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

License

Eloquent-Builder is released under the MIT License. See the bundled LICENSE file for details.

Built with ❤️ for you.

Comments
  • کارکرد نادرست برای محدوده قیمت

    کارکرد نادرست برای محدوده قیمت

    سلام همه چیز رعایت شده و بدون ارور انجام میشه ولی شرط رعایت نمیشه و به درستی اعمال نمیشه

    controller $files = EloquentBuilder::to(File::class, $request->all())->orderBy('id','desc')->paginate(2);

    filter

    class GheymatkolMoreThanFilter extends Filter
    {
        public function apply(Builder $builder, $value): Builder
        {
            return $builder->where('gheymatkol', '>', $value);
        }
    }
    

    view input <input type="text" class="form-control" id="gheymataz" name="gheymatkol_more_than">

    opened by shayanes777 12
  • How to ignore entries present in the filter URL?

    How to ignore entries present in the filter URL?

    Hello! The tool you developed is incredible. Congrats on the job!

    Now how can I ignore some variables in the entry of my URL?

    For example, the number 1 in the image below shows the filters that are needed. The parameters of item 2 are only required to display some items in the PDF. That is, these parameters are used as flags (true or false).

    image

    Is it possible to do that?

    My URL:

    //Get /filter?year=2019&identification=9999&city_id=1&institution_id=4&movement_status=on&origin_resource=Com+emenda
    [
        'year'  => '2019',
        'identification' => '9999',
        'city_id' => '1',
        'institution_id' => '4',
    
        // I want to ignore...
        'movement_status' => 'on',
        'origin_resource' => 'Com emenda'
    ]
    
    opened by ronaldaraujo 8
  • Question: Polymorphic Relationship Example

    Question: Polymorphic Relationship Example

    This package looks amazing, I haven't fully played with it too much but wanted to ask about polymorphic relationships.

    Lets say I have Pages, Posts, and Comments. I want to make an API end point for comments that can pull the comments for a specific page or post with additional filters.

    Is the recommended method to be similar to: https://github.com/mohammad-fouladgar/eloquent-builder/issues/28#issuecomment-516116144

    Where if I have two filters: polymorphic_type and polymorphic_key I should do something like this in my comments controller, or would there be a better way?

    (Code may not actually work; just trying to figure out the best way to go about this)

    //API\Comments.php
    public function index(Request $request)
    {
        $filters = $request->get('filters');
        if(isset($filters['polymorphic_type']) && isset($filters['polymorphic_key'])) {
            $polymorphic = (new $filters['polymorphic_type'])->findOrFail($filters['polymorphic_key');
            $comments = $polymorphic->comments()->getQuery();
        }else{
            $comments = Comment::class;
        }
    
        $result = EloquentBuilder::to(
                    $comments, 
                    $request->all('filters')
        )->paginate(10);
        return response()->json($result);
    }
    
    opened by sniper7kills 7
  • How to use search between dates?

    How to use search between dates?

    Congratulations on this beautiful package.

    I have a dt_start column of type date, in the form I have the inputs from_date and to_date, in the url displays /called?from_date=2020-07-09&to_date=2020-07-23 But it shows the error Not found the filter: FromDateFilter, for not having the FromDate filter, of course. I created a DtStart filter.

    public function apply(Builder $builder, $fromDate): Builder
    {
        return $builder->whereBetween('dt_start', [$fromDate, $fromDate]);
    }
    

    So, how do I get these two parameters?

    bug 
    opened by multiarts 6
  • Select Not Working

    Select Not Working

    Sorry, i am not speak english. I'm using a translate. My question is that when I use select the 'bakiye' column does not appear in the BalanceFilter function. Ekran Resmi 2019-11-06 19 57 07

    Ekran Resmi 2019-11-06 19 59 54 Ekran Resmi 2019-11-06 19 58 58
    opened by muhammedkaraoglu 5
  • Filtering HasManyThrough

    Filtering HasManyThrough

    Hello @mohammad-fouladgar ,

    Thank you for the fantastic job done so far. I ran into an issue this afternoon trying to filter a has many through relationship.

    So I have a project that has applications through another table (roles) and I am trying to filter the applications based on some fields.

    Originally I can just do $applications = $project->find(1)->applications()->paginate(10) to fetch the paginated result of all the applications that belongs to that project.

    But I want to apply some filtering like by dates, status, etc. I thought I could do

    ` $applications = $project->applications()->with(['profile']);

    $result = EloquentBuilder::to($applications, request()->all('filters'))->paginate(10); `

    The above code produces an error. See attached screenshot. Maybe I am doing something wrong. Screenshot 2019-07-27 at 6 14 53 PM

    help wanted 
    opened by joefazee 5
  • Installation issue

    Installation issue

    For some reasons, I can not get this package installed. I am using Laravel 5.8.10 on the mac with the default composer.json. I have this config as part of my composer.json. "minimum-stability": "dev", "prefer-stable": true,

    Screenshot 2019-07-07 at 11 35 34 AM
    opened by joefazee 5
  • Update PHP version requirement

    Update PHP version requirement

    Noting that I can not upgrade my Laravel 8 application to Laravel 9 due to the PHP version requirements by this package. Any chance you can bump the max php version to 8.1?

    opened by james-lukensow 3
  • Fail or ignore filter exception

    Fail or ignore filter exception

    In this PR added a failOrSkipFilter method. Sometimes you may need to ignore the filters if they are not found. This method helps you to do that.

    $users = \EloquentBuilder::failOrSkipFilter(false)->to(User::class,$filters)->get();
    
    // Throw NotFoundFilterException if a filter not found.
    $users = \EloquentBuilder::failOrSkipFilter(true)->to(User::class,$filters)->get();
    

    Please feel free to give any ideas about this PR.

    enhancement 
    opened by mohammad-fouladgar 3
  • Ignore the filter if it was not found

    Ignore the filter if it was not found

    Hi, I would like to add a dynamic filter (I append the query parameter 'filters[profile_id]' to all urls if user presses on a button ). To do this, the NotFoundFilterException must not be throwed if the Model don't have ProfileIdFilter. Is it possible to ignore the filter if it is absent, and not generate the error? Is there any parameter in the configuration for this?

    opened by ArtemNehoda 3
  • Problem with filter zero

    Problem with filter zero

    Hello, thank you for the job!

    I've problem when filter has value 0: // GET /filter?step=0&work=1&... // GET /filter?step[]=0&...

    The param step in ServiceProvider->registerMacros is excluded because it is considered empty, instead it is a valid value in my DB.

    Is there any solution?

    bug 
    opened by merudda 3
Releases(v1.0.0)
Owner
M.Fouladgar
sᴏғᴛᴡᴀʀᴇ ᴅᴇᴠᴇʟᴏᴘᴇʀ
M.Fouladgar
A DynamoDB based Eloquent model and Query builder for Laravel.

Laravel DynamoDB A DynamoDB based Eloquent model and Query builder for Laravel. You can find an example implementation in kitar/simplechat. Motivation

Satoshi Kita 146 Jan 2, 2023
Stop duplicating your Eloquent query scopes and constraints in PHP. This package lets you re-use your query scopes and constraints by adding them as a subquery.

Laravel Eloquent Scope as Select Stop duplicating your Eloquent query scopes and constraints in PHP. This package lets you re-use your query scopes an

Protone Media 75 Dec 7, 2022
A simple to use query builder for the jQuery QueryBuilder plugin for use with Laravel.

QueryBuilderParser Status Label Status Value Build Insights Code Climate Test Coverage QueryBuilderParser is designed mainly to be used inside Laravel

Tim Groeneveld 149 Nov 11, 2022
A WPDB wrapper and query builder library.

DB A WPDB wrapper and query builder library. Installation It's recommended that you install DB as a project dependency via Composer: composer require

StellarWP 35 Dec 15, 2022
Enable/disable query logger in Laravel/Lumen

Enable/disable query logger in Laravel/Lumen

Ngoc Linh Pham 5 Nov 2, 2022
Laravel basic Functions, eloquent cruds, query filters, constants

Emmanuelpcg laravel-basics Description Package with basic starter features for Laravel. Install If Builder Constants Install composer require emmanuel

Emmanuel Pereira Pires 3 Jan 1, 2022
A Laravel package that provides configurable application query capturing & monitoring

Laravel Query Watcher A Laravel package that provides configurable application query capturing & monitoring. Installation install the package via comp

YorCreative 36 Dec 17, 2022
This package provides a trait that will generate a unique uuid when saving any Eloquent model.

Generate slugs when saving Eloquent models This package provides a trait that will generate a unique uuid when saving any Eloquent model. $model = new

Abdul Kudus 2 Oct 14, 2021
Laravel router extension to easily use Laravel's paginator without the query string

?? THIS PACKAGE HAS BEEN ABANDONED ?? We don't use this package anymore in our own projects and cannot justify the time needed to maintain it anymore.

Spatie 307 Sep 23, 2022
Laravel Query Helper was developed for laravel 7.2+ to help you optimize sql queries

Laravel Query Helper Laravel Query Helper was developed for laravel 7.2+ to help you optimize sql queries, this package will contain all advanced SQL

Syrian Open Source 15 Nov 20, 2022
Laravel Form builder for version 5+!

Laravel 5 form builder Form builder for Laravel 5 inspired by Symfony's form builder. With help of Laravels FormBuilder class creates forms that can b

Kristijan Husak 1.7k Dec 31, 2022
Reactive Form Builder for Vue.js with Laravel Support

Dynamic Form Builder for Laravel with Vue.js Create even the most complex forms with ease, using two-sided validation, eloquent, nested elements, cond

Laraform 340 Dec 31, 2022
Laravel Mysql Spatial Builder Extension

magutti-spatial V2 Laravel Builder Mysql Spatial Extension Laravel Builder extensions to calculate distances between two Spatial points using Mysql na

Marco Asperti 4 Oct 2, 2022
A TWBS menu builder for Laravel

Laravel Menu Builder A menu builder for Laravel 4-5 using Bootstrap's markup. Документация на Русском Note that this package is shipped with no styles

Alexander Kalnoy 24 Nov 29, 2022
A powerful form builder, for Laravel and other frameworks (stand-alone too)

Former A Laravelish way to create and format forms Former outputs form elements in HTML compatible with your favorite CSS framework (Bootstrap and Fou

null 1.3k Dec 22, 2022
Laravel API architecture builder based on artisan commands.

??‍?? API-Formula Laravel API architecture builder based on artisan commands. This package provides a nice and fluent way to generate combined control

Krševan Lisica 1 Jan 16, 2022
A Laravel Admin Starter project with Page Builder, Roles, Impersonation, Analytics, Blog, News, Banners, FAQ, Testimonials and more

Laravel CMS Starter Project A Laravel CMS Starter project with AdminLTE theme and core features. Preview project here User: [email protected]

Ben-Piet O'Callaghan 306 Nov 28, 2022
Builder - A handful of tools for Rapid Laravel Development

Grafite Builder Grafite has archived this project and no longer supports or develops the code. We recommend using only as a source of ideas for your o

Grafite Inc 997 Dec 22, 2022
Laravel-FCM is an easy to use package working with both Laravel and Lumen for sending push notification with Firebase Cloud Messaging (FCM).

Laravel-FCM Introduction Laravel-FCM is an easy to use package working with both Laravel and Lumen for sending push notification with Firebase Cloud M

Rahul Thapa 2 Oct 16, 2022