Repository is a design pattern for Laravel 5 which is used to abstract the database layer.
It makes your application easier to be maintained.
Execute the following command to get the latest version of the package:
composer require guilhermegonzaga/repository
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 = ['*']);
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;
}
...
}
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();
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();
}
}
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();
This package is largely inspired by this great package by @andersao.