jespejoh/lararepo

此包已被弃用且不再维护。作者建议使用https://github.com/followloop/laravel-repositories包。

一个提供将Repository模式与Laravel & Eloquent集成的优雅实现的包。

维护者

详细信息

github.com/jespejoh/lararepo

此包尚未发布版本,且信息不多。


README

一个提供将Repository模式与Laravel & Eloquent集成的优雅实现的包。

目标

与仓库一起工作可以提供一种很好的方式,不仅可以解耦代码,还可以分离关注点和隔离内容,以及分离和组合责任。我们大部分时间都会在我们的数据库表上执行非常通用的操作,比如创建、更新、筛选或删除。

然而,使用仓库并不总是好主意,尤其是在Laravel及其ORM Eloquent中,因为有时它迫使我们为了更好的架构(这取决于情况)而放弃一些很好的功能。对于某些项目来说,这可能是一个过度设计,因此是否需要这种复杂度取决于开发者。

此包旨在在Laravel的Eloquent ORM上实现Repository模式时提供样板代码。它通过提供一个RepositoryInterface和一个基本的Repository实现来实现,该实现能够与Eloquent模型一起工作,提供覆盖您可能要在应用程序中执行的85%数据库操作的基本方法。

安装

  1. 通过将此包添加到您的composer.json文件或通过在项目文件夹中运行composer require jespejoh/lararepo来安装此包。
  2. 将提供者添加到您的config/app.php文件中:Jespejoh\LaraRepo\LararepoServiceProvider::class
  3. 通过运行php artisan vendor:publish --provider="/vendor/jespejoh/lararepo/config/lararepo.php"发布配置文件
  4. 打开配置文件(config/lararepo.php),并根据您的需求配置路径。
  5. 万事俱备!

使用

要开始使用此包,您只需要创建一个文件夹,您将在此文件夹中放置所有的仓库接口和仓库实现,并从包提供的EloquentRepository类扩展每个仓库。

您创建的仓库要处理的Eloquent模型也应通过Repo构造函数注入。

然后,包将尝试根据config/lararepo.php文件中指定的参数加载所有仓库接口并将它们绑定到仓库实现。

示例

让我们假设我们将所有仓库放在名为"MyWebbApp"的文件夹中,该文件夹位于"app"文件夹内名为"Repositories"的文件夹中:app/MyWebApp/Repositories。

在此文件夹的根目录下,我们将有所有接口,遵循以下命名约定:[RepositoryName]Interface.php

注意:只要我们使用"Interface"作为后缀,我们使用的名称并不重要。这很重要,因为自动绑定器将尝试查找所有匹配此模式的所有文件。

在此"Repositories"文件夹内,我们必须有一个名为Eloquent的另一个文件夹,它将包含所有仓库的实现,遵循以下命名约定:[RepositoryName].php

我们应该有一个这样的结构

+-- app
|   +-- MyApp
|       +-- Repositories
|           +-- UsersRepositoryInterface.php
|           +-- RolesRepositoryInterface.php
|           +-- CommentsRepositoryInterface.php
|           +-- PostsRepositoryInterface.php
|           +-- Eloquent
|               +-- UsersRepository.php
|               +-- RolesRepository.php
|               +-- CommentsRepository.php
|               +-- PostsRepository.php  

让我们看看UsersRepositoryInterface.phpUsersRepository.php的内容。


<?php

namespace MyApp\Repositories;

use Jespejoh\LaraRepo\RepositoryInterface;

interface UsersRepositoryInterface extends RepositoryInterface {

    // here you would write the contract for methods that your repository will implement.
}

<?php

namespace MyApp\Repositories\Eloquent;

use Jespejoh\LaraRepo\src\EloquentRepository;
use MyApp\Repositories\UsersRepositoryInterface;
use MyApp\Models\User;

class UsersRepositoryInterface extends EloquentRepository implements UsersRepositoryInterface  {

    public function __construct( User $user ) {
        parent::__construct( $user );
    }

    // methods that your repository should implement...
}

现在我们需要配置 config/lararepo.php 文件以匹配我们的路径和命名空间


    'path' => app_path('MyApp/Repositories'),

    'namespace' => 'MyApp\Repositories',

    'implementation' => 'Eloquent',

