当前位置:  开发笔记 > 编程语言 > 正文

使用Laravel Eloquent ORM从"胖模型,瘦身控制器"角度工作的做法是什么?

如何解决《使用LaravelEloquentORM从"胖模型,瘦身控制器"角度工作的做法是什么?》经验,为你挑选了1个好方法。

阅读后,我一直在选择其他开发人员的大脑"脂肪模型,瘦身控制器"的概念:

http://culttt.com/2013/07/01/setting-up-your-first-laravel-4-controller/

http://culttt.com/2013/05/13/setting-up-your-first-laravel-4-model/

大多数受访者正在使用我认为的胖控制器.

虽然这个主题已经出现在Stack Overflow上,但我还没有在实践中找到对该方法的详尽描述.

我刚刚在这里找到一个旧的相关问题.



1> Antonio Carl..:
瘦的控制器

您将在PHP(vanilla或Laravel或Symfony)中看到的越来越多的是有史以来最瘦的控制器.这是你已经在Rails中看到的东西,人们也开始称它为六角形(带有其他一些做法).您需要在控制器中使用一行代码,实际上他们说这应该是您所有方法的目标.这是一个例子,是的,比这更多一点,但仍然是瘦的:

repository = $repository;
    }

    public function store()
    {
        try 
        {
            $this->repository->create(Input::all());
        }
        catch (ValidationException $e) 
        {
            return Redirect::back()->withInput()->withErrors($e->all());
        }

        return Redirect::route('posts');
    }

}

控制器是HTTP请求,业务逻辑和表示层之间的桥梁.因此它应该接收一个请求,将其发送到一个注入的对象,该对象将处理它并重定向到负责向客户端(或用户)提供反馈的路由(或呈现视图).其他所有内容,包括验证,都应该发生在您的存储库,服务,模型(MVC,yay!)等中.

但是我们可以以六边形的方式重构这个控制器,以实现每个方法的一行目标:

repository = $repository;
    }

    public function store()
    {
        return $this->repository->create(Input::all(), $this);
    }

    public function createSucceeded()
    {
        return Redirect::route('posts');
    }

    public function createFailed()
    {
        return Redirect::back()->withInput()->withErrors($e->all());
    }

}

基本上,您的存储库类将使用自己的调用者($this)来触发succeededfailed方法.

脂肪库/服务/模型

模型与您的数据太相关,有时它们是您的ORM并直接与您的数据库服务器通信,因此,现在您会看到人们使用存储库和服务作为它们之间的层.

存储库是一个类,通过直接与模型交流,处理并收集应用程序所需的信息.您的应用程序不应该知道在数据库中选择某些信息所需的内容,选择,位置,顺序,分组,这些是有时只有您的模型应该知道的事情,因此这是一个存储库:

class PostRepository implements PostRepositoryInterface {

    private $model;

    public function __construct(PostInterface $model)
    {
        $this->model = $model;
    }

    public function create($input)
    {
        return $this->model->create($input);
    }

    public findBySlug($slug)
    {
        return $this->model->where('slug', $slug)->first();
    }

}

服务

所有不属于您的业务逻辑的东西,主要是外部服务,距离您的应用程序代码最远,构建它们的分离越多越好.为这些服务创建外部包(Composer包)是将它们与其他所有内容分离的好方法,如果你使它们与框架无关,那么你有权获得10个鲟鱼点.在Laravel中,您可以通过集成三种类来创建服务:

1)服务类:负责执行您的服务必须执行的操作,所有服务逻辑都在此处.

2)服务提供商:负责启动您的服务并将其添加到Laravel的IoC容器中,以便随时可以使用,但请注意,Laravel只会在您的应用程序真正使用它们时实例化您的服务类.

3)Facade:允许您使用static(::)语法从应用程序的任何位置访问您的服务:

Mailer::send($user->id, 'Thanks for registering', 'emails.registered');

这是梅勒服务:

服务类

mailer = $mailer;    
    }

    public function send($userId, $subject, $view, $data = [])
    {
        return $this->mailer->queue($view, $data, function($message) use ($userId, $subject)
        {
            $user = Sentry::findUserById($userId);

            $message->to($user->email, $user->name);

            $message->subject($subject);
        });
    }

}

服务提供者

app->bind('acr.mailer', function($app) {

            return new Mailer($app->make('mailer'));

        });
    }

    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {
        return array('acr.mailer');
    }

}

正面



型号/ ORM

这些人应该是高度可交换的,今天你可能使用Eloquent作为你的ORM,将数据存储在数据库中,但你可能需要将其更改为其他东西,有些人将其100%的数据存储在Redis中,所以你更好通过在ORM和域loginc之间使用接口(契约)层来为这样的更改做好准备,并为您的接口而不是具体的类开发.Taylor Otwell在他的书中甚至说你应该完全删除你的模特文件夹.

interface PostInterface {

    public function all();

    public function find($id);

}

class DbPost extends Eloquent implements PostInterface {

}

class RedisPost extends Eloquent implements PostInterface {

}

这背后的想法是轻松交换实现,所以在Laravel中你可以使用IoC容器告诉Laravel你正在使用哪个实现:

App::bind('PostInterface', 'DbPost');

所以,如果你有一个Repository使用你的PostInterface:

class PostRepository implements PostRepositoryInterface {

    private $model;

    public function __construct(PostInterface $model)
    {
        $this->model = $model;
    }

}

Laravel IoC容器将使用DbPost实例自动实例化此存储库.如果您需要将其更改为Redis,则只需更改一行:

App::bind('PostInterface', 'RedisPost');
观点/演示者

最狡猾的是真棒.

查看

视图应仅负责显示信息.视图不应该知道您的模型,服务,存储库或系统中的任何其他内容.视图应该可以被webesigners编辑,因此,你拥有的代码越多,你的非php程序员设计者将添加的bug越多.您的控制器应该从您的存储库收集信息并将它们传递给您的视图:

repository = $repository;
    }

    public function index()
    {
        return View::make('posts.index')->with('posts', $this->repository->getPaginated());
    }

}

您的观点唯一的责任应该是显示数据:

@extends('layout')

@section('contents')
    
    @foreach($posts as $post)
  • {{ $post->title }} - {{ $post->author }} - {{ $post->published_at }}
  • @endforeach
{{ $users->links() }} @stop

主持人

你如何格式化数据?您在视图中编写原始属性,但是您应该在幕后使用演示者,是的,提供您的数据.演示者通常使用装饰器设计模式来格式化要在页面中显示的数据.这是使用Shawn McCool的LaravelAutoPresenter的一个例子:

resource = $user;
    }

    public function author()
    {
        return $this->resource->author->name;
    }

    public function published_at()
    {
        return $this->date($this->resource->created_at);
    }

    public function dateTime($date)
    {
        return \Carbon\Carbon::createFromFormat('d-m-Y', $date, 'Sao_Paulo/Brazil')
                     ->toFormattedDateString();
    }    
}
相关书籍

Taylor Otwell的Laravel:从Apprentice到Artisan

Chris Fidao的实施Laravel

推荐阅读
ERIK又
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有