DEV Community

Laravel Tuts
Laravel Tuts

Posted on

How to Automatically Generate an XML Sitemap in Laravel

December 11, 2022・Originally published at laraveltuts.com・8 min read

How often should I update my sitemap? What should I include in it? Should I create a new sitemap every time. I add or remove a page from my site?

The sitemap is a file that contains links to all pages on your site. This helps search engines crawl your site better and index your pages faster.

Sitemaps are essential for SEO (search engine optimization). They allow search engines to crawl your entire site and index its contents.

We are going to create a XML Sitemap for our posts using a spatie/laravel-sitemap package.

Follow the below Step-by-Step Guide on how to automatically generate an XML Sitemap in Laravel Application.

How to Automatically Generate an XML Sitemap in Laravel

  • Step 1: Install Laravel Application
  • Step 2: Create Database and Configure
  • Step 3: Installing spatie/laravel-sitemap Package
  • Step 4: Creating Post Model, Migration and Controller
  • Step 5: Create Dummy Records for Post
  • Step 6: Create Sitemap Command
  • Step 7: Scheduled Command in Console Kernel
  • Step 8: Testing

Step 1: Install Laravel Application

Firstly, we will install a laravel application. To install a laravel application run the following code in terminal as show in figure.



composer create-project --prefer-dist laravel/laravel laravel-sitemap

cd laravel-sitemap


Enter fullscreen mode Exit fullscreen mode

Install Laravel Application

Step 2: Create Database and Configure

Let create database in phpmyadmin for our project for adding posts and then we will create those posts sitemap later.

We are creating a database with name “laravel-sitemap” as you can see in below image.

Create Database

After creating database we are going to configure it to our laravel application. To configure the database in laravel. First open .env from our project root directory and enter the database details as show below.



DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel-sitemap
DB_USERNAME=root
DB_PASSWORD=


Enter fullscreen mode Exit fullscreen mode

Database Configure

Now run the migration to create a default tables like users table etc.



php artisan migrate


Enter fullscreen mode Exit fullscreen mode

Database Migration

Step 3: Installing spatie/laravel-sitemap Package

We are using spatie/laravel-sitemap package to generate our posts sitemap. We are going to install the package via composer using a following command in terminal.



composer require spatie/laravel-sitemap


Enter fullscreen mode Exit fullscreen mode

Installing spatie/laravel-sitemap Package

The package will automatically register itself.

Configuration Package

You can override the default options for the crawler. First publish the configuration:



php artisan vendor:publish --provider="Spatie\Sitemap\SitemapServiceProvider" --tag=sitemap-config


Enter fullscreen mode Exit fullscreen mode

This will copy the default config to config/sitemap.php where you can edit it.



use GuzzleHttp\RequestOptions;
use Spatie\Sitemap\Crawler\Profile;
return [
    /*
     * These options will be passed to GuzzleHttp\Client when it is created.
     * For in-depth information on all options see the Guzzle docs:
     *
     * http://docs.guzzlephp.org/en/stable/request-options.html
     */
    'guzzle_options' => [
        /*
         * Whether or not cookies are used in a request.
         */
        RequestOptions::COOKIES => true,
        /*
         * The number of seconds to wait while trying to connect to a server.
         * Use 0 to wait indefinitely.
         */
        RequestOptions::CONNECT_TIMEOUT => 10,
        /*
         * The timeout of the request in seconds. Use 0 to wait indefinitely.
         */
        RequestOptions::TIMEOUT => 10,
        /*
         * Describes the redirect behavior of a request.
         */
        RequestOptions::ALLOW_REDIRECTS => false,
    ],

    /*
     * The sitemap generator can execute JavaScript on each page so it will
     * discover links that are generated by your JS scripts. This feature
     * is powered by headless Chrome.
     */
    'execute_javascript' => false,

    /*
     * The package will make an educated guess as to where Google Chrome is installed. 
     * You can also manually pass it's location here.
     */
    'chrome_binary_path' => '',
    /*
     * The sitemap generator uses a CrawlProfile implementation to determine
     * which urls should be crawled for the sitemap.
     */
    'crawl_profile' => Profile::class,

];


Enter fullscreen mode Exit fullscreen mode

Step 4: Creating Post Model, Migration and Controller

We are going to create posts XML sitemaps. So we are going to create post model, migration and controller for it.

By running the following command its will create all three model migration and model for post.



php artisan make:model Post -mc


Enter fullscreen mode Exit fullscreen mode

-mc will create a migraion and controller.

Creating Post Model, Migration and Controller

Now we are going to update it.

app/Models/Post.php



<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
    use HasFactory;
    protected $fillable = [
        'title', 
        'slug', 
        'description'
    ];
}


Enter fullscreen mode Exit fullscreen mode

Update Post Model

database/migrations/create_posts_table.php



<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->string('slug');
            $table->text('description'); 
            $table->timestamps();
        });
    }
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
};


