MVC загрузка контроллеров

buuni

Новичок
Всем доброго вечера! Мне 15 лет, не судите строго, может быть я упустил какие-то элементарные вещи, но прошу сильно не ругаться :)

Вообщем так. Я начинаю осваивать MVC концепцию для удобного разделения кода, но тут у меня возникает один вопрос. У меня есть контроллер, модель и представление соответственно.

PHP:
<? 
class Controller_index extends Controller {

	public function __construct()
		{
			$this->model = new Model_index();
			$this->view = new View();
		}
	
	public function action_index()
	{	
		$data = $this->model->get_data();
		$this->view->generate('main_view.php', 'template_view.php', $data);
?>
В generate вторым параметром передается основной шаблон и последним - $data - массив, далее уже в нужные места выводится, но в $data хранятся только значения из модели, а мне например нужно подгрузить еще несколько блоков, которые используют другую модель в основной шаблон. Как это лучше сделать ? Заранее генерировать в модели или подгружать через AJAX? Может есть другие варианты, потому-что я себе это немного смутно представляю ? Надеюсь найдутся люди которые смогут направить на путь верный!

Если вдруг не очень понятно описал суть вопроса, поправьте, исправлю!
Спасибо!
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Ну, вид может отображать не только модель, но и другой вид, например.
 

Zvook

Новичок
А это чья реализация MVC ? Это какойто фреймворк? Или ты сам делаешь?
У тебя же $data это массив, так создай ему кастомный элемент типа $data['my_additional_model'] и затолкай туда другую модель. Или третьим параметром в методе generate() передавай массив из моделей типа array('data' => $data, 'my_model' => $my_model)
 

Василий М.

Новичок
generate должен быть не в контроллере. generate надо делать самым последним образом, где-то во front controller примерно.
 

Absinthe

жожо
generate должен быть не в контроллере. generate надо делать самым последним образом, где-то во front controller примерно.
Не согласен.

Я считаю, что если метод контроллера не имеет generate/redirect/json/xml метода, то должен вызываться такой метод во фронт-контроллере с действием по умолчанию.
Но если имеет - то это нормальное поведение метода контроллера.
 

Василий М.

Новичок
у контроллера не может быть generate/redirect/json/xml методов.
контроллер - лишь прослойка между моделью и видом
отдавать в xml - задача вида
генерировать шаблоны должен тоже вид
делать redirect - задача тоже front-controllera, redirect должен быть представлен в виде отдельного объекта.
т.е. процесс таков:

1. HTTP-запрос
2. Определение контроллера
3. Взаимодействия с моделью
3.1 Нужен редирект? Возвращаем объект редиректа во FC, осуществляем.
3.2. Нужно отдать результат в виде HTML/XML/JSON? Отдаем объект View соответствующего типа. View знает о используемом шаблоне.

PHP:
// Движок. Аппликейшин. Fron Controller. Как угодно. 
class Application ...
    /**
     * Основной метод приложения, запускающий конкретные контроллеры
     * и отдающий в output результат.
     *
     * @param void
     * @return void
     */
    public function run()
    {
        $uri = $this->context->getRequest()->getRequest(self::REQUEST_VAR_NAME, 'string');

        if ($uri === '')
        {
            $uri = '/';
        }

        // Определяем контроллер по URL 
        if (!$this->compareRequestWithUriRoutes($uri))
        {
            if (!$this->compareRequestWithStandartUriMap($uri))
            {
                $this->context->getResponse()->clearHeaders();
                $this->context->getRequest()->getRequest()->setModuleName(new Krugozor_Http_UriPartEntity('404'));
                $this->context->getRequest()->getRequest()->setControllerName(new Krugozor_Http_UriPartEntity('404'));
            }
        }

        $controller_name = $this->getControllerClassName
        (
           $this->context->getRequest()->getRequest()->getModuleName()->getCamelCaseStyle(),
           $this->context->getRequest()->getRequest()->getControllerName()->getCamelCaseStyle()
        );

        // Инстанс контроллера 
        $controller = new $controller_name($this->context);
        // Запуск контроллера и получаение рузультата. Результат может быть любого типа.
        $result = $controller->run();

        // Результат не является объектом  - ошибка
        if (!is_object($result))
        {
            throw new RuntimeException(__METHOD__ . ': Не получен результат от работы контроллера ' . $controller_name);
        }

        // HTML, JSON, XML что угодно = это View 
        if ($result instanceof Krugozor_View)
        {
            // Если в запросе присутствует notif, значит необходимо получить во view
            // информацию, переданную с предыдущей страницы и вывести её на экране.
            if ($notif = $this->context->getRequest()->getRequest('notif', 'decimal'))
            {
                $redirect = new Krugozor_Notification($this->context->getDb());
                $redirect->findById($notif);

                if ($redirect->getId())
                {
                    $result->setNotification($redirect);
                }
            }

            // генерация шаблона
            $result->run();

            $this->context->getResponse()->sendCookie()->sendHeaders();

            echo $result->getOut();
        }
        // Redirect - тип редирект 
        else if ($result instanceof Krugozor_Notification)
        {
            $this->context->getResponse()->setHeader('Location', $result->getRedirectUrl())
                                         ->sendCookie()
                                         ->sendHeaders();
        }
        // Image - тип для вывода изображений 
        else if ($result instanceof Krugozor_Module_Common_Model_ImagePng)
        {
            $this->context->getResponse()->sendHeaders();

            imagepng($result->getGdResource());
        }
        // и т.д.
    }
 

WMix

герр M:)ller
Партнер клуба
Василий М.
в слове front-controller есть слово controller... В классическом MVC нет слова front-controller
но конечно же удобно иметь значение по умолчанию

отдавать в xml - задача вида -- согласен если это не автогенератор (и view изначально подразумевает xml. Переключает же между xml и html только controller)
генерировать шаблоны должен тоже вид -- вид это сам шаблон а что ты имел в виду под генерировать?
 

флоппик

promotor fidei
Команда форума
Партнер клуба
МВС - это парадигма, а не набор жестких правил, регулирующих что там должно быть, а что нет.
у контроллера не может быть generate/redirect/json/xml методов.
больше аргументов нет?
 

Вурдалак

Продвинутый новичок
Василий М., с каждым instanceof где-то умирает котёнок. Зачем вводить различия между XML и PNG с точки зрения фронт-контроллера?
 

fixxxer

К.О.
Партнер клуба
Вурдалак
Из за отсутствия перегрузки методов иногда приходится.

Но $result instanceof Krugozor_Module_Common_Model_ImagePng это конечно ппц :)
 

