Return html content of another page in controller

Is there a way through Content Representation to get the html of a page and pass it as argument in a plugin running on a controller?

Plus: would it be possible to decide what to get from the html file? Eg fetching only the <main> tag and everything inside it?

thanks, af

I think you can render the page via the tpl::load function (more info). That way you wouldn’t need to do the hassle with setting up a “hack”-content representation, but could render the page into a variable inside the controller.

Only grabbing the <main> contents, would be possible with a regex on the returned string from the tpl::load function I think.

The important part here is to set the third parameter to true, so that you can store your HTML in a variable:

$html = tpl::load(kirby()->roots()->templates() . '/template.php', $data, true);

You can also use $kirby->render().

$html = $kirby->render(page('projects'));
echo $html;

thank you both (some more chars because otherwise i cannot post)


so i ended up testing both options only today and:

  1. the tpl:: approach spits back an error saying that Call to a member function title() on null from the code i have in my header.php snippet

  2. the $kirby->render approach keeps saying it is rendering a null object, no matter which page or url i tried to load

the only reason i went back to this is that i was using file_get_contents() to call another page and render it through mPDF. But on the production server with SSL, this gives me an error (could be because is php 5.6 — i’m not the sysadmin in this case and can’t upgrade the server software stack).

it would be great if i did not have to work with ssl certificates and php, and just being able to fetch the html of this page to feed into the mPDF function :smiley:



<!doctype html>
<html lang="<?= site()->language() ? site()->language()->code() : 'en' ?>">

  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">

  <title><?= $site->title()->html() ?><?php e($page->template() != 'home', ' • ' . $page->title()->html())?></title>
  <meta name="description" content="<?= $site->description()->html() ?>">

  <?= css('assets/dist/css/styles.min.css') ?>

<body id="t" class="pd-b--3 msc">
  <?php if($page->template() != 'order'): ?>
    <header class="z-2 pd-t--1 pd-b--1 pd-h--1 pd-h--2__md p-st p--t p--l p--r x x-cl x-rw__md x-abl bgc-wh" role="banner">
      <h1 class="d-ib ft-2 ft-3__lg pd-r--2 pd-b--05 pd-b--0__md"><a href="<?= $site->url() ?>" class="bd-b--0"><?= $site->title()->html() ?></a></h1>
      <?php snippet('nav') ?>
  <?php endif ?>

The problem with using the tpl::load() method is that you have to pass all data first down to the template in the $data variable and then again down to the snippets.

Can’t you grab the HTML via Ajax?

Thank you for clarifying.

What about the $kirby->render() mode? Why is it throwing an error?
Also, I can’t find any documentation about it.

Yes, I can probably use AJAX for this as well (which I never used before tbh), just was trying to avoid extra overheads and keep it as basic as possible. I have the feeling AJAX might throw some CORS problem or some SSL-related hiccups.

Will look into it!


I don’t know, it doesn’t in my setting if I simply add the two lines I posted above into another template.

does it change the fact that i am calling $kirby->render() on a controller?

OK, working perfectly on a template, the dumb error is that in a controller there is no $kirby variable — and feeding that into the mPDF plugin directly was hiding the kirby error.

In your controller, $kirby doesn’t seem to be defined:

$html = kirby()->render(page('projects'));
1 Like

Thank you! It works now.

hey sorry, bringing this up again.

so the kirby()->render() works perfectly in certain pages, and not in others. i debugged a bit, changing bits here and there and see if it was making a difference, but it seems it doesn’t and i have no clear idea of why it is like this.

the error i get is

Call to a member function price() on boolean

this is the snippet of code:

  $price_t = 0;
  foreach($o_desc as $item) {
    // this line ↓ //
    $item_price = page('shop/' . str::slug($item[0]))->price();
    $price_s = str::replace($item_price, ['€', ','], '');
    $price_t += $price_s * $item[1];
  $vat = round((6 / 100) * $price_t, 2);
  $price_vat = round($price_t + $vat, 2);

it sounds a bit similar to this other error i was having when using the tpl:: method

Call to a member function title() on null

but in this case I don’t get why in certain pages it works and not in others…

let me know if you need more context for this!

The error message means that you don’t have a page object but a boolean here, so obviously this bit

page('shop/' . str::slug($item[0]))

doesn’t give you a page. Since I don’t know what the $o_desc array or each $item contains, I can’t tell. But I can’t repeat it often enough:

NEVER call an object’s method without making sure you really have an object! Then at least you don’t get an error message (even if it means you don’t get the expected result either).

Hi, just in case someone needs it. In Kirby3 you can use the following solution to get the html of a page based on its ID.

$single_page = $pages->findById('test');
$html = $single_page->render([
        'name' => 'John Doe'

You can have access to this variables in the template just by using ‘$name’ and in the controller you have to pass it through.

return function ($page, $name) {
    $headline = $page->headline()->kt();
    $subheadline = $page->subheadline()->kt();
    return [
        'header' => $headline . ' - ' . $subheadline . ' : ' . $name

… and for rendering content representations you can use the option contentType -> e.g.

$html = $page->render([
    'variables' => $variables
], 'txt');