如何在Kohana 3.1中的HMVC子请求之后保留变量的值?

时间:2011-05-27 00:39:25

标签: php templates request kohana hmvc

我遇到了在Kohana 3.1.3.1中的HMVC子请求之后保留变量值的问题,并且我想知道如何最好地接近/修复它。我认为Kohana中的其他请求彼此隔离,但似乎并非如此......

首先,我创建了一个控制器来扩展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

2 个答案:

答案 0 :(得分:0)

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

不正确。 Request::factory()调用会返回初始 Request实例(因此它使用当前URI值)。您需要为HMVC调用生成URI:

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

<强> PS。对不起,这是我的错。您的代码似乎在3.1中有效。无论如何,尝试使用Request-&gt; uri()用法进行更改。

答案 1 :(得分:0)

我发现了问题/解决方案!

问题是我的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()相同的属性,它就不会覆盖它并使用原始值代替... (其中这就是为什么这个解决方案有效。)有趣。