#laravel
#web
#dev
#seo
Generate a sitemap for dynamic URLs with a scheduled generator and keep your sitemap updated and site optimized for search engines.
Note! roumen/sitemap is compatible ONLY with Laravel 8 or lower, use spatie/laravel-sitemap for Laravel 9 or higher. The setup is identical for both packages, I have labeled code necessary for each one.
The sitemap will help your site to set a higher position on search engines, for instance, once you submit your sitemap to the Google search console your pages will have higher priority on Google to be served to clients.
Packets, packets
We will use a Laravel generator called roumen/sitemap OR spatie/laravel-sitemap, we need to install this packet to our project and we can do that with the composer.
Add this line to the console and execute it.
Laravel 8 or lower:
composer require roumen/sitemap
Laravel 9^:
composer require spatie/laravel-sitemap
Configuration
After installation is done we will create a Controller named SitemapBuilder and add our new packet to the project config/app.php providers array.
Just add this line at the bottom of the providers and save the file. Not required for the spatie/laravel-sitemap.
//...other providers...,
Roumen\Sitemap\SitemapServiceProvider::class,
Now publish the package with this line.
Laravel 8 or lower:
php artisan vendor:publish
Create the model or controller for our builder class with the console command, we will create the controller for this example.
php artisan make:controller SitemapBuilder
Code and setup
Now go to the controller and create a function to catch all static and dynamic links. We have queried all posts and we will rewrite the file every week using automation, we could just update the file and fill the posts from the last post entered into a sitemap, but since our slugs are created from posts titles we will overwrite the file just to keep everything updated.
It is a good idea to add a URL field to the post table so the URL never changes and gets updates that are not explicit, it will prevent shared links to become invalid once we update the title. In our case, it does not matter since all our posts are queried by post (id) and will provide the correct response no matter what we write after "id", for instance, number “11/”. eg. https://techtoapes.com/post/11/some_optional _text.
If you do not want to include all routes then just add them manually and do not use a loop for routes.
Laravel 8 or lower:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Models\Post;
class SitemapBuilder extends Controller
{
public static function handle($token){
if (app()->runningInConsole() == false || $token != env('SITEMAP_TOKEN')) {
return false;
}
$posts = Post::all();
$routes = Route::getRoutes();
$sitemap = App::make("sitemap");
foreach ($routes as $route) {
$sitemap->add($route->uri, '1.0', 'weekly');
}
foreach ($posts as $post) {
$url = urlencode($post->title);
$sitemap->add($url, $post->updated_at, '1.0', 'weekly');
}
$sitemap->store('xml', 'sitemap.xml', public_path());
return true;
}
}
Laravel 9^:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Models\Post;
use Spatie\Sitemap\SitemapGenerator;
use Spatie\Sitemap\Sitemap;
class SitemapBuilder extends Controller
{
public static function handle($token){
if (app()->runningInConsole() == false || $token != env('SITEMAP_TOKEN')) {
return false;
}
$posts = Post::all();
$routes = Route::getRoutes();
$sitemap = Sitemap::create();
foreach ($routes as $route) {
$sitemap->add($route->uri);
}
foreach ($posts as $post) {
$url = urlencode($post->title);
$sitemap->add(("/post/{$post->id}/{$url}"), $post->updated_at, '1.0', 'weekly');
}
$sitemap->writeToFile(public_path('sitemap.xml'));
return true;
}
}
Now, we could add an authorization check for who can make the sitemap by a user authorization but since we will set this builder to execute every week as the automated method that approach would not be too practical so we use the $token we have created in our .env file just for this.
Add to the .env file this line.
SITEMAP_TOKEN="your_token_9SDA18329DA34DASDSDAVA23323FDS"
Great, we have finished the builder, only thing left is to automate this so we never ever need to think about it while it does its task for us.
Automate builder
Open the App/Console/kernel.php file and create a schedule for the sitemap builder to execute every week.
$schedule->call(function () {
SitemapBuilder::handle(env('SITEMAP_TOKEN'));
})->weekly();
Alternatively, we could use a custom Cronjob but this seems practical enough and easy to customize and works on the same principle.
Console Commands
For the first time, we can use the console to call our builder, we will create a Laravel command for it.
php artisan make:command SitemapBuilderCommand
Now in App/Console/commands/ edit this file.
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Http\Controllers\SitemapBuilder;
class SitemapBuildCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'sitemap-build';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Build sitemap of the site and store it in the public folder as .xml file.';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
SitemapBuilder::handle(env('SITEMAP_TOKEN'));
return Command::SUCCESS;
}
}
Execute this command in the console for the first time, later it will run on schedule without the need for human action. We can check the content of our file sitemap.xml stored in the public/ directory.
php artisan sitemap-build
Schedule test
To check that schedule automation is working you can run the following command or change weekly() to everyMinute() and wait.
Should list at least one cronjob.
php artisan schedule:list
This will open the schedule console interface, write the function listed to the console, it probably will be named Callback, and then press ENTER.
php artisan schedule:test
Callback
Check your sitemap.xml file. It should be all there.
Stay online.
[root@techtoapes]$ Author Luka
Login to comment.