guilhermegonzaga / repository
Repositories for Laravel 5 which is used to abstract the database layer.
Requires
- php: >=5.5.9
- illuminate/database: ~5.1
- illuminate/support: ~5.1
Suggests
- guilhermegonzaga/presenter: Implementation for Laravel 5 of the presenter design pattern.
README
Repository is a design pattern for Laravel 5 which is used to abstract the database layer.
It makes your application easier to be maintained.
Installation
Laravel (5.1 and 5.2)
Execute the following command to get the latest version of the package:
composer require guilhermegonzaga/repository
Methods
public function first($columns = ['*'], $fail = true); public function find($id, $columns = ['*'], $fail = true); public function findBy($attribute, $value); public function where(array $where, $boolean = 'and'); public function create(array $data, $force = true); public function update(array $data, $id = null, $force = true); public function delete($id = null); public function paginate($limit = 15, $columns = ['*'], $pageName = 'page'); public function exists(); public function random($qtd = 15); public function scopes(Closure $scope, $boolean = 'and'); public function criteria($class, array $args = []); public function with($relations); public function withBoot(); public function withoutBoot(); public function all($columns = ['*']); public function get($columns = ['*']);
Usage
Create your repository class.
Note that your repository class must extend GuilhermeGonzaga\Repository\Eloquent\Repository
and implement model()
method.
namespace App\Repositories; use GuilhermeGonzaga\Repository\Eloquent\Repository; class CategoryRepository extends Repository { public function model() { return \App\Category::class; } // Optional method, global rules public function boot() { $this->findBy('active', true); $this->orderBy('created_at', 'desc'); } // Other methods }
By implementing model()
method you telling repository what model class you want to use.
Create your model:
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Category extends Model { protected $table = 'categories'; protected $fillable = [ 'name', 'parent_id', ... ]; ... }
Finally, use the repository in the controller:
use App\Repositories\CategoryRepository; class CategoriesController extends Controller { protected $repository; public function __construct(CategoryRepository $repository) { $this->repository = $repository; } ... }
Usage methods
Find all results:
$results = $this->repository->all();
Find first result:
$result = $this->repository->where([['abc', '!=', 'def']])->first(); // Fire ModelNotFoundException (firstOrFail) $result = $this->repository->findBy('abc', 'def')->first(['*'], false); // Not fire ModelNotFoundException (first)
Find all results with pagination:
$results = $this->repository->paginate(); $results = $this->repository->paginate(10);
Find result by id:
$result = $this->repository->find($id); // Fire ModelNotFoundException (findOrFail) $result = $this->repository->find($id, ['*'], false); // Not fire ModelNotFoundException (find)
Loading the model relationships:
$result = $this->repository->with('relationName')->find($id); $result = $this->repository->with(['relation1', 'relation2'])->find($id);
Find result by multiple fields:
$results = $this->repository->where([ //Default condition (=) 'user_id' => '10', //Custom condition ['price', '>=', '9.90'] ])->get();
Find using custom scope (nested):
$results = $this->repository->scopes(function ($query) { $query->whereDate('birth_date', '=', Carbon::now()->toDateString()); $query->whereActive(true); })->get();
Get random results:
$results = $this->repository->whereFeatured(true)->scopes(function ($query) { ... }, 'or')->random()->get(); $results = $this->repository->whereNull('discount')->random(10)->get();
Enable/disable boot()
method in repository:
$results = $this->repository->withBoot()->all(); $results = $this->repository->withoutBoot()->all();
Create new entry:
$result = $this->repository->create(Input::all()); // without $fillable $result = $this->repository->create(Input::all(), false); // with $fillable
Update entry:
$result = $this->repository->update(Input::all(), $id); // without $fillable $result = $this->repository->update(Input::all(), $id, false); // with $fillable $result = $this->repository->whereFieldName('test')->update(Input::all()); // update first result
Delete entry:
$this->repository->delete($id); $this->repository->delete([1, 2, 3]); $this->repository->whereActive(false)->where(['payment_failed' => true], 'or')->delete();
Criteria
This package makes it very easy to work with scopes/criteria.
Create classes to abstract these rules and make them reusable:
namespace App\Repositories\Criteria; use GuilhermeGonzaga\Repository\Contracts\RepositoryContract as Repository; use GuilhermeGonzaga\Repository\Criteria\Criteria; class PopularProducts extends Criteria { public function apply(Repository $repository) { $repository->where([ ['purchases', '>', '50'] ]); } }
Receiving arguments:
namespace App\Repositories\Criteria; use GuilhermeGonzaga\Repository\Contracts\RepositoryContract as Repository; use GuilhermeGonzaga\Repository\Criteria\Criteria; class ProductsByCategory extends Criteria { protected $category; public function __construct($category) { $this->category = $category; } public function apply(Repository $repository) { $repository->findBy('category_id', $this->category); } }
Use the criteria in the controller:
use App\Repositories\ProductRepository; use App\Repositories\Criteria\PopularProducts; use App\Repositories\Criteria\ProductsByCategory; use App\Repositories\Criteria\ProductsByCategories; class ProductsController extends Controller { protected $repository; public function __construct(ProductRepository $repository) { $this->repository = $repository; } public function index() { $this->repository->criteria(PopularProducts::class)->get(); } public function showByCategory($category) { $this->repository->criteria(ProductsByCategory::class, [$category])->get(); } public function showByCategories($category1, $category2) { $this->repository->criteria(ProductsByCategories::class, [ $category1, $category2, $category3 ])->get(); } }
Other methods
In addition to the methods that are available in this package, you can call any method in default of Eloquent Builder. When you call a method that does not exist in this package, it's automatically called on Eloquent Builder.
Ex:
$results = $this->repository->orderBy('created_at', 'desc')->get(); $results = $this->repository->whereIn('category_id', [2, 4, 6])->get(); $results = $this->repository->whereBetween('votes', [10, 100])->get(); $results = $this->repository->whereFieldName('test')->get();
Credits
This package is largely inspired by this great package by @andersao.