Créer une table des matières automatique en PHP

Objectif

L’objectif de ce tutoriel est de fournir un code permettant de créer automatiquement une table des matières à votre contenu en se basant sur les balises HTML de titre <Hx></Hx>

Code

<?php
function add_anchor($string)
{
    $array = explode(" ",$string);
    $id = 0;
    for($i=0;$i<count($array);$i++)
    {
        for($t = 1;$t < 10;$t++)
        {
            $array[$i] = str_replace("</h$t>","<a name=\"title-$id\"></a></h$t>",$array[$i],$count);
            if($count > 0)
            {
                $id += $count;
            }
        }
    }
    $return = implode(" ",$array);
    return $return;
}

function makeTableOfContents($file) 
{
    echo "\t<ol>\n";
    $tableau = preg_split("/[\n]+/", $file);
    $pattern='<h[0-9]*>.*</h[0-9]*>';
    $anchor='<a name=*';
    $oldN = 1;
    
    while(list($cle,$str) = each($tableau)) 
    {
        
        if (eregi($pattern, $str)) 
        {
            $chars = preg_split('/<h/', $str, -1, PREG_SPLIT_OFFSET_CAPTURE);
            
            $fullN = $chars[1][0];
            $n = substr($fullN, 0, 1);
            
            $fullTitle = substr($fullN, 2);
            $closeTag = '/</';//.$n.'>/';
            $titleSplit = preg_split($closeTag, $fullTitle, -1, PREG_SPLIT_OFFSET_CAPTURE);
            $title = substr($fullTitle, 0, ($titleSplit[1][1]-1));
            
            if (eregi($anchor, $str)) 
            {
                $charsanchor = preg_split('/name="/', $str, -1);
                $charsanchor2 = split("<",$charsanchor[1]);
                $title = '<a href="#'. $charsanchor2[0] .''. $title .'</a>';
            }
            
            if($n >= 1) 
            {
                switch($n)
                {
                    case ($n > $oldN):
                        echo "\n\t<ol>\n";
                        echo "\t<li>".$title;
                    break;
                    
                    case ($n < $oldN):
                        echo "</li>\n";
                        $diff = $oldN - $n;
                        for($i=0;$i<$diff;$i++)
                        {
                            echo "\t</li>\n";
                            echo "\t</ol>\n";
                        }
                        echo "\t<li>".$title;
                    break;
                    
                    case ($n == $oldN):
                        echo "</li>\n";
                        echo "\t<li>".$title;
                    break;
                }
                $oldN = $n;
            }
        }
    }
    echo "\n\t</ol>\n";
}
?>

Explications

Le principe de cette table des matières automatique réside en deux fonctions.

La première fonction add_anchor parcours le texte et ajoute une ancre à la fin de chaque titre, avant la balise </hX>

La seconde fonction makeTableOfContents parcours le texte et créé une liste faite avec tous les titres (de <h0> à <h9>) avec un lien pointant sur l’ancre créée par la précédente fonction.

Restrictions

La seule restriction de ce système est qu’il ne faut pas implémenter des titres qui ne se cascadent pas.

Exemple:

<h1>Titre1</h1>
<h3>Titre1.1</h3>

La bonne utilisation est dans cet exemple:

<h1>Titre1</h1>
<h2>Titre1.1</h2>

Il est par contre tout à fait envisageable qu’après un titre <h3> par exemple, il y ait un titre <h1>

Exemple:

<h3>Titre1.1.1</h3>
<h1>Titre2</h1>

Exemple

Petit exemple pour montrer le fonctionnement.

La variable $texte contient le contenu à afficher.

<?php
$texte = "
<h1>Titre 1</h1>
<h2>Sous Titre1</h2>
<p>His cognitis Gallus ut serpens adpetitus telo vel saxo iamque spes extremas opperiens et succurrens saluti suae quavis ratione colligi omnes iussit armatos et cum starent attoniti, districta dentium acie stridens adeste inquit viri fortes mihi periclitanti vobiscum.</p>
<h2>Sous Titre2</h2>
<p>Denique Antiochensis ordinis vertices sub uno elogio iussit occidi ideo efferatus, quod ei celebrari vilitatem intempestivam urgenti, cum inpenderet inopia, gravius rationabili responderunt; et perissent ad unum ni comes orientis tunc Honoratus fixa constantia restitisset.</p> 
";

En passant cette variable dans la fonction add_anchor(), une ancre est ajoutée à chaque titre.

<?php
$texte = "
<h1>Titre 1<a name="title-0"></a></h1>
<h2>Sous Titre1<a name="title-1"></a></h2>
<p>His cognitis Gallus ut serpens adpetitus telo vel saxo iamque spes extremas opperiens et succurrens saluti suae quavis ratione colligi omnes iussit armatos et cum starent attoniti, districta dentium acie stridens adeste inquit viri fortes mihi periclitanti vobiscum.</p>
<h2>Sous Titre2<a name="title-2"></a></h2>
<p>Denique Antiochensis ordinis vertices sub uno elogio iussit occidi ideo efferatus, quod ei celebrari vilitatem intempestivam urgenti, cum inpenderet inopia, gravius rationabili responderunt; et perissent ad unum ni comes orientis tunc Honoratus fixa constantia restitisset.</p> 
";

Ensuite, il suffit de passer cette nouvelle variable dans la seconde fonction makeTableOfContents pour créer la table des matières:

<ol>
<li><a href="#title-0">Titre 1</a>
<ol>
<li><a"#title-1">Sous Titre 1</a>
</li><li><a href="#title-2">Sous Titre 2</a>
</li></ol>
</ol>

Voici concrètement le code utilisé

<?php
$texte = "
<h1>Titre 1</h1>
<h2>Sous Titre1</h2>
<p>His cognitis Gallus ut serpens adpetitus telo vel saxo iamque spes extremas opperiens et succurrens saluti suae quavis ratione colligi omnes iussit armatos et cum starent attoniti, districta dentium acie stridens adeste inquit viri fortes mihi periclitanti vobiscum.</p>
<h2>Sous Titre2</h2>
<p>Denique Antiochensis ordinis vertices sub uno elogio iussit occidi ideo efferatus, quod ei celebrari vilitatem intempestivam urgenti, cum inpenderet inopia, gravius rationabili responderunt; et perissent ad unum ni comes orientis tunc Honoratus fixa constantia restitisset.</p> 
";

$newtexte = add_anchor($texte);
makeTableOfContents($newtexte);
echo "<hr/>";
echo $newtexte;

Et le résultat obtenu:

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *