【问题标题】:Laravel Repsitory Pattern for all model适用于所有模型的 Laravel 存储库模式
【发布时间】:2018-08-21 15:16:06
【问题描述】:

我已经关注了很多 Laravel 仓库的教程和类似教程的 msot。下面的链接之一

https://itsolutionstuff.com/post/laravel-5-repository-pattern-tutorial-from-scratchexample.html

第 1 步:创建界面

在第一步中,我们必须创建接口,然后在 app 文件夹中创建 Repositories(app/Repositories) 目录。我们还需要在 Repositories 文件夹中创建 User(app/Repositories/User) 文件夹。

好的,现在首先我们将在用户目录中创建 UserInterface,所以首先创建 UserInterface.php 文件并将下面的代码放入该文件中:

app/Repositories/User/UserInterface.php

namespace App\Repositories\User;


interface UserInterface {


    public function getAll();


    public function find($id);


    public function delete($id);
}

第 2 步:创建存储库

好的,在这一步我们将创建UserRepository.php 用于写入数据库登录,在这个文件中我们将编写我们的数据库登录代码。所以,首先在用户目录中创建UserRepository.php 文件并放入下面的代码。

app/Repositories/User/UserRepository.php

namespace App\Repositories\User;


use App\Repositories\User\UserInterface as UserInterface;
use App\User;


class UserRepository implements UserInterface
{
    public $user;


    function __construct(User $user) {
$this->user = $user;
    }


    public function getAll()
    {
        return $this->user->getAll();
    }


    public function find($id)
    {
        return $this->user->findUser($id);
    }


    public function delete($id)
    {
        return $this->user->deleteUser($id);
    }
}

第 3 步:创建服务提供者

