ещё по контроллерам вопрос

Духовность™

Продвинутый новичок
ещё по контроллерам вопрос

В моей реализации, контроллеры совершают какие-то действия и отдают результат во View. Например,
PHP:
class News_Controller
{
    // где-то там наверху мы инстанцируем View 

    // метод показа новости, он же action, 
    // отвечающий за получение данных для одной логической страницы сайта
    public function ViewNews()
    {
        // получаем меню сайта 
        $this->view->menu = $this->getMenu();
        
        // получаем данные новости $news по какому-то условию...
        $this->news = $news;
    }
}
ВНЕЗАПНО возникла необходимость получить данные новости с теми же условиями, но в другом контролере. Ну не переписывать же код? Не знаю, верно это или нет, но я захотел из другого контроллера вызвать метод News_Controller::ViewNews();

PHP:
class Oter_Controller
{
    public function otherAction()
    {
        $news_controler = new News_Controller();
        // получаем из view данные новости 
        $this->view->news = $news_controler->getView()->news;
    }
}
В итоге это получилось, но там же сработала и конструкция
PHP:
// получаем меню сайта 
$this->view->menu = $this->getMenu();
определенная в методе ViewNews()

Внимание, вопрос:

1. Правильно ли это - вызывать в одном контроллере (Oter_Controller) другой контроллер (News_Controller)?
2. Если это приемлимо, как избавиться от "второстепенных" операций типа $this->view->menu = $this->getMenu();?
 

HraKK

Мудак
Команда форума
Имхо ты сейчас делаешь то в чем и я ошибся в свое время. Ты используешь контролеры как класс который управляет логикой. А он должен лишь говорить ЧТО в этой модели надо отобразить или выполнить. Андестанд?
 

HraKK

Мудак
Команда форума
Ты должен из другого контролера вызывать News обьект, а не News_Controller
 

флоппик

promotor fidei
Команда форума
Партнер клуба
triumvirat, почитай Архитектуру корп. приложений, почиииитааайй!! )))

HraKK правильно сказал, сформировать данные о себе должна модель. Контроллер должен лишь сказать, какие данные, или в какой форме.

-~{}~ 30.01.09 22:36:

зы. Хотя, построение цепочек контроллеров само по себе тоже допустимо, но не в данном случае.
 

Духовность™

Продвинутый новичок
Ты должен из другого контролера вызывать News обьект, а не News_Controller
тогда это дублирование кода (которого я хочу избежать за счет вызова контроллера News_Controller из Other_Controller), ибо объект news в ViewNews() вызывается примерно так:

PHP:
$news_mapper  = new News_Mapper();
// формирование $params
// ... 
$news = $news_mapper->findByParams($params);
-~{}~ 30.01.09 19:39:

