Jump to content

Cannot hook before Page::render


owzim
 Share

Recommended Posts

While this is working perfectly:

public function init() {
    $this->addHookAfter('Page::render', $this, 'replaceEverything');
} 

This is not, nothing happens:

public function init() {
    $this->addHookBefore('Page::render', $this, 'replaceEverything');
} 

replaceEverything looks simply like this:

public function replaceEverything($event) {
    $event->return = "REPLACED, YO!";
} 


I want to replace the rendering entirely, so a hook after would not be efficient, since I don't need the previous rendering.

What's wrong?

  • Like 1
Link to comment
Share on other sites

$event->replace=true;

You mean like this?

public function replaceEverything($event) {
    $event->replace = true;         
    $event->return = "REPLACED, YO!"; 
} 

That did nothing =(

Link to comment
Share on other sites

Thanks WillyC ... still not working ...

This is my method:

public function replaceEverything($event) {
    $event->replace = true;         
    $event->return = "REPLACED, YO!"; 
} 

it still does not do anything when using (the page gets rendered as usual):

public function init() {
	$this->addHookBefore('Page::render', $this, 'replaceEverything'); 
}

But it works, so it replaces when using:

public function init() {
	$this->addHookAfter('Page::render', $this, 'replaceEverything'); 
}

=(

Link to comment
Share on other sites

If you hook before render, there's no $event->return (yet). So you can't replace anything, only if you echo out your stuff and exit() it will work. This has been like this ever since, and I know because I played with it, but never actually needed it or seen any use for it.

  • Like 2
Link to comment
Share on other sites

Thanks Soma, the echo and exit method might be sufficient for my case. Have to look into it further.

Still, I am wondering why the $event->return is not working here. I would consider this a bug, since it's documented here:

http://processwire.com/api/hooks/ (scroll to "How can my hook read (or modify) the return value of the hooked method?")

that you can influence the returned value of hookable methods this way, with no stated exception.

Link to comment
Share on other sites

This Page::render is kind of a special case, because there isn't actually a Page::render() method if you look in the Page class. It is itself a hook added by the PageRender.module. So you can't replace it since the method doesn't actually exist. Instead, you'd have to hook the source of that Page::render hook, which is actually: PageRender::renderPage

  • Like 2
Link to comment
Share on other sites

In your case, if your before hook replaces PageRender::renderPage, you should be able to just echo your output directly. You don't need to exit or stop execution. Meanwhile, I will look into making $event->return; work for before hooks with $event->replace = true; 

Link to comment
Share on other sites

Meanwhile, I will look into making $event->return; work for before hooks with $event->replace = true; 

I figured it out. Since PageRender::renderPage is providing the rendered output in $event->return; rather than the function returning it (since it is actually a hook to a non-existent Page::render), then you have to do the same. As a result, this code in your before hook function should work:

$otherEvent = $event->arguments(0); // grab event provided to PageRender::renderPage
$otherEvent->return = "<p>Hello World</p>"; // plug in our value
$event->replace = true; // prevent PageRender::renderPage from being called
  • Like 3
Link to comment
Share on other sites

  • 8 years later...
On 8/6/2013 at 6:21 PM, ryan said:

I figured it out. Since PageRender::renderPage is providing the rendered output in $event->return; rather than the function returning it (since it is actually a hook to a non-existent Page::render), then you have to do the same. As a result, this code in your before hook function should work:

$otherEvent = $event->arguments(0); // grab event provided to PageRender::renderPage
$otherEvent->return = "<p>Hello World</p>"; // plug in our value
$event->replace = true; // prevent PageRender::renderPage from being called

Hi @ryan, is it something that is still relevant ?

I'm trying to use this for a module I'm writing but it doesn't seem to work as the after hook is still executed, even with `replace` set to true. Here's a boiled down sample of my setup:

public function init() {
	$this->addHookBefore("PageRender::renderPage", $this, "beforeRenderPage");
	$this->addHookAfter("PageRender::renderPage", $this, "afterRenderPage");
}

protected function beforeRenderPage($event) {
	$parentEvent = $event->arguments(0);
	$page        = $parentEvent->object;
	$markup      = $this->wire()->cache->getFor($this, "cache-$page->id");
	if($markup) {
		$parentEvent->return = $markup;
		$event->replace = true;
	}
}

protected function afterRenderPage($event) {
	$parentEvent = $event->arguments(0);
	$page        = $parentEvent->object;
	$this->wire()->cache->saveFor($this, "cache-$page->id", $parentEvent->return);
}

Thank you in advance for your help.

Link to comment
Share on other sites

9 hours ago, monollonom said:

I'm trying to use this for a module I'm writing but it doesn't seem to work as the after hook is still executed, even with `replace` set to true.

I don't think $event->replace = true is supposed to have any effect on whether an "after" hook fires for a method - it just means that the code inside the hooked method will not execute. If you're trying to stop subsequent hooks from firing then have a look at $event->cancelHooks (https://processwire.com/api/ref/hook-event/)

  • Thanks 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...