Code Monkey home page Code Monkey logo

repository's Introduction

Laravel Repository Package

THIS PACKAGE IS A WORK IN PROGRESS

This packages helps you to easily implement the repository package in your Laravel application.

Why use this package out of the many other Laravel repository package? This package was inspired by multiple other Laravel repository package. I took all the good things from those packages and create one unique package for it. Also I keep maintain this package, because I use it in multiple of my own projects.

Installation

You can install this package using composer, by running the following command:

composer require dees040/repository

The service provider is automatically added via Laravel package discovery.

Methods

Dees040\Repository\Contracts\Repository

  • all($columns = ['*'])
  • paginate($perPage = null, $columns = ['*'])
  • first($columns = ['*'])
  • find($id, $columns = ['*'])
  • findOrFail($id, $columns = ['*'])
  • findByField($field, $value, $columns = ['*'])
  • findWhere(array $where, $columns = ['*'])
  • findWhereIn(array $where, $columns = ['*'])
  • firstOrCreate(array $attributes, array $values = [])
  • create(array $attributes = [])
  • insert(array $attributes = [])
  • update($id, array $attributes)
  • updateOrCreate(array $attributes, array $values = [])
  • delete($id)
  • deleteWhere(array $where)
  • deleteWhereIn(array $where)
  • orderBy($column, $direction = 'asc')
  • with($relations)
  • has($relation)
  • whereHas($relation, \Closure $closure)
  • orWhereHas($relation, \Closure $closure)
  • sync($id, $relation, $attributes, $detaching = true)
  • syncWithoutDetaching($id, $relation, $attributes)

Usage

Creating a repository

Repositories can be created by hand or via a command provided in this package. If you'd like to create a repository by hand you should create two files for each repository.

One class for the repository contract:

<?php

namespace App\Repositories\Contracts;

use Dees040\Repository\Contracts\Repository;

interface PostRepository extends Repository
{

}

And one class for the actual repository:

<?php

namespace App\Repositories;

use App\Post;
use App\Repositories\Contracts\PostRepository;
use Dees040\Repository\Eloquent\BaseRepository;

class PostEloquentRepository extends BaseRepository implements PostRepository
{
    /**
     * Get the base model.
     *
     * @return string
     */
    public function getModel()
    {
        return Post::class;
    }
}

The other option is creating the file using the make:repository command:

php artisan make:repository Post

Usage in controllers

After creating the repository you should bind the repository contract to the correct repository using the Laravel Container. By doing this Laravel knows exactly which repository to use for which contract. This makes it very easy to switch between a eloquent repository or e.g. a MongoDB repository.

So before using any repositories in your controller make sure to bind it to the container. You can do that using the bind($abstract, concrete) method in the Container. E.g.: App::bind(\App\Repositories\Contracts\PostRepository::class, \App\Repositories\PostEloquentRepository::class).

Personally I like to create a new service provider named \App\Providers\RepositoryServiceProvider.php and do something like this:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class RepositoryServiceProvider extends ServiceProvider
{
    /**
     * The contracts with their associated repositories.
     *
     * @var array
     */
    protected $repositories = [
        \App\Repositories\Contracts\PostRepository::class => \App\Repositories\PostEloquentRepository::class,
    ];
    
    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
       //
    }

    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        foreach ($this->repositories as $contract => $repository) {
            $this->app->bind($contract, $repository);
        }
    }
}

After binding in to the container you can use dependency injection inside your controller to get the repository.

public function __contruct(PostRepository $repostiroy)
{
    $this->repository = $repostiroy;
}

Using criteria

If you'd like to execute custom queries to the database call you can use criteria. You can add criteria to your call by calling the pushCriteria method.

$this->repository->pushCriteria(new Criteria());
$this->repository->pushCriteria(Criteria::class);

Make sure that your custom criteria classes are implementing the \Dees040\Repository\Contracts\Criteria interface. An example of custom criteria is:

<?php

namespace App\Criteria;

use Dees040\Repository\Contracts\Criteria;

class HasUserRelationCriteria implements Criteria
{
    /**
     * Execute the criteria.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  \Dees040\Repository\Contracts\Repository  $repository
     * @return \Illuminate\Database\Eloquent\Model
     */
    public function apply($model, $repository)
    {
        return $this->model->orderBy('created_at')
            ->whereHas('users', function ($query) {
                $query->where('users.id', 1);
            });
    }
}

RequestCriteria

The package ships with a useful criteria out of the box. The RequestCriteria. It gives you the ability to easily perform extra actions on your queries via the route parameters. You can add order by items or search through your models. You can add the criteria by default in the constructor of a repository:

public function __construct()
{
    $this->pushCriteria(\Dees040\Repository\Criteria\RequestCriteria::class);
}

After doing this you can add following query parameters.

  • https://example.test/posts?order_by=created_at
  • https://example.test/posts?order_by=created_at&sort_by=desc
  • https://example.test/posts?search=Lorem ipsum
  • https://example.test/posts?search=Lorem ipsum&search_fields=body
  • https://example.test/posts?search=Lorem ipsum&search_fields=title,body:like
  • https://example.test/posts?search=Lorem ipsum&search_fields=title,body:like&order_by=title

If you'd like to have the ability to search you should override the getSearchableFields() method in your repository. All the fields returned in the array of that method are then searchable via the route parameters.

/**
 * Get all fields which are searchable.
 *
 * @return array
 */
public function getSearchableFields()
{
    return [
        'title',
        'body',
    ];
}

TODOS

  • Create a build in criteria class for requests
  • Search fields in the request criteria
  • Create cache
  • Parse results
  • Pagination options
  • Search on custom fields in request criteria
  • Dynamic criteria class
  • Regex split on search fields
  • Add dot nation for relations in request criteria
  • Create commands

repository's People

Contributors

dees040 avatar thomasowow avatar youneselbarnoussi avatar

Watchers

 avatar  avatar

repository's Issues

firstOrFail method

Would be nice to have the firstOrFail method available.

An example use case would be:

$repo->whereHas(...)->firstOrFail();

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.