Rechain object variables in plugin

I’m trying to get into plugins for kirby and created an automated process to virtually develop a sitemap.xml, when the URI calls it.

This is my result:

if ( $_SERVER['REQUEST_URI'] == '/sitemap.xml' ) :
    header('Content-type: text/xml; charset="utf-8"');
    echo '<?xml version="1.0" encoding="utf-8"?>';
    $ignore = array('sitemap', 'error', 'impressum', 'datenschutz');
    ?>
    <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
      <?php foreach($pages->index()->visible() as $p): ?>
        <?php if( in_array($p->uri(), $ignore) ) continue ?>
      <url>
        <loc><?php echo html($p->url()) ?></loc>
        <lastmod><?php echo $p->modified('c') ?></lastmod>
        <priority><?php echo ($p->isHomePage()) ? 1 : number_format(0.5/$p->depth(), 1) ?></priority>
      </url>
      <?php endforeach ?>
    </urlset>
    <?php
    die();
endif;

But when I enter the domain with the /sitemap.xml URI – I get this error:

Notice: Undefined variable: pages in /kirby/site/plugins/sitemap/sitemap.php on line 13 Fatal error: Call to a member function index() on null in /kirby/site/plugins/sitemap/sitemap.php on line 13

So how can I rechain the object variables for my plugin?

$pages = pages();

gives no result :frowning:

Solved myself. I was missing one step… :wink:

$site  = site();
$pages = $site->pages();

Instead of doing it this way, you can also use a route.

This was also my idea, but I don’t want to put so much code into config.php – where would it make sense to store a function to fire?

e.g.

c::set('routes', array(
    array(
        'pattern' => 'sitemap.xml',
        'action'  => sitemap()
    )
));

and

<?php

function sitemap() {

    $site  = site();
    $pages = $site->pages();

    header('Content-type: text/xml; charset="utf-8"');
    
    echo '<?xml version="1.0" encoding="utf-8"?>';
    
    $ignore = array('sitemap', 'error', 'impressum', 'datenschutz');
    
    ?>
    
    <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    
        <?php foreach($pages->index()->visible() as $p): ?>
            <?php if( in_array($p->uri(), $ignore) ) continue ?>
            <url>
                <loc><?php echo html($p->url()) ?></loc>
                <lastmod><?php echo $p->modified('c') ?></lastmod>
                <priority><?php echo ($p->isHomePage()) ? 1 : number_format(0.5/$p->depth(), 1) ?></priority>
            </url>
        <?php endforeach ?>
        
    </urlset>
    
    <?php

}

?>

sitemap() function maybe as a controller file? or better as a plugin?

Ok, I’ve got it. I think this is a nice solution:

c::set('routes', array(
    array(
        'pattern' => 'robots.txt',
        'action'  => function() {
            include_once('site/config/functions.php');
            return robots();
        }
    ),
    array(
        'pattern' => 'sitemap.xml',
        'action'  => function() {
            include_once('site/config/functions.php');
            return sitemap();
        }
    )
));

To have a central place for all my additional functions I’m including an extra file. This gives my site a better performance, because it only includes the functions when the router really hits.

Thanks for the inspiration @lukasbestle!

The most elegant way would be to put the code into a plugin in site/plugins/sitemap/sitemap.php. The plugin can then register the route like so:

kirby()->routes(array(
    array(
        'pattern' => 'sitemap.xml',
        'action'  => ...
    )
));

Related:

Plugins:

Thanks for your help. Alot of good suggestions here. I love this community <3

1 Like