0

I'm trying to generate valid sitemap with php. The logic is simple. I forwarded all ^(.+)index_sitemal.xml request to my index_sitemap.php file in .htaccess. PHP script is below:

<?php 
header( "content-type: application/xml; charset=UTF-8" );
    echo '<?xml version="1.0" encoding="UTF-8"?>'."\n";
    echo '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'."\n";
    $len = 10;   // to take
    $min = 50;  // minimum
    $max = 100;  // maximum
    $range = [];
    foreach (range(0, $len - 1) as $i) {
        while(in_array($num = mt_rand($min, $max), $range));
        $range[] = $num;
        echo '<sitemap><loc>http://'.$_SERVER['SERVER_NAME'].'/sitemap/'.$num.'.xml</loc></sitemap>'."\n";
    }
    echo '</sitemapindex>';
?>

In browser it displays good.

Link for image - (sorry low reputation) https://i.ibb.co/4ZmLJ1D/Screenshot-at-Jan-29-10-47-01.png

But while trying to validate the xml I'm getting type error.

Link for image - (sorry low reputation) https://i.ibb.co/Ws11cBj/Screenshot-at-Jan-29-10-55-28.png

Is there any way to display a dynamic sitemap using php?

hllktlhndd
  • 303
  • 2
  • 10
Fedor
  • 39
  • 1
  • 8

1 Answers1

5

I had a similar issue before but solved it by running a different PHP file to update the sitemap with a CRON job.

<?php
$xmlString = '<?xml version="1.0" encoding="UTF-8"?>';
$xmlString .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">';

$xmlString .= '<url>';
$xmlString .= '<loc>http://example.com/</loc>';
$xmlString .= '<lastmod>'.date(DATE_ATOM,time()).'</lastmod>';
$xmlString .= '<changefreq>daily</changefreq>';
$xmlString .= '<priority>1.0</priority>';
$xmlString .= '</url>';

$xmlString .= '<url>';
$xmlString .= '<loc>http://example.com/videos/</loc>';
$xmlString .= '<lastmod>'.date(DATE_ATOM,time()).'</lastmod>';
$xmlString .= '<changefreq>daily</changefreq>';
$xmlString .= '<priority>1.0</priority>';
$xmlString .= '</url>';

$xmlString .= '<url>';
$xmlString .= '<loc>http://example.com/contact/</loc>';
$xmlString .= '<lastmod>'.date(DATE_ATOM,time()).'</lastmod>';
$xmlString .= '<changefreq>daily</changefreq>';
$xmlString .= '<priority>1.0</priority>';
$xmlString .= '</url>';

$xmlString .= '<url>';
$xmlString .= '<loc>http://example.com/blog/</loc>';
$xmlString .= '<lastmod>'.date(DATE_ATOM,time()).'</lastmod>';
$xmlString .= '<changefreq>daily</changefreq>';
$xmlString .= '<priority>1.0</priority>';
$xmlString .= '</url>';

$sql = "SELECT * FROM categories";
$stmt = DB::run($sql);
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
    $url = $row["url"];
    $xmlString .= '<url>';
    $xmlString .= '<loc>http://example.com/category/'.htmlentities($url).'/</loc>';
    $xmlString .= '<lastmod>'.date(DATE_ATOM,time()).'</lastmod>';
    $xmlString .= '<changefreq>daily</changefreq>';
    $xmlString .= '<priority>1.0</priority>';
    $xmlString .= '</url>';
}

$xmlString .= '</urlset>';

$dom = new DOMDocument;
$dom->preserveWhiteSpace = FALSE;
$dom->loadXML($xmlString);

$dom->save('../sitemap.xml');
?>

Edit

<?php

$host = 'http://www.google.com/ping?sitemap=https://www.example.com/sitemap.xml'; 
$ch = curl_init($host);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if($httpcode>=200 && $httpcode<300){
  echo 'success';
} else {
  echo 'try again';
}

?>
halfer
  • 19,824
  • 17
  • 99
  • 186
Paddy Hallihan
  • 1,624
  • 3
  • 27
  • 76
  • Paddy Hallihan thank you for your answer! I need to configure CRON job to make test of it first. But could you please advise if this script generates static "../sitemap.xml" or displaying it only without saving? – Fedor Jan 29 '19 at 09:43
  • You can just run the PHP file in your browser for testing without setting up the cron job and it should save the xml file. In my case I have a cron folder with all the scripts so the XML is saved back in the main directory `../sitemap.xml` so you may need to adjust this – Paddy Hallihan Jan 29 '19 at 09:48
  • The actual XML file is static when saved. But the CRON job will rewrite it every hour/day or whatever you choose. – Paddy Hallihan Jan 29 '19 at 09:49
  • Hm, strange but I do not get this static sitemap.xml. But anyway I got your point and will proceed in this direction, thank you. Another thing is how to display it. I mean if I save it "$dom->save('../sitemap.xml');" then my php script will not return xml sitemap as was initially planned. – Fedor Jan 29 '19 at 09:57
  • The only thing I could think of in this case is like I said earlier with going up a directory with `../` and making sure you have the ability to write to this directory. Also when it is saved I do not need to display it. I know the name is always going to be the same so that is the URL i have given Google search console. I also have another script then in a seperate cron job that pings Google to say hey here's a new sitemap (see edited answer) – Paddy Hallihan Jan 29 '19 at 10:05
  • "Also when it is saved I do not need to display it. I know the name is always going to be the same so that is the URL i have given Google search console." - right, but I have .htaccess rule of forwarding. So i need to have display option, but I guess CURL can do this with right header. – Fedor Jan 29 '19 at 10:23
  • Oh ok well you might need to change things around for your specific set up but this is what I did anyway I hope it helps – Paddy Hallihan Jan 29 '19 at 10:24