Две недели назад я обсуждал статью "((45))". После этого появился огромный интерес к демонстрации шаблона "Репозиторий" в действии. Сегодня мы посмотрим, как репозиторий подходит для ((http://github.com/rtablada/laravel-faq Laravel Faq Page)). Просто говоря, репозиторий - это абстрактный слой между каким-либо хранилищем и вашим приложением или бизнес-логикой. Это примерно то же, как если бы вы могли подойти к полке для книг и взять нужные из них одним движением руки. Итак, давайте посмотрим на задачи, которые мы хотим решить взаимодействием между хранилищем данных или слоем постоянного хранилища. 1. Выборка всех заданных вопросов 2. Создание пустого вопроса для связывания формы в представлении 3. Страничный вывод запросов 4. Создание и хранение вопроса 5. Выборка вопросов по первичному ключу 6. Обновление вопроса с первичным ключом и некоторым массивом данных 7. Удаление вопроса по первичному ключу Если вы уже знакомы с Laravel, то у вас, вероятно, появится вопрос: "что не так с Eloquent?". Единственное не совсем стандартное его использование снаружи от модели - обновление вопроса по первичному ключу и атрибутам. Однако я скрыл несколько требований. Первое - наши вопросы используют пакет ((https://github.com/rtablada/eloquentRankable Eloquent Rankable)) и наши коллекции выборок должны быть отсортированы по важности. Второе - страничный вывод должен быть только для отвеченных вопросов. Таким образом, мы думаем о репозитории как о методе исключения специфической логики базы данных из наших контроллеров. (Что, несомненно, делает Тейлора очень счастливым.) Для начала мы создадим интерфейс для именования наших методов и их аргументов. Этот интерфейс позже будет реализован в нашем хранилище, использующем Eloquent. В %%(t)src/Rtablada/LaravelFaq/Repositories/FaqRepository.php%% создадим следующее. %% faqModel = $faqModel; } public function newInstance(array $attributes = array()) { if (!isset($attributes['rank'])) { $attributes['rank'] = 0; } return $this->faqModel->newInstance($attributes); } public function paginate($perPage = 0, $columns = array('*')) { $perPage = $perPage ?: Config::get('laravel-faq::pagination.length'); return $this->faqModel->rankedWhere('answered', 1)->paginate($perPage, $columns); } public function all($columns = array('*')) { return $this->faqModel->rankedAll($columns); } public function create(array $attributes) { return $this->faqModel->create($attributes); } public function find($id, $columns = array('*')) { return $this->faqModel->findOrFail($id, $columns); } public function updateWithIdAndInput($id, array $input) { $faq = $this->faqModel->find($id); return $faq->update($input); } public function destroy($id) { return $this->faqModel->destroy($id); } } %% Как вы видите, мы использовали синтаксис %%(t)ranked*%% из Eloquent Rankable в некоторых наших методах. Этот синтаксис в нашем контроллере ограничит свободу тому, кто хочет создать "плоскую" файловую версию пакета. Это так же убирает логику из нашего контроллера, что и является основной целью нашей абстракции. Теперь, если мы захотим что-то изменить в логике получения записей из БД, нам не потребуется искать обращения к ней во всех наших контроллерах и изменять их. Наконец, в %%(t)src/Rtablada/LaravelFaq/LaravelFaqServiceProvider.php%% мы должны добавить связывания и сказать Laravel, что всякий раз, когда мы запрашиваем экземпляр %%FaqRepository%%, мы на самом деле хотим использовать реализацию %%FaqRepositoryEloquent%%. Мне нравится выносить связывания в отдельные методы - это позволяет впоследствии изменять логику, которая не загромождает функцию загрузки %%boot%%. В boot добавим следующее: %% $this->bootRepositories(); %% И далее создадим функцию %%bootRepositories%%: %% public function bootRepositories() { $this->app->bind('Rtablada\LaravelFaq\Repositories\FaqRepository', 'Rtablada\LaravelFaq\Repositories\FaqRepositoryEloquent'); } %% И это все. Теперь у вас есть быстрая абстракция, позволяющая изменять логику и даже производить изменения всей структуры.