YiiFramework 1 функционал в 2 контроллерах

Djos

Новичок
Приветствую вас. Мне интересно как бы вы реализовали, но начнем сначала.

Поступила задача, нужно переделать Карту О под новый дизайн. В проекте уже сделаны 3 Карты, Карта Т, Карта Г, а Карта О осталось старой. Карта может быть моей(смотришь свою карту) или пользователя(смотришь у кого-то карту). В моей свой url(/account/card), у пользователя (/user/<ID>/card). Дизайн Карт у моей и пользователя одинаковый. Отличие минимальные, у моей есть кнопки, и список, а у пользовательской свои кнопки и часть интерфейса скрыта. Между собой Карты по дизайну отличаются сильнее. Поэтому решил что лучше пусть у каждой Карты свои шаблоны. По задачи надо сделать Карту О.

Наследование:
CardController <- AccountController <- MainController – (далее буду писать account\CardController)
CardController <- UserController <- MainController – (далее буду писать user\CardController)

AccountController->user = авторизованный пользователь.
UserController->user = просматриваемы пользователь.

Как реализовано сейчас. Рядом с «user\CardController» лежит «user\CardTrait» в котором был описаны все функции контролер(actionIndex, actionLoadTab). Шаблоны лежали «user\view». В контролерах «user\CardController» и «account\CardController» был подключен trait «user\CardTrait».

account\CardController
use user\CardTrait

user\CardController
use user\CardTrait

Изначально я начал разрабатывать мою Карту О. Решил что лучше будет создать свой контроллер для карты «account\cards\OController». Шаблоны положил в «account\views\cards\o». В «user\CardTrait» подправил.
Код:
public function actionIndex()
{
 $user = $this-> user ;

 if ($user->status == 1) {
  return \Yii:: $app ->runAction('account/cards/o'); //перенаправляем Карты О на новый контроллер
 } elseif ($user->status == 2) {
  return $this->_getTaIndex();
 } elseif ($user->status == 3) {
  return $this->_getGuideIndex();
 }

 return null;
}
Все было замечательно, но когда начал делать саму механику моя карта или пользовательская карта, пришел в тупик. При такой реализации, когда заходим по /user/ID/card, в «user\CardTrait->actionIndex()», $user будет который запрашиваем, но потом идет runAction(), который создает «account\cards\OController» и в нем уже $user авторизованный(т.к. базовый контроллер уже «AccountController»). Тут пошел ко 2 параметру в runAction() и в нем стал передавать $user.
return \Yii::$app->runAction('account/cards/o', ['user' => $user]);

Все было прекрасно, но появилась проблема номер 2. В интерфейсе есть ajax загрузка часть другого интерфейса. Url создавалась через Url::to() и пользовательской Карты О, запросы получались /account/cards/o/<action>. А action есть логика по пользователю, в итоге туда шли данные от авторизованного пользователя, а смотрим мы пользовательскую Карту О.

Как я предложить сделать:

Функционал в «account\cards\OController» положить в «components\cards\OTrait»,
«user\CardTrait» переместить «components\cards\CardTrait».

В классах:

account\cards\CardController
use components\cards\CardTrait

account\cards\OController
use components\cards\OTrait

user\cards\CardController
use components\cards\CardTrait

user\cards\OController
use components\cards\OTrait

Дальше в account\CardController
Код:
public function actionIndex()
{
 $user = $this->user;

 if ($user->status == 1) {
  return \Yii::$app->runAction('account/cards/o'); //перенаправляем Карты О на новый контроллер
 } else {
  return \Yii::$app->runAction('account/cards/card'); //перенаправляем на Карты Т и Г
 }

}
Дальше в user\CardController
Код:
public function actionIndex()
{
 $user = $this->user ;

 if ($user->status == 1) {
  return \Yii::$app->runAction('user/cards/o'); //перенаправляем Карты О на новый контроллер
 } else {
  return \Yii::$app->runAction('user/cards/card'); //перенаправляем на Карты Т и Г
 }

}
В итоге реализация Карты О в 1 месте, при этом можно у контроллеров «account|user\cards\OController» добавить функционал или изменить его.
Url у моей Карты О - /account/card/, а у ajax - /account/cards/o/<action>.
Url пользовательской Карты О - /user/<ID>/card, ajax - /user/cards/o/<action>?id=<ID>. Сделать /user/<ID>/cards/o/<action> не получилась, сайт незнает такой роутер.

В yii я новенький. Может есть лучше реализация.
Какие у вас идеи? Что думаете про мою реализацию?
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
думаю, что ты скорее художник, чем инженер: цветам уделяется намного большее внимание, чем смыслу
 

Djos

Новичок
До инженере мне далеко. У меня есть задача, мне интересно как бы к этому подошли другие. Критика и анализ помогает дальнейшему росту. Я старался как то донести информацию. Допусках что возможно не все понятно, но без общения, я не смогу уточнить. И если вы хотели меня задеть, вы в этом при успели. Надеюсь что вы хоть что то от этого получили.
Прощу вас, если вам что то не понятно, укажите что. Это в моих целях. Мы взрослые люди и не стоит переходить на личное.
 

AmdY

Пью пиво
Команда форума
@Djos тебе самому не кажется, что твоё решение грамоздкое и запутанное? Зачем тебе плодить роуты, контроллеры, перенаправление, трейты, если ты сам верно описал что надо делать.
Между собой Карты по дизайну отличаются сильнее. Поэтому решил что лучше пусть у каждой Карты свои шаблоны.
Меняй шаблон имя шаблона в зависимости от владельца карты и всё, зачем остальные костыли?
 

Djos

Новичок
Меняй шаблон имя шаблона в зависимости от владельца карты и всё, зачем остальные костыли?
У каждой карты Т, Г, О - свои данные, значит своя логика где описать логику работы карт, где мне менять шаблоны от владельцев карт?
Есть 2 url, /account/card и /user/<ID>/card. У каждого свой контроллер, они между собой не как не пересекаются, но у Карты О которую я реализовываю, логика между моей и пользовательской карты одинаковая. И как эту логику лучше всего разместить по 2 контроллерам. Неужели банально копи-пас, но это же дублирование кода?
 

WMix

герр M:)ller
Партнер клуба
Неужели банально копи-пас, но это же дублирование кода?
если это о контроллере, то в подобном копипасте нет проблем. это другая рута, это другой data-provider (появляется новый input параметр <ID>) не известно как этот проект будет развиваться дальше. зачем себе уже в самом начале связывать руки?
 

Djos

Новичок
если это о контроллере, то в подобном копипасте нет проблем. это другая рута, это другой data-provider (появляется новый input параметр <ID>) не известно как этот проект будет развиваться дальше. зачем себе уже в самом начале связывать руки?
Наверно думаю что так не правильно. ООП и придумали чтоб не было дублирование кода, а если он есть значит плохая архитектура проекта.

Сейчас вот думаю, а не лучше все action сделать, а в контроллерах уже подключать какие action нужны. Сейчас есть в контроллере 3 action(actionIndex. actionLoadFirstTab. actionLoadSecondTab). Их можно поместить в 1 action, OActionIndex. И уже в контролерах сделать подключения в функции actions(). Это так на вскидку.
 

Djos

Новичок
Можно с UrlRule задать правила:
/user/<ID>/<controller>/<action> => /account/<controller>/<action>

Когда заходишь по /user/<ID>/cards/o, то Url::to(['first-tab']) выдает /account/cards/o/first-tab, а нужно /user/<ID>/cards/o/first-tab.
Можно ли это как то изменить, чтоб было такой же url, по которому пришел?
 
Сверху