🖖Repository Pattern in Laravel. The package allows to filter by request out-of-the-box, as well as to integrate customized criteria and any kind of filters.

Overview

Awes.io logo

Repository

Repository Pattern in Laravel. The package allows to filter by request out-of-the-box, as well as to integrate customized criteria and any kind of filters.

Coverage report Last version Build status Downloads License CDN Ready laravel Last commit Analytics Hosted by Package Kit Patreon

Repository Laravel

Table of Contents

Installation

Via Composer

$ composer require awes-io/repository

The package will automatically register itself.

Configuration

First publish config:

php artisan vendor:publish --provider="AwesIO\Repository\RepositoryServiceProvider" --tag="config"
// $repository->smartPaginate() related parameters
'smart_paginate' => [
    // name of request parameter to take paginate by value from
    'request_parameter' => 'limit',
    // default paginate by value
    'default_limit' => 15,
    // max paginate by value
    'max_limit' => 100,
]

Overview

Package allows you to filter data based on incoming request parameters:
https://example.com/news?title=Title&custom=value&orderBy=name_desc

It will automatically apply built-in constraints onto the query as well as any custom scopes and criteria you need:

protected $searchable = [
    // where 'title' equals 'Title'
    'title',
];

protected $scopes = [
    // and custom parameter used in your scope
    'custom' => MyScope::class,
];
class MyScope extends ScopeAbstract
{
    public function scope($builder, $value, $scope)
    {
        return $builder->where($scope, $value)->orWhere(...);
    }
}

Ordering by any field is available:

protected $scopes = [
    // orderBy field
    'orderBy' => OrderByScope::class,
];

Package can also apply any custom criteria:

return $this->news->withCriteria([
    new MyCriteria([
        'category_id' => '1', 'name' => 'Name'
    ])
    ...
])->get();

Usage

Create a Model

Create your model:

namespace App;

use Illuminate\Database\Eloquent\Model;

class News extends Model 
{
    ...
}

Create a Repository

Extend it from AwesIO\Repository\Eloquent\BaseRepository and provide entity() method to return full model class name:

namespace App;

use AwesIO\Repository\Eloquent\BaseRepository;

class NewsRepository extends BaseRepository
{
    public function entity()
    {
        return News::class;
    }
}

Use built-in methods

use App\NewsRepository;

class NewsController extends BaseController 
{
    protected $news;

    public function __construct(NewsRepository $news)
    {
        $this->news = $news;
    }
    ....
}

Execute the query as a "select" statement or get all results:

$news = $this->news->get();

Execute the query and get the first result:

$news = $this->news->first();

Find a model by its primary key:

$news = $this->news->find(1);

Add basic where clauses and execute the query:

$news = $this->news->->findWhere([
        // where id equals 1
        'id' => '1',
        // other "where" operations
        ['news_category_id', '<', '3'],
        ...
    ]);

Paginate the given query:

$news = $this->news->paginate(15);

Paginate the given query into a simple paginator:

$news = $this->news->simplePaginate(15);

Paginate the given query by 'limit' request parameter:

$news = $this->news->smartPaginate();

Add an "order by" clause to the query:

$news = $this->news->orderBy('title', 'desc')->get();

Save a new model and return the instance:

$news = $this->news->create($request->all());

Update a record:

$this->news->update($request->all(), $id);

Delete a record by id:

$this->news->destroy($id);

Attach models to the parent:

$this->news->attach($parentId, $relationship, $idsToAttach);

Detach models from the relationship:

$this->news->detach($parentId, $relationship, $idsToDetach);

Find model or throw an exception if not found:

$this->news->findOrFail($id);

Execute the query and get the first result or throw an exception:

$this->news->firstOrFail();

Create a Criteria

Criteria are a way to build up specific query conditions.

use AwesIO\Repository\Contracts\CriterionInterface;

class MyCriteria implements CriterionInterface {

    protected $conditions;
    
    public function __construct(array $conditions)
    {
        $this->conditions = $conditions;
    }

    public function apply($entity)
    {
        foreach ($this->conditions as $field => $value) {
            $entity = $entity->where($field, '=', $value);
        }
        return $entity;
    }
}

Multiple Criteria can be applied:

use App\NewsRepository;

class NewsController extends BaseController 
{
    protected $news;

    public function __construct(NewsRepository $news)
    {
        $this->news = $news;
    }

    public function index()
    {
        return $this->news->withCriteria([
            new MyCriteria([
                'category_id' => '1', 'name' => 'Name'
            ]),
            new WhereAdmin(),
            ...
        ])->get();
    }
}

Scope, Filter and Order

In your repository define which fields can be used to scope your queries by setting $searchable property.

protected $searchable = [
    // where 'title' equals parameter value
    'title',
    // orWhere equals
    'body' => 'or',
    // where like
    'author' => 'like',
    // orWhere like
    'email' => 'orLike',
];

Search by searchables:

public function index($request)
{
    return $this->news->scope($request)->get();
}
https://example.com/news?title=Title&body=Text&author=&email=gmail

Also several serchables enabled by default:

