Каковы методы работы с точки зрения" Толстой модели, тощего контроллера " с Laravel красноречивым ORM? [закрытый]

Я выбирал мозги других разработчиков по концепции "жирных моделей, тощих контроллеров" после прочтения:

большинство респондентов используют то, что я бы назвал контроллерами жира.

в то время как тема подошла к переполнению стека, я не найти подробное описание метода на практике.

Я только что нашел старый вопрос здесь.

1 ответов


Тощий Контроллеры

то, что вы увидите в PHP (vanilla или Laravel или Symfony), все больше и больше-самые тонкие контроллеры. Это то, что вы уже видите в Rails, и люди также начинают называть его (с некоторыми другими практиками) шестиугольным. Одна строчка кода-это все, что вам нужно в вашем контроллере, на самом деле они говорят, что это должно быть целью для всех своих методов. Это пример с, да, немного больше, чем это, но все же тощий:

<?php

class PostController extends Controller {

    private $repository;

    public function __construct(PostRepositoryInterface $repository)
    {
        $this->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!), п.

но мы могли бы преобразовать этот контроллер, в шестиугольный путь, достигнуть ОДН-строк-в-метод цель:

<?php

class PostController extends Controller {

    private $repository;

    public function __construct(PostRepositoryInterface $repository)
    {
        $this->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), чтобы огонь succeeded и failed методы.

Fat Репозитории / Услуги / Модели

модели слишком связаны с вашими данными, иногда они являются вашим 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 packages) для этих служб-хороший способ отделить их от всего остального, и вы, если вы сделаете их агностиками фреймворка, имеете право получить 10 баллов осетровые. В Laravel вы можете создавать сервисы, интегрируя три вида классов:

1) класс обслуживания (es): ответственный за то, что ваша служба должна делать, вся ваша логика обслуживания идет сюда.

2) поставщик услуг: ответственный за загрузку вашего сервиса и добавление его в контейнер IOC Laravel, чтобы он мог быть готов к использованию в любое время, но обратите внимание, что Laravel будет создавать только экземпляры ваших классов услуг, когда ваше приложение действительно их использует.

3) фасад: позволяет получить доступ к службе из любой точки приложения с помощью статического (::) синтаксис:

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

это почтовая служба:

Сервис Класс

<?php namespace ACR\Services\Mailer;

use Illuminate\Mail\Mailer as IlluminateMailer;
use Sentry;

class Service {

    public function __construct(IlluminateMailer $mailer)
    {
        $this->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);
        });
    }

}

Провайдер

<?php namespace ACR\Services\Mailer;

use Illuminate\Support\ServiceProvider as  IlluminateServiceProvider;
use ACR\Services\Mailer\Service as Mailer;

class ServiceProvider extends IlluminateServiceProvider {

    /**
     * Indicates if loading of the provider is deferred.
     *
     * @var bool
     */
    protected $defer = true;

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->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');
    }

}

фасад

<?php namespace ACR\Services\Mailer;

use Illuminate\Support\Facades\Facade as IlluminateFacade;

class Facade extends IlluminateFacade {

    protected static function getFacadeAccessor() { return 'acr.mailer'; }

}

модели / ORM

эти ребята должны быть очень заменяемыми, сегодня вы можете использовать красноречивый как ваш ORM, сохраняя данные в базе данных, но вам может потребоваться изменить его на что-то еще, некоторые Фокс хранят 100% своих данных в Redis, поэтому вам лучше быть готовым к изменениям, как с помощью интерфейса (контракта) слоя между ОРМ и ваш домен loginc и действительно развиваться ваши интерфейсы, а не конкретные классы. Тейлор Отуэлл в своей книге даже говорит, что вы должны полностью удалить свою папку моделей.

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');

Итак, если у вас есть репозиторий, используя свой PostInterface:

class PostRepository implements PostRepositoryInterface {

    private $model;

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

}

контейнер Laravel IoC автоматически создаст экземпляр этого репозитория с экземпляром DbPost. И если вам когда-нибудь понадобится изменить его на Redis, вам просто нужно изменить одну строку:

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

Вид / Ведущие

самый тупой, самый страшный.

вид

вид должен отвечать только за отображение информации. Представления не должны знать о ваших моделях, службах, репозиториях или чем-либо еще остальное в твоей системе. Представления должны редактироваться веб-дизайнерами, поэтому, чем больше кода у вас на них, тем больше ошибок добавит к ним ваш не-php-программист-дизайнер. Ваш контроллер должен собирать информацию из ваших репозиториев и передавать их в ваши представления:

<?php

class PostController extends Controller {

    private $repository;

    public function __construct(PostRepositoryInterface $repository)
    {
        $this->repository = $repository;
    }

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

}

и только ваше мнение должно показать, что данные:

@extends('layout')

@section('contents')
    <ul>
        @foreach($posts as $post)
            <li>
                {{ $post->title }} - {{ $post->author }} - {{ $post->published_at }}
            </li>
        @endforeach
    </ul>

    {{ $users->links() }}
@stop

ведущие

как вы форматируете свои данные? Вы пишете свойства raw в своих представлениях, но вы должен, за кулисами, использовать ведущих, чтобы, да, представить свои данные. Докладчики обычно используют шаблон оформления декоратора для форматирования данных, которые будут представлены на ваших страницах. Это пример использования LaravelAutoPresenter Шона Маккула:

<?php namespace App\Presenters;

use McCool\LaravelAutoPresenter\BasePresenter;

class Post extends BasePresenter {

    public function __construct(UserModel $user)
    {
        $this->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();
    }    
}

Книги

Ларавель Тейлора Отуэлла: от ученика до ремесленника

Крис Fidao и Laravel