В современном искусстве программирования техника SOLID получила широкое распространение благодаря старому доброму принципу "разделяй и властвуй". В этой статье я хочу осветить некоторые солидные моменты, которые неочевидны новичкам. Для начала я покажу общую архитектуру приложения, так как без нее будет непонятно использование классов и наследований. Так как я буду использовать ресур-контроллер, то маршруты описываются примитивным массивом вида %%(php) 'CustomersController', ]); %% Сейчас он обрабатывает запрос вида http:://localhost/ajax/customers который попадает в совершенно типичный тонкий контроллер из бестпрактикс следующего вида: %%(php) model = $model; parent::__construct(); } } %% он наследуется от AjaxController в котором описаны общие для всех ресурсных контроллеров методы index, show, store и destroy, которые, в свою очередь, работают с моделью-репозитарием содержащим всю логику работы. Для примера рассмотрим метод index: %%(php) getModel($request); $res = $model->getCollection($request); return $res; } %% Как видно, после получения модели-репозитария вызывается метод getCollection, в модели он описан следующим образом %%(php) model; return $class::paginate($this->perPage); } /** * Возвращает класс ресурс-коллекцию * @param Request $request * @return string */ public function getResourceCollection($request) : string { return $this->collection; } /** * Отображает коллекцию моделей в ее представлении * @param Request $request * @return resource */ public function getCollection($request) { $models = $this->getModels($request); $collection = $this->getResourceCollection($request); if ($collection) { return new $collection($models); } return new ResourceCollection($models); } } %% Тогда конечная модель-репозитарий CustomersRepositary примет такой вид: %%(php) $object->id, 'name' => $object->name, ]; } /** * {@inheritdoc} */ public function toArray($request) { $res = []; foreach($this->collection as $object){ $res[] = $this->getResource($object); } return $res; } } %% Итак... после всех проделанных манипуляций при запросе к адресу /ajax/customers у нас должно получиться что то вроде %%(json) {"data": [ {"id": 1, "name": "Иванов"}, {"id": 2, "name": "Петров"}, {"id": 3, "name": "Сидоров"} ]} %% Теперь предположим, что нам необходимо как-то усложнить результат. Пусть, к примеру, при некотором запросе мы хотим получить какое-то дополнительное поле, например возраст покупателей, тогда запрос будет /ajax/customers?withAge=1 Что сделает юный падаван увидив такую задачу? Правильно, полезет менять CustomersCollectionResource на что то вида %%(php) $object->id, 'name' => $object->name, ]; } protected function getResourceWithAge($object) { return [ 'id' => $object->id, 'name' => $object->name, 'age' => $object->age, ]; } /** * {@inheritdoc} */ public function toArray($request) { $res = []; $withAge = $request->get('withAge', false); foreach($this->collection as $object){ if ($withAge) { $res[] = $this->getResourceWithAge($object); } else { $res[] = $this->getResource($object); } } return $res; } } %% Ну оно же работает? Конечно. Но со временем такое программирование приведет к нагромождению if/switch и усложнит понимание того, что здесь вообще происходит. SOLID, а именно SRP говорит о принципе единственности ответственности, поэтому сделаем класс-наследник %%(php) $object->age, ]); } } %% А подключать его будем в CustomersRepositary: %%(php) get('withAge', false)) { return CustomersAgeCollectionResource::class; } return $this->collection; } } %% Что мы этим добились? Представление не должно заниматься проверками входящих данных, само представление-наследник получился тонким, изменяется один метод getResource который наследует данные родителя и обогащает их дополнением в виде возраста. Конечно, можно пойти еще дальше и вынести проверку withAge в контроллер, где и должны происходить такого рода проверки. Для этого нужно создать новый репозитарий CustomersAgeRepositary и перегрузить метод getModel в CustomersController, но я думаю общий принцип этого метода уже понятен.