Dynamische sitemap.xml in CakePHP 3 erstellen

CakePHP

Schritt 1. Anlegen einer Action im Controller.

In meinem Beispiel lege ich die Action im PagesController an: src/Controller/PagesController.php

...
    public function initialize()
    {
        parent::initialize();
        $this->loadComponent('RequestHandler');
    }
...
    public function sitemap()
    {
        $conditions = ['Pages.enabled' => true];
        $pages = $this->Pages->find('all')
            ->select(['id', 'slug', 'modified'])
            ->where($conditions)
            ->order(['Pages.modified'=>'DESC'])
            ->limit(200);

        $newsTable = TableRegistry::get('News');
        $conditions = ['News.enabled' => true];
        $news = $newsTable->find('all')
            ->select(['id', 'slug', 'modified'])
            ->where($conditions)
            ->order(['News..modified'=>'DESC'])
            ->limit(50);

        $this->set(compact('pages', 'news'));
        $this->viewBuilder()->layout('ajax');
        $this->RequestHandler->respondAs('xml');
    }

Wie man sieht, will ich in der Sitemap alle aktiven Seiten (Pages) und Neuigkeiten (News) einbauen. Für das Rendern als XML response benötigt Cake die RequestHandler Komponente.

Schritt 2. Anlegen einer sitemap View: src/Template/Pages/sitemap.ctp

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
    <url>
        <loc><?= $this->Url->build('/',true); ?></loc>
        <lastmod><?php echo $this->Time->toAtom(time()-4200); ?></lastmod>
        <priority>1.0</priority>
    </url>
    <?php foreach($pages as $page):?>
    <url>
        <loc><?= $this->Url->build(['controller' => 'Pages', 'action' => 'view', 'id' => $page->id, 'slug' => $page->slug], true);?></loc>
        <lastmod><?php echo $this->Time->toAtom($page->modified); ?></lastmod>
        <priority>0.<?php echo rand(5,9); ?></priority>
    </url>
    <?php endforeach; ?>
    <?php foreach($news as $page):?>
    <url>
        <loc><?= $this->Url->build(['controller' => 'News', 'action' => 'view', 'id' => $page->id, 'slug' => $page->slug], true);?></loc>
        <lastmod><?php echo $this->Time->toAtom($page->modified); ?></lastmod>
        <priority</priority>
    </url>
    <?php endforeach; ?>
</urlset>

Schritt 3. Route konfigurieren: config/routes.php

...
Router::scope('/', function ($routes) {
    $routes->connect('/sitemap.xml', array('controller' => 'Pages', 'action' => 'sitemap'));
...