Seth Phat
Seth Phat Blog

Follow

Seth Phat Blog

Follow
Quickly create a Sitemap for your Laravel site

Photo by GeoJango Maps on Unsplash

Quickly create a Sitemap for your Laravel site

Seth Phat's photo
Seth Phat
ยทJan 25, 2023ยท

3 min read

Hi guys,

Today I'm gonna share to you my snippet to generate a whole sitemap. Quick and reliable.

Creating a sitemap is easy and you don't have to install any dependencies (probably you will googling like "laravel sitemap").

Let's get started.

FYI I suppose you would know what is the "sitemap" and its benefits for SEO, so I won't explain it here.

Sitemap Structure

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    <url>
        <loc>http://localhost:3000</loc>
        <changefreq>always</changefreq>
        <priority>1</priority>
        <lastmod>2023-01-20T14:59:42.000000Z</lastmod>
    </url>
</urlset>

So, a normal view render of Laravel would get the job done easily, or if you prefer the OOP way, you can use SimpleXML of PHP.

SimpleXML for Sitemap

This requires the simplexml extension from PHP.

First I will create an entity class to hold the information of the url

class SitemapNode
{
    public const CHANGE_FREQUENCY_ALWAYS = 'always';
    public const CHANGE_FREQUENCY_DAILY = 'daily';

    public function __construct(
        public string $url,
        public string $changeFrequency,
        public float $priority = 1,
        public ?Carbon $lastModifiedDate = null
    ) {
    }

    public static function make(): SitemapNode
    {
        return new self(...func_get_args());
    }

    public function appendSitemap(SimpleXMLElement $element): self
    {
        $url = $element->addChild('url');

        $url->addChild('loc', $this->url);
        $url->addChild('changefreq', $this->changeFrequency);
        $url->addChild('priority', $this->priority);

        $this->lastModifiedDate
            && $url->addChild('lastmod', $this->lastModifiedDate->toISOString());

        return $this;
    }
}

FYA my application only needs daily or always option, feel free to add more for your use cases.

Then, I create a Collection like this (from my command, so I registered a cron job for every 12 hours, it will render the sitemap) and append all the URLs of my application, including:

  • Static pages (home page, about us, contact us,...)

  • Dynamic pages (with slug)

$urls = collect([
    SitemapNode::make(
        $this->getWebUrl(), 
        SitemapNode::CHANGE_FREQUENCY_ALWAYS
    ),
    SitemapNode::make(
        $this->getWebUrl('about-us'), 
        SitemapNode::CHANGE_FREQUENCY_ALWAYS)
    ),
    // add more URLs here, eg dynamic pages,...
]);

Okay then let's render and store it:

$xml = new SimpleXMLElement('<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" />');

$urls->each(fn (SitemapNode $node) => $node->appendSitemap($xml));

// parse to string
$xmlString = $xml->asXML();

// store to any places
file_put_contents(
    public_path('sitemap.xml'),
    $xmlString
);

A mix between OOP and Func-programming, it looks super clean, isn't it? ๐Ÿ˜†

Blade

Easiest solution without any dependencies too. So you will need an array to hold the urls with the needful information: loc, changefreq, priority and lastmod , eg:

$urls = [
    [
        'loc' => 'https://sethphat.dev', 
        'changefreq' => 'always',
        'priority' => 1,
        // lastmod can be null or unexists
        'lastmod' => Carbon::now(),
    ],
    // .... more
];

Then render it via blade:

// sitemap.blade.php
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" />
    @foreach ($urls as $url)
        <url>
            <loc>{!! $url['loc'] !!}</loc>
            <changefreq>{{ $url['changefreq'] }}</changefreq>
            <priority>{{ $url['priority'] }}</priority>
            @if (isset($url['lastmod']))
                <lastmod>{{ $url['lastmod']->toISOString() }}</lastmod>
            @endif
        </url>
    @endforeach
</urlset>

Get the rendered string:

use Illuminate\Support\Facades\View;

$renderedSitemap = View::make('sitemap', compact('urls'))->render();

// STORE TO DISK

That's all :p

Conclusion

Well, that's simply that, things don't have to be much more complicated and you don't need to install any dependency.

Fewer dependencies, happier/easier life & maintenance.

Not to mention, everything above is testable under unit testing too.

Cheers!

ย 
Share this