现在仓库已经准备好使用,可以注入到其他服务或控制器中


<?php

namespace MyApp\Services\Users;

use MyApp\Repositories\UsersRepositoryInterface;

class UsersService implements UsersServicesInterface  {

    protected $usersRepository;

    public function __construct( UsersRepositoryInterface $usersRepositoryInterface ) {
        $this->usersRepository = $usersRepositoryInterface;
    }

    // other methods in your service.
}

注意:本示例假设您已将 composer.json 配置为自动加载 app/MyApp 目录下的文件,并使用 MyApp 命名空间。

默认提供的方法。

仓库包默认提供了一系列方法。这些是


    /**
     * Finds one item by the provided field.
     *
     * @param $value mixed Value used for the filter.
     * @param string $field Field on the database that you will filter by. Default: id.
     * @param array $columns Columns to retrieve with the object.
     * @return mixed Model|NULL An Eloquent object when there is a result, NULL when there are no matches.
     */
    public function findOneBy( $value, $field = 'id', array $columns = ['*'] );

    /**
     * Finds ALL items the repository abstract without any kind of filter.
     *
     * @param array $columns Columns to retrieve with the objects.
     * @return mixed Collection Laravel Eloquent's Collection that may or may not be empty.
     */
    public function findAll( array $columns = ['*'] );

    /**
     * Finds ALL items by the provided field.
     *
     * @param $value mixed Value used for the filter.
     * @param string $field Field on the database that you will filter by. Default: id.
     * @param array $columns Columns to retrieve with the objects.
     * @return mixed Collection Laravel Eloquent's Collection that may or may not be empty.
     */
    public function findAllBy( $value, $field, array $columns = ['*'] );

    /**
     * Finds ALL the items in the repository where the given field is inside the given values.
     *
     * @param array $value mixed Array of values used for the filter.
     * @param string $field Field on the database that you will filter by.
     * @param array $columns Columns to retrieve with the objects.
     * @return mixed Collection Laravel Eloquent's Collection that may or may not be empty.
     */
    public function findAllWhereIn( array $value, $field,  array $columns = ['*'] );

    /**
     * Allows you to eager-load entity relationships when retrieving entities, either with or without criterias.
     *
     * @param array|string $relations Relations to eager-load along with the entities.
     * @return mixed The current repository object instance.
     */
    public function with( $relations );

    /**
     * @param CriteriaInterface $criteria Object that declares and implements the criteria used.
     * @return mixed The current repository object instance.
     */
    public function addCriteria( CriteriaInterface $criteria );

    /**
     * Finds ONE (the first) item in the repository that matches the saved/given criteria.
     *
     * @param array $columns Columns to retrieve with the objects.
     * @return mixed Model|NULL A model object when there is a result, NULL when there are no matches.
     */
    public function findOneByCriteria( array $columns = ['*'] );

    /**
     * Finds ALL items in the repository that match the saved/given criteria.
     *
     * @param array $columns Columns to retrieve with the objects.
     * @return mixed Collection Laravel Eloquent's Collection that may or may not be empty.
     */
    public function findAllByCriteria( array $columns = ['*'] );

    /**
     * Skips the current criteria (all of them). Useful when you don't want to reset the object but just not use the
     * filters applied so far.
     *
     * @param bool|TRUE $status If you want to skip the criteria or not.
     * @return mixed The current repository object instance.
     */
    public function skipCriteria( $status = TRUE );

    /**
     * Returns a collection with the current criteria loaded in the repository, whether it's being applied or not.
     *
     * @return mixed Collection Current criteria loaded into the repository.
     */
    public function getCriteria();

    /**
     * Returns a Paginator that based on the criteria or filters given.
     *
     * @param int $perPage Number of results to return per page.
     * @param array $columns Columns to retrieve with the objects.
     * @return Paginator object with the results and the paginator.
     */
    public function paginate( $perPage, array $columns = ['*'] );

    /**
     * Allows you to set the current page with using the paginator. Useful when you want to overwrite the $_GET['page']
     * parameter and retrieve a specific page directly without using HTTP.
     *
     * @param int $page The page you want to retrieve.
     * @return mixed The current repository object instance.
     */
    public function setCurrentPage( $page );

    /**
     * Resets the current scope of the repository. That is: clean the criteria, and all other properties that could have
     * been modified, like current page, etc.
     *
     * @return mixed The current repository object instance.
     */
    public function resetScope();

    /**
     * Creates a new entity of the entity type the repository handles, given certain data.
     *
     * @param array $data Data the entity will have.
     * @return mixed Model|NULL An Eloquent object when the entity was created, NULL in case of error.
     */
    public function create( array $data );

    /**
     * Updates as many entities as the filter matches with the given $data.
     *
     * @param array $data Fields & new values to be updated on the entity/entities.
     * @param $value mixed Value used for the filter.
     * @param string $field Field on the database that you will filter by. Default: id.
     * @return mixed Model|NULL An Eloquent object representing the updated entity, NULL in case of error.
     */
    public function updateBy( array $data, $value, $field = 'id' );

    /**
     * Removes as many entities as the filter matches. If softdelete is applied, then they will be soft-deleted.
     *
     * @param $value
     * @param $value mixed Value used for the filter.
     * @param string $field Field on the database that you will filter by. Default: id.
     * @return boolean TRUE It will always return TRUE.
     */
    public function delete( $value, $field = 'id' );

    /**
     * @return int number of records matching the criteria (or total amount of records).
     */
    public function count();

