Модели
Модели — основа вашего приложения. Логика (контроллеры и маршруты), так же как и виды (представления данных — например, в HTML) — всего лишь средство для пользователя взаимодействовать с вашими моделями. Самый типичный пример логики, содержащейся в модели — бизнес-логика.
Примеры функциональности, которая может осуществляться моделью:
- Работа с базами данных;
- Файловый ввод/вывод;
- Взаимодействие с вёб-сервисами.
Предположим, что вы пишите блог. Вам наверняка потребуется модель «Сообщение». Посетители могут комментировать ваши заметки, поэтому вам также понадобится модель «Комментарий». А если пользователи будут комментировать, значит нам нужна будет модель «Пользователь». Уловили?
Библиотеки
Библиотеки — это классы, выполняющие действия, не привязанные конкретно к вашему приложению. Например, это может быть библиотека для создания PDF-документов из HTML. Эта задача, пусть и сложная, не специфична конкретно для вашего проекта — такие вещи и называются «библиотеками».
Для создания библиотеки просто поместите её класс в папку libraries. Например, мы напишем библиотеку с единственным методом, который будет выводить на экран переданную ему строку. Создадим файл printer.php в папке libraries с таким содержимым:
<?php
class Printer {
public static function write($text) {
echo $text;
}
}
Теперь в любом месте своего проекта вы можете написать PHPPrinter::write('Вывод с помощью write().');
и библиотека будет загружена автоматически при обращении к ней.
Автозагрузка классов
Модели и библиотеки очень легко использовать благодаря автозагрузчику классов Laravel. Больше информации дано в статье «Автозагрузка классов».
Как это сделать?
Мы все слышали мантру: «Контроллеры должны быть тонкими!». Но как это применимо в реальности? Возможно, часть проблемы — в слове «модель». Что, в сущности, оно означает? Насколько этот термин вообще полезен? Многие связываю «модель» с понятием «база данных», что ведёт к раздутым контроллерам с лёгкими моделями, обращающимися к БД. Давайте посмотрим, какие у нас есть альтернативы.
Что если мы вообще сотрём папку «models» и назовём её как-то более уместно? Действительно, давайте назовём её так же, как и наше приложение. Возможно, мы работаем над сайтом отслеживания спутников, который называется «Trackler» — поэтому мы создадим папку trackler в папке application.
Порядок! Теперь мы разделим наши классы на entities («сущности»), services («сервисы») и repositories («хранилища»). Создадим для каждой группы свою папку внутри папки trackler и посмотрим, что с ними делать дальше.
Сущности
Сущности («entities») — хранилища данных вашего приложения. В общем случае они просто содержат набор свойств. В нашем проекте есть сущность Location («расположение») со свойствами latitude («широта») и longitude («долгота»). Её код может выглядеть так:
<?php namespace Trackler\Entities;
class Location {
public $latitude;
public $longitude;
public function __construct($latitude, $longitude) {
$this->latitude = $latitude;
$this->longitude = $longitude;
}
}
Выглядит хорошо. Теперь, когда у нас есть сущность, мы можем поговорить о других двух папках.
Сервисы
Сервисы («services») содержат процессы нашего приложения. В нашем тестовом проекте Trackler у нас может быть форма, где пользователь вводит GPS-координаты. Нам нужно удостовериться, что введённые координаты действительно верные — иными словами нам нужно проверить сущность Location. Итак, внутри папки services мы можем создать папку validators , содержащую следующий класс:
<?php namespace Trackler\Services\Validators;
use Trackler\Entities\Location;
class Location_Validator {
public static function validate(Location $location) {
// Проверяем переданный экземпляр Location...
}
}
Отлично! Теперь у нас есть отличный способ тестирования нашего класса валидации в отрыве от контроллеров и маршрутов. Итак, мы проверили положение (Location) и готовы его сохранить. Что теперь?
Хранилища
Хранилища («repositories») предоставляют интерфейс для доступа к данным. Они сохраняют и получают сущности вашего приложения. В нашем примере с сущностью Location нам нужно хранилище, где бы она могла быть сохранена. Мы можем хранить её используя любой удобный механизм — СУБД, Redis или что-то ещё более экзотичное. Рассмотрим этот пример:
<?php namespace Trackler\Repositories;
use Trackler\Entities\Location;
class Location_Repository {
public function save(Location $location, $user_id) {
// Сохраняем положение ($location) переданного $user_id...
}
}
Теперь у нас есть чёткое разделение между программными сущностями, сервисами и хранилищами. Это значит, что мы можем вставлять в наши сервисы и контроллеры хранилища-заглушки и тестировать их, не затрагивая остальные части приложения. Мы также можем переключить проект на совершенно другой метод хранения данных без изменения сервисов, сущностей или контроллеров. Мы достигли отличного разделения сфер интересов.