Render site in the update after hook

Don’t ask me what i want to achieve with that. (It’s about fetching things from the output after saving)

I like to render() the homepage in the site.update:after hook. The problem: site() has no render() method. And the homepage has its old content:

'site.update:after' => function ($newSite) {
    $newSite->homepage()->render();
},

What can i do?

I don’t think you’ll get any useful answer without elaborating what you want to achieve. Cause this all doesn’t make a lot of sense to me (calling the render() method in an update hook.

Why should the home page has new content? This is the site update hook, so the content changed is of site not of home.

Hi Nico.

Okay let’s go deeper into my aim: I have fields over my pages and site. The values of this fields needs to be saved in presence of its content. (On update - with a special condition)
I decide to render the current page on save and it works well. But if the user change something on the side, any page needs to be rerendered with the new values (in this case: the homepage).

But how? I need something like render a page with an injection of the new side variables or a side:update:after:after hook.

But how would the other pages, e.g. home, be already updated in site.update:after? Wouldn’t you need to do $site->homePage()->update() first inside site.update:after?

Pages will be rendered with the page.update:after hook. The side doesn’t changed in this case:

'page.update:after' => function ($newPage, $oldPage) {
	$newPage->render(['fetch_vars' => true]);
},

I think you are running into a race condition. If you sleep briefly before rendering, then it seems to work. But I don’t think this is very stable. And you would not be able to use the cache, unless you flush it manually.

'site.update:after' => function ($newSite) {
            sleep(1);
            $page = $newSite->find('home');
            $result = $page->render();
            F::write(kirby()->root('index') . '/after.txt', $result);
        },

I tried sleep as well. But then the whole update process sleeps as well. I would need a kind of a async method for that. But i’m not familiar to this.

Yes, I didn’t present that as a solution, just as an explanation.

1 Like

But it’s a good solution approach…

Still don’t understand what you want with the rendered HTML. You’ll probably need to send this to a queue, so it’s done in the background.

Let say i like to create custom CSS, that needs to be created, when the visitor call the page.
I send fetch_vars to the page. If this fetch_var presents, it starts fetching things. And at the end of the page, it writes the fetched values to a file.

For now i don’t need the HTLM output. But it could be nice, if i recieving there the fetched vars. So i don’t need to make a call inside the pages end.

I knew as i wrote this line, that it’s inevitable to do it. :crazy_face:

So why exactly don’t you write this file from the hook?

This i do. This has nothing to do with the actual problem:

But let me try it…

No, of course not, it wouldn’t make sense, at least not considering how Kirby works.

It’s hard to judge without knowing the details, but rendering an entire page just to write some CSS to a file seems somehow wrong and not very resource efficient.

You’re right. For me it took a while to notice that side != homepage. :wink:

The more elegant solution is, to using controllers:

'controllers' => [
	'site' => function () {
		return [
			'foo' => "No value given"
		];
	}
],
'site.update:after' => function ($newSite, $oldSite) {
	$foo = $newSite->homepage()->controller()['foo'];
	// Write $foo or pin it on the hat
},

In the template you could use:

<?php $foo = site()->foo()->isTrue() ? "Foo is True" : "Foo is False"; ?>

But also in this way:

Shure i know, you can also achieve this example directly in the hook with:

$foo = $newSite->foo()->isTrue() ? "Foo is True" : "Foo is False"; 

But in my case, $foo is a class with methods:

<?php $foo->appendFoo('Something from here')` ?> 
<?php $foo->appendFoo('Something from there')` ?> 

And at the end i call $foo->writeValues() to make my dreams come true.

And why is that a problem?

And your example $foo variable here contains a boolean, not a class.

(Maybe i used the foo expression to often :speak_no_evil:)

I just mention it, in case some other people likes to take some samples of code to make something great with kirby. To use a class with methods is not a (or the) problem.

In my last posts i shown two examples.

  1. $foo is just a variable to set, when you need it.
  2. $foo is a class, that is defined in the controller. (Sorry, i forgot to give the code of the initializing the class):
'controllers' => [
	'site' => function () {
		return [
			'foo' => new FooClass()
		];
	}
],