在这一步中,我们必须为绑定UserInterfaceUserRepository 类创建服务提供者。所以让我们在用户文件夹中创建UserRepoServiceProvide.php`文件并输入以下代码:

app/Repositories/User/UserRepoServiceProvide.php

namespace App\Repositories\User;


use Illuminate\Support\ServiceProvider;


class UserRepoServiceProvide extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {

    }


    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind('App\Repositories\User\UserInterface', 'App\Repositories\User\UserRepository');
    }
}

现在,我们必须在 app.php 文件中添加服务器提供,所以在 config/app.php 中添加 UserRepoServiceProvide 并添加下面一行。

配置/app.php

return [

....

'providers' => [

......,

App\Repositories\User\UserRepoServiceProvide::class,

]

....

]

第 4 步:创建用户模型

我认为我们已经有了用户模型,所以你只需要添加 getAll()、findUser() 和 deleteUser() 函数。但是你也可以通过下面的代码。所以,让我们在你的模型上添加下面的代码。

app/User.php

命名空间应用程序;

use Illuminate\Foundation\Auth\User as Authenticatable;


class User extends Authenticatable
{
    protected $fillable = [
        'name', 'email', 'password',
    ];


    protected $hidden = [
        'password', 'remember_token',
    ];


    public function getAll()
    {
        return static::all();
    }


    public function findUser($id)
    {
        return static::find($id);
    }


    public function deleteUser($id)
    {
        return static::find($id)->delete();
    }
}

第 5 步:在控制器中使用

现在我们准备在控制器中使用我们的存储库模式。因此,让我们在 UserController.php 文件中添加以下代码。

app/Http/Controllers/UserController.php

namespace App\Http\Controllers;


use Illuminate\Http\Request;
use App\Repositories\User\UserInterface as UserInterface;


class UserController extends Controller
{


    public function __construct(UserInterface $user)
    {
        $this->user = $user;
    }


    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $users = $this->user->getAll();
        return view('users.index',['users']);
    }


    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        $user = $this->user->find($id);
        return view('users.show',['user']);
    }


    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function delete($id)
    {
        $this->user->delete($id);
        return redirect()->route('users');
    }
}

现在最后只需触发下面的命令,因为我们必须自动加载类。

作曲家更新

php artisan optimize

我的问题是大多数教程在 UserRepository 中注入了用户模型,所以如果这样做我需要为所有模型分别创建存储库。有什么方法可以让我使用单个存储库并注入模型

【问题讨论】:

    标签: php laravel laravel-5 repository-pattern


    【解决方案1】:

    你可以,但我不确定这是一个好的解决方案。我在我的所有 Laravel 项目中也使用了某种存储库模式,但我的设置不同。

    我有一个BaseRepository,我的所有标准功能如下:

    <?php
    namespace App\Repositories;
    use Carbon\Carbon;
    class BaseRepository {
        public $model;
        public function __construct($model){
            $this->model = $model;
        }
        public function all(){
            return $this->model->all();
        }
        public function getById($id){
            return $this->model->findorFail($id);
        }
        public function store($model){
            $model->created_at = Carbon::now();
            return $model->save();
        }
        public function update($model){
            $model->updated_at = Carbon::now();
            return $model->save();
        }
        public function destroy($model){
            return $model->delete();
        }
    }
    

    这样,在我的控制器中,如果我只需要基本功能(那些在我的 BaseRepository 中),我正在这样做:

    use App\Models\MyModel;
    use App\Repository\BaseRepository;
    
    class XXX extends Controller {
        protected MyModelRepository;
        public function __construct(BaseRepository $baseRepository){
            $this->MyModelRepository = $baseRepository;
        }
    }
    

    这可以满足您的需求,但我认为这不是一个好方法,因为您可能需要一些特定的功能,具体取决于您的模型。所以我正在以这种方式创建专用存储库(每个模型一个):

    <?php
    namespace App\Repository;
    use App\Model\Maj;
    class MajRepository extends BaseRepository {
        public function __construct(Maj $maj){
            $this->model = $maj;
        }
        public function all(){
            return $this->model->with('medias')->with('plugins')->get();
        }
        public function getById($id){
            return $this->model->with('medias')->with('plugins')->findorFail($id);
        }
    }
    

    因此,与我的特定模型相关的这个特定存储库扩展了 BaseRepository 并允许使用所有 BaseRepositories 功能。但它也可以有它自己的特定功能,如您所见。然后我在我的控制器中这样称呼它:

    <?php
    namespace App\Http\Controllers;
    use App\Model\Maj;
    use App\Repository\MajRepository;
    use Illuminate\Http\Request;
    use Carbon\Carbon;
    class WpMajController extends Controller {
        protected $majRepository;
    
        public function __construct(MajRepository $majRepository){
            $this->majRepository = $majRepository;
        }
    
     /**
      * Permet d'afficher la liste des suivi de mises à jour WP
      * @return view
      */
        public function index(){
            $majs = $this->majRepository->all();
            return view('wpMaj.index', compact('majs'));
        }
    

    【讨论】:

      【解决方案2】:

      我看过这些教程很多。这是一种过度设计的方法。完全可以为所欲为。

      最简单的方法如下;

      首先,您要为自己设置一个基础存储库,所有其他存储库都将扩展该基础存储库。我为自己使用了一个常见的,你可以在这里看到:https://github.com/ollieread/toolkit/blob/master/src/Repositories/BaseRepository.php(我正在链接,因为它相当大)。重要的一点是:

      abstract class BaseRepository {
          protected $model;
          protected function make() {
              return new $this->model;
          }
          // rest of the code here
      }
      

      现在我可以为自己创建一个UserRepository,如下所示;

      class UserRepository extends BaseRepository {
          protected $model = User::class;
          public function getAll(): Collection {
              return $this->make()->newQuery()->get();
          }
      }
      

      接口没有混乱(10 次中有 9 次不需要),这意味着您不必将其绑定到 IoC。您可以输入提示UserRepository 并获取实例。

      我也没有注入模型,因为简单地说,你只需要知道类的名称。当你真正需要一个实例时,你可以运行$this-&gt;make()

      关于我的 BaseRepository 的注意事项

      通过神奇的方法,您可以调用getOneById($id)getByCategoryId($categoryId) 之类的东西,而无需自己定义方法。

      getOneById($id) => getOneBy('id', $id)
      getByCategoryId($categoryId) => getBy('category_id', $categoryId)
      

      但是,如果您要经常使用这些方法,我总是建议将它们添加到文档块中。例如,UserRepository 将变为;

      /**
       * @method User make()
       * @method null|User getOneById(int $id)
       * @method Collection getBySurname(string $surname)
       */
      class UserRepository extends BaseRepository {
          protected $model = User::class;
          public function getAll(): Collection {
              return $this->make()->newQuery()->get();
          }
      }
      

      这样 IDE 将自动建议和检测返回类型。

      还有一个删除方法,但如果你愿意,你可以自己覆盖它。

      【讨论】:

        【解决方案3】:

        Repository Pattern 非常棒。 (注意,我认为你应该只在必要的情况下使用存储库模式,而不是用于你的 models 的所有甚至小的实现,以避免过度杀伤和过度设计的项目)

        我猜Repository Pattern 应该用于项目模型的未来维护至关重要的地方,而不是所有小的CRUD 实现。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-03-15
          • 2012-06-02
          • 2016-12-13
          • 2014-08-13
          • 1970-01-01
          • 2014-03-05
          • 2014-09-19
          • 2015-01-22
          相关资源
          最近更新 更多