Вурдалак

Продвинутый новичок
fixxxer, например? Вообще проще и логичнее возвращать объект типа Response, в котором уже будут headers и контент. Можно ввести свои внутренние заголовки по аналогии с X-Accel-Redirect для прочих нужд (controller forward, например).
 

fixxxer

К.О.
Партнер клуба
$result = $this->doSmth();
$this->display($result);

function display(ResultInterface $Result) {
$Result->writeTo($this->Response);
}

function display(integer $result) {
$this->Response->status($result);
}

ну грубо говоря. А так то конечно, угу.

Я, кстати, возвращаю instanceof Result, а в Response пишу на уровне фронт-контроллера, это позволяет легко делать всякие hmvc. Собственно у меня фронт контроллер это такой же ControllerInterface как и все остальные, условность.
 

buuni

Новичок
А это чья реализация MVC ? Это какойто фреймворк? Или ты сам делаешь?
У тебя же $data это массив, так создай ему кастомный элемент типа $data['my_additional_model'] и затолкай туда другую модель. Или третьим параметром в методе generate() передавай массив из моделей типа array('data' => $data, 'my_model' => $my_model)
Нет, не фреймворк, где-то вычитал, где-то скопировал, где-то сам :)

Да, я в принципе сейчас понимаю как можно передать другую модель, но, я думаю что есть какие-то более рациональные способы.
Допустим, пользователь перешел в раздел "Новости" (www.../news), соответственно подгружается контроллер "controller_news", далее там идет обращение к модели "model_news", там реализуется вся логика, далее возвращается массив с полученными данными, то бишь $data. В нем хранятся только данные полученных новостей. Дальше все поступает в вид и там реализуется. Вот в чем вопрос. Я могу конечно в модели "model_news" подгружать другие модели, допустим модель с пользователями online и потом в представлении уже выводить этот блок, но это получается как-то не рационально, создавать в каждой модели метод с получением этого блока. Может быть можно как-то обойтись без этого ?
Может быть я чего-то не допонимаю, подскажите! Спасибо !
 

WMix

герр M:)ller
Партнер клуба
МВС - это парадигма, а не набор жестких правил, регулирующих что там должно быть, а что нет.
в мвс есть, должны быть модель вью и контроллер иначе нет смысла называть это мвс, все остальное может присутствовать.
отсюда front-controller это не обязательный элемент это часть controller! как впрочем и рутер.. но это удобно вырезать наружу!
вопрос front-controller или controller смысла не имеет... (это парадигма, а не набор жестких правил) но по парадигме управляет всеже controller видами, а не вид подстраивается самостоятельно
 

keltanas

marty cats
buuni
Почитай, как у других реализовано.
А вообще, конечно, для 15 лет хороший код )) Некоторые в 25 такое не пишут... Но, сильно ZF1 напоминает...

Хотя, как тут порой замечают, современные фреймворки те еще примеры для подражания... Иногда лучше проще, зато лучше...

Как говорится:
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
 
Сверху