So, you have multiple subdomains served by one instance of Laravel, based on laravel multilanguage site, but now you need to set up sitemaps for each of them?
Here is how!
If you are not familiar with the solution for serving multiple subdomains using Laravel localization, especially https://github.com/mcamara/laravel-localization, please read this article first:
Ok, so now when we have basic understanding, let's generate sitemap files for each subdomain.
For sitemap generation we will use: https://github.com/spatie/laravel-sitemap , so please install it.
OK, now we are ready.
Step 1: Create Sitemap generation cron task
Let's create an artisan command that will be used by cron job:
php artisan make:command GenerateSitemap
Inside of GenerateSitemap we will add code that will be called by cron:
public function handle()
{
$cronService = app('App\Http\Modules\Cron\Services\CronService');
$subdomainMap = config('laravellocalization.supportedLocales');
foreach ($subdomainMap as $key => $value) {
$cronService->generateSiteMap($key,$value['subdomain']);
}
}
config('laravellocalization.supportedLocales')
is a list of defined languages in mcamara plugin, so basically we will trigger cron for every enabled language.
Now in our CronService, let's create a method for making sitemap per subdomain:
public function generateSiteMap($language,$subdomain){
$path = public_path($subdomain.'-sitemap.xml');
app()->setLocale($language);
$subdomainMap = config('laravellocalization.supportedLocales');
$subdomain = $subdomainMap[App::getLocale()]['subdomain'] ?? $subdomainMap[config('app.default_domain')]['subdomain'];
// if we have subdomain and language is not main language set subdomain
// otherwise use no subdomain. This is exception for main root domain
if ($language != config('app.default_domain') ) {
// Set the URL for subdomain-based locale
FacadeURL::forceRootUrl("https://{$subdomain}." . config('app.app_domain'));
}
$sitemap = Sitemap::create();
// home route
$sitemap->add(URL::create(route('home'))
->setLastModificationDate(Carbon::yesterday())
->setChangeFrequency(Url::CHANGE_FREQUENCY_WEEKLY)
->setPriority(0.1))
you will also define default domain in your .env file and in config/app.php:
DEFAULT_DOMAIN='en'
// config/app.php
...
'default_domain' => env('DEFAULT_DOMAIN'),
Add the task to your console/Kernerl.php
$schedule->command('app:generate-sitemap')->daily();
OK, now when we execute:
php artisan app:generate-sitemap
our sitemaps will be generated, with prefixed URLs, and it will be named:
germany-sitemap.xml, austria-sitemap.xml...
How to show specific sitemap for each subdomain:
In your route file, create route for sitemap.xml :
Route::get('sitemap.xml',[HomeController::class,'returnSitemap'])->name('sitemap');
and then in HomeController we all the logic for displaying different sitemaps:
public function returnSitemap(Request $request){
$localizationConfig = config('laravellocalization.supportedLocales');
$language = app()->getLocale();
$subdomain = $localizationConfig[$language]['subdomain'];
$sitemap_path = public_path($subdomain.'-sitemap.xml');
$sitemapContent = File::get($sitemap_path);
return response($sitemapContent, 200)
->header('Content-Type', 'application/xml');
}
And that it is it