флоппик
да читаю, я читаю. на практике все сложнее!! ;(
 

HraKK

Мудак
Команда форума
Я не говорил что news это модель.
У меня лично где то так:
PHP:
$this->Category->paginator = $Paginator->getCurrentRowset();
$this->Category->articles = $this->Category->getArticles( 'date', 'DESC', $countonpage, $this->offset -1 , true );
$this->view->Category = $this->Category;
или так например:
PHP:
CategoriesCollection::getInstance()->getCategoryById( 1 )->getArticleById(3)->getDescription()->author;
 

serglt

Анус, ой, Ахтунг
Ну дык можно ж добавить метод который генерирует view новостей, без всяких меню и прочих других действий, и вызывать его в методе ViewNews, ну и если надо в других контроллерах. Я лично так делаю если много кода и чтоб копи паста не было, не вижу ничего плохого что контроллеры переплетаются.
 

Beavis

Banned
можно формирование меню надо засунуть в модель, а во всех контроллерах где надо, вызывать
PHP:
$menu = new Menu();
$this->view->menu = $menu->getData();
 

HraKK

Мудак
Команда форума
то в чем разница между моей реализацией?
Разница в том что у тебя получение новости зашито в контроллере. А у меня в ORM классе новостей.
 

Духовность™

Продвинутый новичок
Имхо ты сейчас делаешь то в чем и я ошибся в свое время. Ты используешь контролеры как класс который управляет логикой. А он должен лишь говорить ЧТО в этой модели надо отобразить или выполнить. Андестанд?
Нет, оказывается не андерстенд. Вот тут уроки по Зенду: http://zend-framework.ru/2008/10/nachalo-raboty-s-zend-framework/

У меня тоже самое, что и описано в этом уроке. По сути - одно и тоже. Там тоже логика в контроллере...
 

HraKK

Мудак
Команда форума
У меня тоже самое, что и описано в этом уроке. По сути - одно и тоже. Там тоже логика в контроллере...
PHP:
function indexAction()
    {
        $this->view->title = "My Albums";
        $albums = new Albums();
        $this->view->albums = $albums->fetchAll();
    }
Да неужели?
 

Духовность™

Продвинутый новичок
HraKK
Это черезмерно надуманно-простой пример, как и весь урок. В реальности всё сложнее намного.

Вот в уроке:

PHP:
function editAction()
{
    $this->view->title = "Edit Album";

    $form = new AlbumForm();
    $form->submit->setLabel('Save');
    $this->view->form = $form;

    if ($this->_request->isPost()) {
        $formData = $this->_request->getPost();
        if ($form->isValid($formData)) {
            $albums = new Albums();
            $id = (int)$form->getValue('id');
            $row = $albums->fetchRow('id='.$id);
            $row->artist = $form->getValue('artist');
            $row->title = $form->getValue('title');
            $row->save();

            $this->_redirect('/');
        } else {
            $form->populate($formData);
        }
    } else {
        // album id is expected in $params['id']

        $id = (int)$this->_request->getParam('id', 0);
        if ($id > 0) {
            $albums = new Albums();
            $album = $albums->fetchRow('id='.$id);
            $form->populate($album->toArray());
        }
    }
}
вот у меня теже действия с пользователем:

PHP:
public function edit()
{
    if ($this->current_user->getUser()->id <= 0)
    {
        $this->request->setHeader('Location', '/user/registration/');
        $this->request->sendHeaders();
        exit;
    }

    $this->view->goHtmlTitle()->add( $this->view->lang->html_title );

    $params = array
    (
        'what' => '`id_country`, `country_name'.(LANG == 'en' ? '_en' : '').'` as `country_name`',
        'order' => array('country_name' => 'ASC'),
    );

    $Country_Mapper = new Country_Mapper();
    $this->view->countries = $Country_Mapper->getObjectList_($params)->getData()->getDataAsArray();

    $this->user = $this->current_user->getUser();

    if (Request::isPost())
    {
        if (isset($this->request->user))
        {
            $this->user_mapper = new User_Mapper();
            $this->user = $this->user_mapper->createFromArray($this->request->user);
        }

        $validator = new Validator_Chain(DIR_LANG_VALIDATOR_MESSAGES, 'Registration');

        $validator->add('user_login', new Validator_Simple_Var_Empty($this->request->user->user_login));
        $validator->add('user_login', new Validator_Simple_Char_Password($this->request->user->user_login));
        $validator->add('user_login', new Validator_Simple_User_Login_Exists($this->request->user->user_login, 
                                                                             $this->current_user->getUser()->id));
 
        if ($this->request->user->user_password_1)
        {
            $validator->add('user_password_1', new Validator_Simple_Char_Password($this->request->user->user_password_1));
        }

        if ($this->request->user->user_password_2)
        {
            $validator->add('user_password_2', new Validator_Simple_Char_Password($this->request->user->user_password_2));
        }

        if ($this->request->user->user_password_1 &&
            $this->request->user->user_password_2 &&
            $this->request->user->user_password_1 !== $this->request->user->user_password_2
           )
        {
            $validator->addError('user_password', 'INCORRECT_PASSWORDS');
        }

        $validator->add('user_mail', new Validator_Simple_Var_Empty($this->request->user->user_mail));
        $validator->add('user_mail', new Validator_Simple_Email($this->request->user->user_mail));
        $validator->add('user_mail', new Validator_Simple_User_Mail_Exists($this->request->user->user_mail,
                                                                           $this->current_user->getUser()->id)
                                                                          );

        $validator->add('user_name', new Validator_Simple_Var_Empty($this->request->user->user_name));

        $validator->add('user_age_day', new Validator_Simple_Var_Empty($this->request->user->user_age_day));
        $validator->add('user_age_day', new Validator_Simple_Int_Range($this->request->user->user_age_day, 1, 32));

        $validator->add('user_age_month', new Validator_Simple_Var_Empty($this->request->user->user_age_month));
        $validator->add('user_age_month', new Validator_Simple_Int_Range($this->request->user->user_age_month, 1, 12));

        $validator->add('user_age_year', new Validator_Simple_Var_Empty($this->request->user->user_age_year));
        $validator->add('user_age_year', new Validator_Simple_Int_Range($this->request->user->user_age_year, 1930, date('Y')));

        $validator->add('user_sex', new Validator_Simple_Var_Enum($this->request->user->user_sex, 
                                                                  array('M', 'F'), 'INVALID_RADIO_VALUE'));

        $validator->add('user_country', new Validator_Simple_Var_Empty($this->request->user->user_country));
        $validator->add('user_city', new Validator_Simple_Var_Empty($this->request->user->user_city));
        $validator->add('user_region', new Validator_Simple_Var_Empty($this->request->user->user_region));

        $validator->add('user_url', new Validator_Simple_Url($this->request->user->user_url));

        $validator->validate();

        if ($err = $validator->getErrors())
        {
            $this->view->err = $err;
        }
        else
        {
            $this->user->id = $this->current_user->getUser()->id;
            $this->user->user_url = $this->user->user_url == 'http://' ? '' : $this->user->user_url;
            $this->user_mapper->save($this->user);

            if ($this->user->id)
            {
                // Если новый пароль определён
                if ($this->request->user->user_password_1 && $this->request->user->user_password_2)
                {
                    // Ищем пользователя с новым паролем (не обяхательно)
                    $this->user = $this->user_mapper->findByLoginPassword($this->request->user->user_login,
                                                                          $this->request->user->user_password_1
                                                                         );

                    if ($this->user->id > 0)
                    {
                        $time = time()+60*60*24*31;

                        $this->request->setcookie('id_user', $this->user->id, $time, '/');
                        $this->request->setcookie('user_hash', md5($this->user->user_login.
                                                                   $this->user->user_password.SALT), $time, '/');
                        $this->request->sendCookie();
                    }

                    $redirect_url = '/user/edit/';
                }
                else
                {
                    $redirect_url = '/user/edit/';
                }

                $redirect = new Redirect();
                $redirect->setMessage('user_edit_ok');
                $redirect->setRedirectUrl($redirect_url);
                $redirect->run();
            }
        }
    }

    $this->view->user = $this->user->getData();
}
как видно, реальный код намного сложнее и в контроллере какие-то логические действия - неизбежность...
 

HraKK

Мудак
Команда форума
как видно, реальный код намного сложнее и в контроллере какие-то логические действия - неизбежность...
Ясень пень. Это тоже логика на то он и контролер, просто не надо туда втюривать все что можно и нельзя.

ЗЫ - я бы убился разбераю такую тонну кода) Может валидацию, куда-то вынести?
 

AmdY

Пью пиво
Команда форума
если появляется вложеность третьего и больше уровня, нужно стараться вынести часть в отдельные методы. самый простой способ в твоей ситуации сделать приватный метод _validate()

$redirect = new Redirect();
$redirect->setMessage('user_edit_ok');
$redirect->setRedirectUrl($redirect_url);
$redirect->run();
почему не - $this->_redirect($url, $message); кстати, в верхушке ты почемуто редирект делаешь по другому.

и не засирай $this, в него нужно ложить только то, что используется в других методах, а то у тебя локальная версия глобальных переменных получается.

а по основному вопросу - не парся. код не пишется из паттернов, это паттерны являются примерами типового кода.
 

Духовность™

Продвинутый новичок
и не засирай $this
да, страдал этим раньше, щас осознал

почему не - $this->_redirect($url, $message); кстати, в верхушке ты почемуто редирект делаешь по другому.
redirect - это не совсем HTTP request объект. Это оболочка, которая сначала пишет в базу сообщение user_edit_ok (как минимум) и делает location на указанный URL с ID созданной записи. При ответете сервера извлекается запись с этим ID и показывается текст, мол, всё хорошо, данные сохранены.
 
Сверху