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
Via Composer
$ composer require awes-io/repository
The package will automatically register itself.
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, ]
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();
Create your model:
namespace App; use Illuminate\Database\Eloquent\Model; class News extends Model { ... }
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 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();
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(); } }
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); } }
Package provides useful artisan command:
php artisan repository:generate Models/Order --scope=Search
Main repository: App\Repositories\Orders\OrdersRepository
Main scopes class: App\Repositories\Orders\Scopes\OrdersScopes
Individual search scope class: App\Repositories\Orders\Scopes\SearchOrdersScope
The coverage of the package is Coverage report.
You can run the tests with:
composer test
Please see contributing.md for details and a todolist.