Enter fullscreen mode Exit fullscreen mode

Update Post Migration

We don’t need to update PostController.php file for this tutorial because we are going to add dummy records for posts using faker in our next step.

If you want to add, edit, update or to display posts you can using PostController.php. You can check out our article Laravel 9 Vue JS CRUD App using Vite Example. We had discuss the CRUD in deatils.

Run the migration to create our new post table.



php artisan migrate


Enter fullscreen mode Exit fullscreen mode

Step 5: Create Dummy Records for Post

Now we are going to add some dummy records to the post table so that we can generate a XML sitemap for posts.

You can skip this part if you already create a post.

So, now we are going to create factory for our post model using the following command.



php artisan make:factory PostFactory --model=Post


Enter fullscreen mode Exit fullscreen mode

Creating Post Factory

Update the database/factories/PostFactory.php file.



<?php
namespace Database\Factories;
use App\Models\Post;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Post>
 */
class PostFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = Post::class;
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition()
    {
        return [
            'title' => $this->faker->sentence($nbWords = 6, $variableNbWords = true),
            'slug' => $this->faker->randomNumber($nbDigits = NULL, $strict = false),
            'description' => $this->faker->text($maxNbChars = 2000)
        ];
    }
}


Enter fullscreen mode Exit fullscreen mode

Update Post Factory

Note for slug we are using some random numbers.

Now we are going to generate some random post using tinker.



php artisan tinker
Post::factory()->count(30)->create()


Enter fullscreen mode Exit fullscreen mode

30 is the total number of post we want to generate.

Dummy Records Create for Post

Now you can Exit from tinker using exit command.



exit


Enter fullscreen mode Exit fullscreen mode

Step 6: Creating Sitemap Command

You can easily create an artisan command to create a sitemap and schedule it to run frequently. This will ensure that new pages and content types will be automatically picked up. To create a sitemap command run the following command.



php artisan make:command GenerateSitemap


Enter fullscreen mode Exit fullscreen mode

Create Sitemap Command

Update the sitemap command with the following code.

app/Console/Commands/GenerateSitemap.php



<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Spatie\Sitemap\Sitemap;
use Spatie\Sitemap\Tags\Url;
use App\Models\Post;
class GenerateSitemap extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'sitemap:generate';
    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Automatically Generate an XML Sitemap';
    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $postsitmap = Sitemap::create();
        Post::get()->each(function (Post $post) use ($postsitmap) {
            $postsitmap->add(
                Url::create("/post/{$post->slug}")
                    ->setPriority(0.9)
                    ->setChangeFrequency(Url::CHANGE_FREQUENCY_MONTHLY)
            );
        });
        $postsitmap->writeToFile(public_path('sitemap.xml'));
    }
}


Enter fullscreen mode Exit fullscreen mode
  • sitemap:generate is our command to generate the sitemap.
  • “setPriority” — set the post priority.
  • “setChangeFrequency” — set the post change frequency with daily, monthly, yearly.

You can read other options at spatie/laravel-sitemap package.

Update Sitemap Command

Step 7: Scheduled Command in Console Kernel

Now we nee to register this command to kernel for automatically generate XML sitemap. It can be scheduled in the console kernel to be run daily.

app/Console/Kernel.php



// app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
    ...
    $schedule->command('sitemap:generate')->daily();
    ...
}


Enter fullscreen mode Exit fullscreen mode

Update Kernel File for Schedule Sitemap Automatically

Step 8: Testing

We are all set, the sitemap is automatically set to be run daily. To set for now we are going to run the command to generate our sitemap manually by running the following command.



php artisan sitemap:generate


Enter fullscreen mode Exit fullscreen mode

The above command will generate the sitemap.xml in public directory.

Run the following command to start the Artisan development server for laravel.



php artisan serve


Enter fullscreen mode Exit fullscreen mode

And open the following link in any web browser to open the sitemap.



http://127.0.0.1:8000/sitemap.xml


Enter fullscreen mode Exit fullscreen mode

How to Automatically Generate an XML Sitemap in Laravel

Conclusion

This concludes our tutorial on How to Automatically Generate an XML Sitemap in Laravel. We hope you found it helpful. If you did, please share this article with your friends or family and leave us a comment to let us know what you think and stay tuned for more tutorials. If you like the tutorial please subscribe our youtube channel and follow us on social network facebook and instagram.

Top comments (3)

Collapse
 
rafaeldevcode profile image
Rafael Vieira

If I have more than 10,000 contents and I need to generate the sitemap, do I have to do it all at once? I tried to generate it in a job, but Spatie always overwrites the file, in their documentation I didn't see support for reading an existing file, any suggestions on how I should proceed?

Collapse
 
moamahfouz profile image
Mohamed A. Mahfouz

What about adding a boolean field to the db something like added_to_sitemap?

Collapse
 
hoomehrsanatkar profile image
Humehr Sanatkar

Thanks for sharing this article :)👍