В зависимости от того, на какую страницу заходит пользователь, подключается нужный контроллер и модель. Часто встречается, что в каком-то контроллере уже реализован определенный метод, который, допустим, получает браузер/ос и этот метод вдруг требуется в другом контроллере. Не копировать же этот метод? Стараюсь избежать даже малейшего повторения кода. Пришел к тому, что надо добавить новый, общий контроллер (бывают, кстати и методы общие). Хотел бы узнать, как правильно реализовать общую часть?
AlikDex: Выходит, что я могу подключить в каком-нибудь bootstrap.php файл с одним трейтом (соответственно, он будет подключаться всегда) и там, где мне требуется использовать повторы кода, я пишу use trait_name и использую методы трейта?
hrvasiliy: зависит от ситуации наверное. Базовый контроллер в любом случае будет абстрактным. От него наследуются все остальные. Также и модель. Лично я бы не стал перегружать абстрактные классы кучей мелких методов с конкретным функционалом, а вынес все в трейты.
Реализуется через общий абстрактный класс контроллера.
abstract class AbstractController
{
public function commonMethod() { }
}
class ConcreteControllerA extends AbstractController { }
class ConcreteControllerB extends AbstractController { }
Можно всё это приправить трейтами:
trait ControllerTrait
{
public function traitMethod() { }
}
/**
* В этом контроллере будут общие методы абстрактного
* класса и методы трейта.
*/
class ConcreteControllerA extends AbstractController
{
use ControllerTrait;
}
/**
* А в этом только общие методы абстрактного класса.
*/
class ConcreteControllerB extends AbstractController
{
}
1. Я уже наследую в каждый контроллер базовый класс контроллера, получается, что базовый класс контроллера еще должен наследовать общий абстрактный класс?
2. Как подключать? - Через bootstrap.php, который подключает все базовые классы и настройки? (т.е. при каждом запросе)
3. В комментариях к вопросу указали на трейты, вы считаете использовать абстрактный класс "лучше"?
hrvasiliy:
1. Если есть методы, которые должны быть реализованы во всех контроллерах, то их логично было бы и вынести в базовый контроллер. Вообще вас никто не ограничивает, можно сколь угодно сложную иерархию контроллеров выстраивать. Главное, чтобы она была логичной, чтобы как можно реже приходилось переопределять методы в классах наследниках.
2. Эм... Не совсем понимаю, в чём проблема, и как это связано с основным вопросом? Вам про autoload и composer ведь известно?
3. По ситуации: в общие классы (кстати, не обязательно абстрактные) выносятся общие методы для всех классов-наследников. Трейты это по сути примеси, то есть в трейте можно объявить нужные методы, и добавлять их в любые классы буквально в пару строк. Получается что-то вроде альтернативы множественному наследованию.
27cm: Вообще, видимо, я что-то затупил, скажем так. Действительно, я же могу вынести просто общие методы будь то это контроллеры или методы в их базовые классы. Не так ли? И проблема будет решена простым способом.
hrvasiliy: в Yii2 архитектура контроллеров и моделей примерно следующая:
abstact class BaseController {}. От него наследуются общий для всех контроллер. class Controller extends BaseController {}. От этого контроллера уже наследуются остальные, например class IndexController extends Controller {}.
Вот. Общие методы( c конкретным функционалом), присущие только контроллерам реализуются в общем классе Controller. У моделей тоже самое. Схема жизнеспособная, логичная и простая.
Общие методы, которые могут быть использованы и там и там можно вынести в трейты.
hrvasiliy: Если эти методы реализованы одинаково, нужны для всех контроллеров, которые наследуются от базового и скорее всего понадобятся для будущих его наследников, то да, можно смело выносить.