protected $scopes = [
    // orderBy field
    'orderBy' => OrderByScope::class,
    // where created_at date is after
    'begin' => WhereDateGreaterScope::class,
    // where created_at date is before
    'end' => WhereDateLessScope::class,
];
$this->news->scope($request)->get();

Enable ordering for specific fields by adding $orderable property to your model class:

public $orderable = ['email'];
https://example.com/news?orderBy=email_desc&begin=2019-01-24&end=2019-01-26

orderBy=email_desc will order by email in descending order, orderBy=email - in ascending

You can also build your own custom scopes. In your repository override scope() method:

public function scope($request)
{
    // apply build-in scopes
    parent::scope($request);

    // apply custom scopes
    $this->entity = (new NewsScopes($request))->scope($this->entity);

    return $this;
}

Create your scopes class and extend ScopesAbstract

use AwesIO\Repository\Scopes\ScopesAbstract;

class NewsScopes extends ScopesAbstract
{
    protected $scopes = [
        // here you can add field-scope mappings
        'field' => MyScope::class,
    ];
}

Now you can build any scopes you need:

use AwesIO\Repository\Scopes\ScopeAbstract;

class MyScope extends ScopeAbstract
{
    public function scope($builder, $value, $scope)
    {
        return $builder->where($scope, $value);
    }
}

Artisan Commands

Package provides useful artisan command:

php artisan repository:generate Models/Order --scope=Search

It'll generate several classes for App\Models\Order:

Main repository: App\Repositories\Orders\OrdersRepository

Main scopes class: App\Repositories\Orders\Scopes\OrdersScopes

Individual search scope class: App\Repositories\Orders\Scopes\SearchOrdersScope

Testing

The coverage of the package is Coverage report.

You can run the tests with:

composer test

Contributing

Please see contributing.md for details and a todolist.

Credits

License

MIT

