Как сохранить значение переменной после подзапроса HMVC в Kohana 3.1?

У меня возникла проблема с сохранением значения переменной после подзапроса HMVC в Kohana 3.1.3.1, и мне интересно, как лучше подойти/исправить это. Я думал, что дополнительные запросы в Кохане изолированы друг от друга, но, похоже, это не так...

Прежде всего, я создал контроллер для расширения Controller_Template:

abstract class Controller_Website extends Controller_Template {
public  $page_info;
public  $allow_caching;

public function before()
{
    // ... more unrelated code here ...

    // Only do this if auto_render is TRUE (default)
    if ($this->auto_render === TRUE AND $this->request->is_initial())
    {
        // Set our Page_Info to the values we just loaded from the database
        $this->page_info        = clone $this->navs[$slug];
    }

    // ... more unrelated code here ...
}

public function after()
{
    // ... more unrelated code here ...

    // For internal requests, let's just get everything except for the template
    if (! $this->request->is_initial())
    {
        $this->response->body($this->template->main_view->render());
    }

    // Only if auto_render is still TRUE (Default)
    if ($this->auto_render === TRUE AND $this->request->is_initial())
    {
        // ... more unrelated code here ...
        // ... get stuff from the database to populate the template ...

        // now render the response body
        $this->response->body($this->template->render());
    }

    // ... more unrelated code here...
    // including setting headers to disable/enable caching
}

}

А вот пример того, как выглядит один из контроллеров:

class Controller_Events extends Controller_Website {
    public function action_filtered()
    {
        // ... do some stuff ...

        // and set some values 
        $this->page_info->page_title    = 'Set in Events controller';

        // and some more stuff including generating some output
    }
}

Теперь я хочу, чтобы один из моих других контроллеров мог получать выходные данные от контроллера событий без шаблона. Controller_Website (выше) позаботится об исключении шаблона из вывода, но учтите следующее:

class Controller_Search extends Controller_Website {
    public function action_index()
    {
        // ... do some stuff ...

        // now let's include the result from our events controller
        $this->template->main_view->events  = Request::factory()
                                                ->controller('events')
                                                ->action('filtered')
                                                ->execute();

        // and set some values 
        $this->page_info->page_title    = 'Set in Search controller';

        // and some more stuff including generating some output
    }
}

Поэтому, когда мой шаблон вызывает echo $this->page_info->page_title; (помните, что мой шаблон включается только в выходные данные контроллера поиска, а не в выходные данные контроллера событий), я ожидаю, что он вернет "Установить в контроллере поиска", но вместо этого он возвращает "Установить в контроллере событий"

Проблема в том, что этот метод action_filtered() очень длинный, и я настроил пару маршрутов, которые используют этот метод для вывода нескольких страниц событий (например, фильтрация событий по году, месяцу, месту проведения, городу и т. д.), поэтому он не делает смысла дублировать этот метод в моем поисковом контроллере. Отсюда необходимость в запросе HMVC. Когда отфильтрованное действие вызывается как основной/начальный запрос, имеет смысл установить значения в $page_info, но когда оно вызывается как подзапрос, мне нужно сохранить значения, установленные в контроллере поиска или в любом другом исходном контроллере.

Конечно, я мог бы создать оператор if в контроллере событий, чтобы обновлять эти значения только в том случае, если это основной запрос, но, очевидно, это далеко не идеально. Должен ли быть способ сделать этот подзапрос изолированным от исходного запроса?

Что я делаю не так, или как лучше решить эту проблему?

Заранее спасибо!

DM


person DM.    schedule 27.05.2011    source источник
comment
Одно уточнение, просто чтобы быть уверенным: в начальном запросе вы повторяете какую-то переменную, и кажется, что ее значение было изменено путем вызова запроса HMVC?   -  person Tadeck    schedule 27.05.2011
comment
@Tadeck - да, переменная всегда отображается только в представлении шаблона (например, заголовок страницы). После запуска запроса HMVC $this->page_info->page_title (например) остается тем, что было установлено в контроллере событий, и я больше не могу изменить его в контроллере поиска, даже если я попытаюсь изменить его в методе after() контроллера поиска. .   -  person DM.    schedule 27.05.2011


Ответы (2)


Request::factory()
    ->controller('events')
    ->action('filtered')
    ->execute();

Это неправильно. Request::factory() возвращает начальный экземпляр Request (поэтому он использует текущее значение URI). Вам нужен сгенерированный URI для вашего вызова HMVC:

Request::factory(Request::current()->uri(array(
    'controller' => 'events', 
    'action' => 'filtered'
)))->execute();

ПС. Извините, это моя ошибка. Ваш код кажется действительным в 3.1. В любом случае, попробуйте изменить его с помощью Request->uri().

person biakaveron    schedule 27.05.2011

Я нашел проблему/решение!

Проблема в том, что на моем Controller_Website у меня было это в моем action_before():

// Create a new DM_Nav object to hold our page info
// Make this page info available to all views as well
$this->page_info = new DM_Nav;
View::bind_global('page_info', $this->page_info);

Проблема заключается в bind_global, который на самом деле работает так, как должен, позволяя вам изменить значение этой переменной постфактум... (Действительно, очень удобная функция.)

Обходной путь/решение состояло в том, чтобы заставить шаблон использовать только исходный page_info, определяя, был ли это начальный/основной запрос. Итак, в самом конце action_before() метода Controller_Website, где говорится:

// Only if auto_render is still TRUE (Default)
if ($this->auto_render === TRUE AND $this->request->is_initial())
{

Я добавил эту строку в конец этого оператора if:

    $this->template->page_info  = $this->page_info;
}

Эта строка избыточна для начальных/основных запросов, но это означает, что любые дополнительные подзапросы могут по-прежнему иметь доступ к своим собственным page_info значениям, не затрагивая значения, используемые в шаблоне. Таким образом, получается, что если вы назначаете свойство представлению, а затем пытаетесь bind_global() использовать то же свойство с новыми значениями, оно не перезаписывается и вместо этого используются исходные значения... (Вот почему это решение работает.) Интересно.

person DM.    schedule 27.05.2011