'); // Add homepage $this->addUrl($xml, route('home'), now(), 'daily', '1.0'); // Add jobs index $this->addUrl($xml, route('jobs.index'), now(), 'daily', '0.9'); // Add remote jobs $this->addUrl($xml, route('jobs.remote'), now(), 'daily', '0.9'); // Add categories $categories = JobCategory::all(); foreach ($categories as $category) { $this->addUrl( $xml, route('jobs.category', $category->slug), $category->updated_at, 'daily', '0.8' ); } // Add active jobs $jobs = Job::where(function ($query) { $query->whereNull('expires_at') ->orWhere('expires_at', '>', now()); }) ->orderBy('posted_at', 'desc') ->limit(10000) // Limit to 10k most recent jobs ->get(['id', 'slug', 'posted_at', 'updated_at']); foreach ($jobs as $job) { $this->addUrl( $xml, route('jobs.show', $job), $job->updated_at ?? $job->posted_at, 'weekly', '0.7' ); } return $xml->asXML(); } /** * Add URL to sitemap */ private function addUrl( \SimpleXMLElement $xml, string $url, ?\DateTimeInterface $lastmod = null, string $changefreq = 'weekly', string $priority = '0.5' ): void { $urlElement = $xml->addChild('url'); $urlElement->addChild('loc', htmlspecialchars($url)); if ($lastmod) { $urlElement->addChild('lastmod', $lastmod->format('Y-m-d')); } $urlElement->addChild('changefreq', $changefreq); $urlElement->addChild('priority', $priority); } /** * Generate sitemap index for large sites */ public function generateSitemapIndex(): string { $xml = new \SimpleXMLElement(''); // Add main sitemap $this->addSitemapToIndex($xml, route('sitemap.main'), now()); // Add jobs sitemap $this->addSitemapToIndex($xml, route('sitemap.jobs'), now()); return $xml->asXML(); } /** * Add sitemap to index */ private function addSitemapToIndex(\SimpleXMLElement $xml, string $url, \DateTimeInterface $lastmod): void { $sitemapElement = $xml->addChild('sitemap'); $sitemapElement->addChild('loc', htmlspecialchars($url)); $sitemapElement->addChild('lastmod', $lastmod->format('Y-m-d')); } /** * Generate main sitemap (static pages and categories) */ public function generateMainSitemap(): string { $xml = new \SimpleXMLElement(''); // Add homepage $this->addUrl($xml, route('home'), now(), 'daily', '1.0'); // Add jobs index $this->addUrl($xml, route('jobs.index'), now(), 'daily', '0.9'); // Add remote jobs $this->addUrl($xml, route('jobs.remote'), now(), 'daily', '0.9'); // Add categories $categories = JobCategory::all(); foreach ($categories as $category) { $this->addUrl( $xml, route('jobs.category', $category->slug), $category->updated_at, 'daily', '0.8' ); } return $xml->asXML(); } /** * Generate jobs sitemap */ public function generateJobsSitemap(): string { $xml = new \SimpleXMLElement(''); // Add active jobs $jobs = Job::where(function ($query) { $query->whereNull('expires_at') ->orWhere('expires_at', '>', now()); }) ->orderBy('posted_at', 'desc') ->limit(50000) // Sitemap limit ->get(['id', 'slug', 'posted_at', 'updated_at']); foreach ($jobs as $job) { $this->addUrl( $xml, route('jobs.show', $job), $job->updated_at ?? $job->posted_at, 'weekly', '0.7' ); } return $xml->asXML(); } }