Comments
  • Implementation of repository pattern

    Implementation of repository pattern

    Hello, I think you are not achieving the benefits you preached about with your interface. The Eloquent jargon in your interface and the type hint to return an Eloquent model are coupling it to Eloquent: this hurts the repository pattern in this case. If a project were to eventually replace Eloquent, it will be difficult to do that.

    opened by Whallas 1
  • Remove deprecated str_after helper

    Remove deprecated str_after helper

    Summary

    the helper function is deprecated in Laravel 6. #https://github.com/laravel/framework/pull/26898#issue-239566151

    Test plan (required)

    I changed this in the test itself.

    thank you.

    opened by MohammedAlkutrani 1
  • Columns in `$searchable` are ambiguous

    Columns in `$searchable` are ambiguous

    Your issue may already be reported! Please search on the issue tracker before creating one.

    Expected Behavior

    It should be possible to use the same column name on a joined table without SQL errors

    Current Behavior

    If a column name specified in the $searchable array also exists in a joined table (e.g. in another scope), a SQL error occurs because the column name is ambiguous

    Possible Solution

    When using any column in the $searchable array, it should be prefixed with the table name associated with the repository

    Steps to Reproduce (for bugs)

    1. Add parent_id to the $searchable array
    2. Add a custom scope which joins to another table and uses parent_id in that table
    3. Code fails with an ambiguous column

    Context

    We have generic names on several tables so we have had to work around this by removing any clashing names from the $searchable array and adding custom scopes to search on that field, thus defeating the point of the array.

    Your Environment

    • Version used: 1.8
    • Browser Name and version: N/A
    • Operating System and version (desktop or mobile): N/A but Ubuntu
    • Link to your project: Private project

    System GA

    Analytics

    opened by ghost 0
  • How do we override the OrderByScope::class

    How do we override the OrderByScope::class

    Your issue may already be reported! Please search on the issue tracker before creating one.

    Expected Behavior

    I want to override the OrderByScope::class so that I can create my own implementation of the orderBy functionality.

    Current Behavior

    It seems like the Scope has the foloowing default scopes:

    class Scopes extends ScopesAbstract
    {
        protected $scopes = [
            'orderBy' => OrderByScope::class,
            'begin' => WhereDateGreaterScope::class,
            'end' => WhereDateLessScope::class,
        ];
    

    This means it will always automatically use the OrderByScope class. Can we provide our own class for this?

    opened by shabaz-ejaz 0
  • How do I get count()?

    How do I get count()?

    I am trying to get the total count() before I apply get(), but it gives an error.

    $returnData = $this->trainerSlot
                ->orderBy('date')
                ->orderBy('place_id')
                ->offset(0)->limit(25);
            $allCount = $returnData->count(); // Error
    

    If I use the same construction without a repository it works.

    $returnData = TrainerSlot::orderBy('date')
                ->orderBy('place_id')
                ->offset(0)->limit(25);
    $allCount = $returnData->count(); // find total 1200 string
    

    If I try to get the total amount after, I called $returnData->get(), then it only gives out the amount received after the limit&offset.

    $returnData = $this->trainerSlot
                ->orderBy('date')
                ->orderBy('place_id')
                ->offset(0)->limit(25);
    $returnData->get();
    $allCount = $returnData->count(); // find total 25 string
    
    opened by atach 0
  • Compatibility with Laravel 8

    Compatibility with Laravel 8

    Hi there! Seems like a very useful library. Thank you for making it.

    I tried to install it with a fresh Laravel 8 installation, but it didn't succeed. Error message below: image

    image

    It would be awesome to have this work with Laravel 8.

    opened by yousof-wm4d 0
Releases(v1.1.8)
Owner
Awes.io
The platform to build Web apps for Startups, SaaS and Enterprises.
Awes.io
The query filter bundle allows you to filter data from QueryBuilder and the Database.

The query filter bundle allows you to filter data from QueryBuilder and the Database. you can filter multiple columns at the same time and also you can filter relation fields with two-level deep and without any join in your query builder.

Bugloos 15 Dec 29, 2022
Auto-generated Interface and Repository file via Repository pattern in Laravel

Auto-generated Repository Pattern in Laravel A repository is a separation between a domain and a persistent layer. The repository provides a collectio

Ngo Dinh Cuong 11 Aug 15, 2022
A nice GUI for Laravel Artisan, ready out of the box, configurable and handy for non-CLI experienced developers.

Artisan UI A nice GUI for Laravel Artisan, ready out of the box, configurable and handy for non-CLI experienced developers. Supported commands must be

Pablo Leone 1 Dec 3, 2021
🚀 Zero-downtime deployment out-of-the-box

?? Laravel Deployer Looking for the old Laravel Deployer? Click here. Laravel Deployer is no longer the package it used to be. Since that package was

Loris Leiva 1.6k Dec 31, 2022
This Package helps you in laravel application to log all desired activity for each request from request entry point to generate response at a single snapshot.

Laravel Scenario Logger This Package helps you in laravel application to log all desired activity for each request from request entry point to generat

Mehrdad Mahdian 6 Sep 27, 2021
Filter resources with request parameters

FilterWhere Filter resources with request parameters Author: Thomas Jakobi [email protected] License: GNU GPLv2 Features With this MODX Revolu

Thomas Jakobi 1 Jul 12, 2022
Specially customized Laravel jetstream's scaffolding for Frest html + laravel admin Template

frest-html-laravel-jetstream Specially customized Laravel jetstream's scaffolding for Frest html + laravel admin Template. It'll not work with any oth

PIXINVENT CREATIVE STUDIO 0 Apr 5, 2022
Database Repository / PHP Repository / Laravel Repository

Database Repository / PHP Repository / Laravel Repository Installation Use following command to add this package to composer development requirement.

Bakery 6 Dec 21, 2022
A package to implement repository pattern for laravel models

Laravel Model UUID A simple package to use Repository Pattern approach for laravel models . Repository pattern Repositories are classes or components

null 26 Dec 21, 2022
Fast and simple implementation of a REST API based on the Laravel Framework, Repository Pattern, Eloquent Resources, Translatability, and Swagger.

Laravel Headless What about? This allows a fast and simple implementation of a REST API based on the Laravel Framework, Repository Pattern, Eloquent R

Julien SCHMITT 6 Dec 30, 2022
Repository Pattern implementation for Laravel

This is a Simple Repository Pattern implementation for Laravel Projects and an easily way to build Eloquent queries from API requests.

Ephraïm SEDDOR 1 Nov 22, 2021
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
Shell script for Git module deployment with include/exclude filters.

Deploy multiple Git repositories in an unique folder modgit is a shell script for deploying multiple Git repositories in root folder of any project, w

Johann Reinké 175 Nov 22, 2022
A collection of easy-to-use filters with clause conditions to Filament

Filament Advanced Filter A collection of easy-to-use filters with clause conditions to Filament Installation Install the package via composer (require

Webbing Brasil 45 Jan 2, 2023
States allows you to create PHP classes following the State Pattern in PHP.

States allows you to create PHP classes following the State Pattern in PHP. This can be a cleaner way for an object to change its behavior at runtime without resorting to large monolithic conditional statements and this improve maintainability and workflows writing.

Teknoo Software 10 Nov 20, 2022
A package that uses blade templates to control how markdown is converted to HTML inside Laravel, as well as providing support for markdown files to Laravel views.

Install Install via composer. $ composer require olliecodes/laravel-etched-blade Once installed you'll want to publish the config. $ php artisan vendo

Ollie Codes 19 Jul 5, 2021
A Laravel package for quickly adding .well-known URLs

A Laravel package for quickly adding .well-known URLs well-known is a Laravel package for quickly adding well-known locations (RFC8615) to a Laravel a

Kim Hallberg 2 Sep 13, 2022
A package to filter laravel model based on query params or retrieved model collection

Laravel Filterable A package to filter laravel model based on query params or retrived model collection. Installation Require/Install the package usin

Touhidur Rahman 17 Jan 20, 2022
Joomla Framework Filter Package

The Filter Package Installation via Composer Add "joomla/filter": "~2.0.*@dev" to the require block in your composer.json and then run composer instal

Joomla! Framework 10 Dec 16, 2022