条件

为了避免我们的仓库中充满了诸如 findActiveUsers()findActiveUsersOlderThan( $date ) 等方法,我们将使用条件来对搜索或查询应用过滤器。

条件只是一个实现了本包提供的 CriteriaInterface 的 PHP 对象,它操作 Eloquent 模型以应用我们想要为特定搜索应用的查询或查询集。

要创建您自己的条件,将它们放置在您想要的任何位置,并实现提供的 CriteriaInterface。

例如:假设我们有一个应用程序,用户可以通过 Facebook、Twitter 或电子邮件注册。我们需要根据用户注册的方法检索所有用户。我们会有这样一个条件


<?php

namespace MyApp\Repositories\Eloquent\Criteria\Users;

use Jespejoh\LaraRepo\Criteria\CriteriaInterface;
use MyApp\Models\User;

class RegisteredVia implements CriteriaInterface  {

    protected $registeredVia;
    protected $onlyActive;

    public function __construct( $registeredVia, $onlyActive = TRUE ) {

        $this->registeredVia = $registeredVia;
        $this->onlyActive = $onlyActive;

    }


    public function apply( $queryBuilder ) {

        if ( $this->onlyActive ) $queryBuilder = $queryBuilder->where( 'active', TRUE );

        return $queryBuilder->where( 'registered_via', $this->registered_via );

    }

}

现在在您的服务或控制器中,您可以像这样使用这个条件


    $registeredViaFacebookCriteria = new RegisteredVia( 'facebook' );

    return $this->usersRepository->addCriteria( $registeredViaFacebookCriteria )->findAllByCriteria();

我们甚至可以链式调用不同的条件


    $registeredViaFacebookCriteria = new RegisteredVia( 'facebook' );
    $orderByCreationDate = new OrderBy( 'created_at', 'ASC' );

    return $this->usersRepository
                ->addCriteria( $registeredViaFacebookCriteria )
                ->addCriteria( $orderByCreationDate )
                ->findAllByCriteria();

更新日志

-- 尚未发布任何版本 --

致谢

  • Jesús Espejo (Twitter)
  • Bosnadev 的这篇优秀的文章为这个包中包含的大部分内容提供了灵感:[https://bosnadev.com/2015/03/07/using-repository-pattern-in-laravel-5/](https://bosnadev.com/2015/03/07/using-repository-pattern-in-laravel-5/)

错误 & 贡献

  • 发现了错误?这既是好事也是坏事。请使用 Github 上的 Issues 来告诉我。
  • 需要功能或有一些有趣的内容想要贡献吗?太好了!提交一个 pull request。

许可证

MIT 许可证 (MIT)。请参阅 许可证文件 了解更多信息。