开发者

How do I preserve the value of a variable after an HMVC sub-request in Kohana 3.1?

I'm having an issue with preserving the value of a variable after an HMVC sub-request in Kohana 3.1.3.1 and am wondering how best to approach/fix it. I thought that additional requests in Kohana were isolated from each other, but it doesn't seem to be the case...

First of all, I've created a controller to extend the 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
}

}

And here's an example of what one of the controllers looks like:

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
    }
}

Now I want one of my other controllers to be able to pull the output from the events controller, without the template. Controller_Website (above) takes care of excluding the template from the output, but consider this:

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
    }
}

So when my template calls echo $this->page_info->page_title; (remember, my template is only being included in the search controller's output and not the event controller's output), I'm expecting it to return "S开发者_开发技巧et in Search controller" but instead it returns "Set in Events Controller"

The problem is that this action_filtered() method is very long and I've set up a couple routes that use this method to output several event pages (like filtering events by year, month, venue, city, etc.) so it doesn't make sense to duplicate this method in my search controller. Hence the need for an HMVC request. When the filtered action is called as a main/initial request, it makes sense to set values in $page_info but when it's called as a sub-request, I need to preserve the values set in the search controller, or whatever the initial controller is.

Of course, I could create an if statement in the events controller to only update these values if it's a main request, but that's less than ideal, obviously. There must be a way to make this sub-request run isolated from the initial request?

What am I doing wrong, or what's the best way to go about solving this?

Thanks in advance!

DM


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

Its incorrect. Request::factory() call returns an initial Request instance (so it uses current URI value). You need a generated URI for your HMVC call:

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

PS. Sorry, its my mistake. Your code seems to be valid in 3.1. Anyway, try to change it with Request->uri() usage.


I found the problem/solution!

The problem is that in my Controller_Website I had this in my 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);

The problem is the bind_global – which is actually working as it's supposed to by letting you change the value of this variable after the fact... (A very neat feature indeed.)

The workaround/solution was to force the template to use only the original page_info by detecting if it was an initial/main request. So at the very end of the action_before() method of Controller_Website where it says:

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

I added this line to the end of that if statement:

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

This line is redundant on initial/main requests, but it means that any additional sub-requests can still have access to their own page_info values without affecting the values used in the template. It appears, then, that if you assign a property to a view and then attempt to bind_global() the same property with new values, it doesn't overwrite it and uses the original values instead... (Which is why this solution works.) Interesting.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