%

PHP5|7 : un fichier sitemap.xml, ou sitemap.xml.gz

Article publié, le et modifié le
4 minutes de lecture

Cet article contient 756 mots.
Source brute de l'article :
Commit version : f5a1ac5

Description

Ou comment créer un fichier sitemap.xml - ou sa version compressée sitemap.xml.gz en PHP.

Sitemap.xml basique

Voyons comment écrire en PHP un sitemap.xml très basique :

Code : php

<?php
### créons les constantes utiles
# détection du protocole utilisé : scheme
if ( empty($_SERVER['HTTPS']) ) define('SCHEME', 'http');
else define('SCHEME', 'https');

# détection du nom d'hôte et écriture de la base URL
define('HOST', $_SERVER['HTTP_HOST']);
define('BASE', SCHEME."://".HOST);

# détection du chemin absolu, réel du script
define('ROOT', realpath(getenv('DOCUMENT_ROOT')));

# écriture de l'entête XML
$flux = '<?xml version="1.0" encoding="UTF-8"?>'."\n";
$flux .= '<urlset xmlns="http://www.google.com/schemas/sitemap/0.9"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.google.com/schemas/sitemap/0.9
 http://www.google.com/schemas/sitemap/0.9/sitemap.xsd">'."\n";

# on récupère les informations du fichier index 
$file_mtime = date ("c", filemtime(ROOT.'/index.php')); 

# écriture du flux, relatif au fichier index
$flux .= '  <url>
        <loc>'.BASE.'</loc>
        <lastmod>'.$file_mtime.'</lastmod>
        <priority>1</priority>
    </url>'."\n";

# écriture finale du flux XML
$flux .= '</urlset>'."\n";

# on envoie le flux avec le bon entête et le bon encodage
header("Content-Type: application/xml; charset=utf-8"); 
echo $flux; 
?>

Bien-sûr l’écriture du fichier sitemap.xml est basique, non compressé, et ne sert - dans ce cas - qu’à indexer le fichier index.php - cas peu utile, avouons-le !

Parcours de répertoire

Maintenant, admettons que nous avons un répertoire ‘outils’, dans lequel nous avons différents scripts PHP que nous souhaitons indexer, eux aussi ;)

Pour cela, nous allons utiliser les Itérateurs par parcourir le répertoire, puis récupérer les informations de fichier par le biais de la classe SPL !

Code : php

<?php
# créons un tableau... 
$folders = array ('tools');

# parcours du tableau et exécutions d'instructions relatives...
foreach($folders as $name) {
    
    switch($name) {
        case 'tools': $pattern = '/^.+\.php$/i'; break;
    }
    
    # Utilisons les fonctions Iterator pour parcourir le bon répertoire depuis sa racine absolue.
    $Directory = new RecursiveDirectoryIterator(ROOT.'/'.$name.'/');
    $Iterator = new RecursiveIteratorIterator($Directory);
    $dirs = new RegexIterator($Iterator, $pattern, RecursiveRegexIterator::GET_MATCH);
    
    # parcours de l'objet Iterateur, pour écrire le flux XML nécessaire, 
    foreach($dirs as $dir => $dirs) {
        $flux .= '  <url>'."\n";     
        
        $info = new SplFileInfo($dir);
        
        # construction de l'URL visible
        $flux .= "      <loc>".BASE.'/'.$name.'/'.$info->getBasename()."</loc>"."\n";
        # récupération de la date de dernière modification du fichier - cf, l'argument ''c'' permet de restituer directement la date au bon format attendu
        $flux .= "      <lastmod>".date ("c", $info->getCTime())."</lastmod>"."\n";
        
        ### l'ancienne méthode donnerait ce code PHP
        #$flux .= "      <loc>".BASE.'/'.$name.'/'.basename($dir)."</loc>"."\n";
        #$flux .= "      <lastmod>".date ("c", filemtime($dir))."</lastmod>"."\n";
        
        $flux .= '  </url>'."\n";
    }
    
}
?>

Bien-sûr, ce code PHP de parcours de dossier et de restitution d’informations fichiers, envoyé dans le flux XML nécessaire, est à intégrer après le code relatif au fichier index et avant le code de fermeture du flux XML.

Compression du sitemap.xml

Maintenant, voyons comment compresser de manière simple et rapide le flux XML pour créer un fichier sitemap.xml.gz nécessaire :

Code : php

<?php
# on prend le flux XML dans son ensemble pour l'encoder en gz
$gzdata = gzencode($flux, 9);
?>

Ensuite pour envoyer les données, utilisons les bons entêtes, puis affichons le flux encodé :

Code : php

<?php
# déclaration des entêtes nécessaires
header("Content-Type: application/x-gzip");
header("Content-Encoding: gzip");
header("Content-Disposition: attachment; filename=sitemap.xml.gz");
# affichage du flux encodé - et non pas du flux normal !!!
echo $gzdata; 
?>

TL;DR

Voici la version finale du code PHP pour créer dynamiquement un fichier sitemap.xml, et sa version compressée sitemap.xml.gz :

Fichier : sitemap.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<?php
### les constantes utiles
if ( empty($_SERVER['HTTPS']) ) define('SCHEME', 'http');
else define('SCHEME', 'https');
define('HOST', $_SERVER['HTTP_HOST']);
define('BASE', SCHEME."://".HOST);
define('ROOT', realpath(getenv('DOCUMENT_ROOT')));

# écriture de l'entête XML
$flux = '<?xml version="1.0" encoding="UTF-8"?>'."\n";
$flux .= '<urlset xmlns="http://www.google.com/schemas/sitemap/0.9"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.google.com/schemas/sitemap/0.9
 http://www.google.com/schemas/sitemap/0.9/sitemap.xsd">'."\n";

# on récupère les informations du fichier index 
$file_mtime = date ("c", filemtime(ROOT.'/index.php')); 
$flux .= '  <url>
        <loc>'.BASE.'</loc>
        <lastmod>'.$file_mtime.'</lastmod>
        <priority>1</priority>
    </url>'."\n";

# gestion du répertoire 'outils'
$folders = array ('tools');

foreach($folders as $name) {
    
    switch($name) {
        case 'tools': $pattern = '/^.+\.php$/i'; break;
    }
    
    $Directory = new RecursiveDirectoryIterator(ROOT.'/'.$name.'/');
    $Iterator = new RecursiveIteratorIterator($Directory);
    $dirs = new RegexIterator($Iterator, $pattern, RecursiveRegexIterator::GET_MATCH);
    
    foreach($dirs as $dir => $dirs) {
        $flux .= '  <url>'."\n";
        
        $info = new SplFileInfo($dir);
        $flux .= "      <loc>".BASE.'/'.$name.'/'.$info->getBasename()."</loc>"."\n";
        $flux .= "      <lastmod>".date ("c", $info->getCTime())."</lastmod>"."\n";
               
        $flux .= '  </url>'."\n";
    }
    
}
    
$flux .= '</urlset>'."\n";

# création du flux encodé
$gzdata = gzencode($flux, 9);

# envoi du flux 
if(!empty($gzdata)) {
    header("Content-Type: application/x-gzip");
    header("Content-Encoding: gzip");
    header("Content-Disposition: attachment; filename=sitemap.xml.gz");
    echo $gzdata; 
} 
else {
    header("Content-Type: application/xml; charset=utf-8"); 
    echo $flux; 
}
?>

Et, voilà ! :D