Bonsoir (ou bonjour, tout dépend de l'heure à laquelle vous lirez ceci :p)

Voulant compléter le tutoriel sur le MVC, j'ai décidé de créer une fonction permettant de créer les 'slugs' automatiquement.
Ma fonction est loin d'être complète, elle est basique. Elle permet de généré automatique le slug par rapport a un titre simple (article ou page).

Voici le code :

function AutoLinks($strlink)
{
        $str = preg_replace('/\s/', '-', $strlink); // Remplace les espaces par des '-'.

        $str = htmlentities($str, ENT_NOQUOTES, 'utf-8');

        $str = preg_replace('#&([A-za-z])(?:acute|cedil|circ|grave|orn|ring|slash|th|tilde|uml);#', '\1', $str); // Remplace les accents des caractères
        $str = preg_replace('#&([A-za-z]{2})(?:lig);#', '\1', $str);
        $str = preg_replace('/(^\w\-]+)/i', '', $str); // Remplace les caractères spéciaux sauf les '-'
        $str = preg_replace('/([_])/i', '', $str); // Remplace les underscores

        $str = strtolower($str); // On écrit le tout en minuscule

        return $str;
}

Vous êtes libre de l'utiliser pour votre site, et de le modifier selon vos envie. J'ai juste décider de partager ma petite fonction qui pourra certainement en aidez plus d'un.
(Ps : les preg_replace peuvent certainement être améliorer, mais hélas je ne suis pas un pro dans ce domaine :p)

Pandoraaa.

7 réponses


iriven
Réponse acceptée

en ce qui me concerne, j'ai beaucoup personnalisé ma version du tuto mvc proposé par grafikart, qui au final n'en garde à l'identique que le systeme de routage, et j'utilise le code suivant comme generateur de slug:

/* Remplace caractères accentués d'une chaine */
/* Générateur de Slug (Friendly Url) : convertit un titre en une URL conviviale.*/
public static function makeSlug($string, $maxlen=0){
    self::getInstance();
//cyrylic transcription
      $cyrylicFrom = array('?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?');
      $cyrylicTo = array('A', 'B', 'W', 'G', 'D', 'Ie', 'Io', 'Z', 'Z', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', 'F', 'Ch', 'C', 'Tch', 'Sh', 'Shtch', '', 'Y', '', 'E', 'Iu', 'Ia', 'a', 'b', 'w', 'g', 'd', 'ie', 'io', 'z', 'z', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 't', 'u', 'f', 'ch', 'c', 'tch', 'sh', 'shtch', '', 'y', '', 'e', 'iu', 'ia'); 

      $from = array('Á', 'À', 'Â', 'Ä', '?', '?', 'Ã', 'Å', '?', 'Æ', '?', '?', '?', '?', 'Ç', '?', '?', 'Ð', 'É', 'È', '?', 'Ê', 'Ë', '?', '?', '?', '?', '?', '?', '?', '?', 'á', 'à', 'â', 'ä', '?', '?', 'ã', 'å', '?', 'æ', '?', '?', '?', '?', 'ç', '?', '?', 'ð', 'é', 'è', '?', 'ê', 'ë', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', 'I', 'Í', 'Ì', '?', 'Î', 'Ï', '?', '?', '?', '?', '?', '?', '?', '?', '?', 'Ñ', '?', 'Ó', 'Ò', 'Ô', 'Ö', 'Õ', '?', 'Ø', '?', 'Œ', '?', '?', '?', 'í', 'ì', 'i', 'î', 'ï', '?', '?', '?', '?', '?', '?', '?', '?', '?', 'ñ', '?', 'ó', 'ò', 'ô', 'ö', 'õ', '?', 'ø', '?', 'œ', '?', '?', '?', '?', 'Š', '?', '?', '?', 'Þ', 'Ú', 'Ù', 'Û', 'Ü', '?', '?', '?', '?', '?', '?', '?', 'Ý', '?', 'Ÿ', '?', '?', 'Ž', '?', '?', '?', '?', 'š', '?', 'ß', '?', '?', 'þ', 'ú', 'ù', 'û', 'ü', '?', '?', '?', '?', '?', '?', '?', 'ý', '?', 'ÿ', '?', '?', 'ž');
      $to = array('A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'AE', 'C', 'C', 'C', 'C', 'C', 'D', 'D', 'D', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'G', 'G', 'G', 'G', 'G', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'c', 'c', 'c', 'c', 'd', 'd', 'd', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'g', 'g', 'g', 'g', 'g', 'H', 'H', 'I', 'I', 'I', 'I', 'I', 'I', 'I', 'I', 'IJ', 'J', 'K', 'L', 'L', 'N', 'N', 'N', 'N', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'CE', 'h', 'h', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'ij', 'j', 'k', 'l', 'l', 'n', 'n', 'n', 'n', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'R', 'R', 'S', 'S', 'S', 'S', 'T', 'T', 'T', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'W', 'Y', 'Y', 'Y', 'Z', 'Z', 'Z', 'r', 'r', 's', 's', 's', 's', 'B', 't', 't', 'b', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'w', 'y', 'y', 'y', 'z', 'z', 'z');
   $numbers=array('0','1','2','3','4','5','6','7','8','9','-');
   $from = array_merge($from, $cyrylicFrom);
   $to = array_merge($to, $cyrylicTo);   
   $newstring=strtolower(str_replace($from, $to, trim($string))); 
   $newstring=str_replace(' ', '-', $newstring); 
   $newStringTab=array();
   if(function_exists('str_split'))
   {
         $stringTab=str_split($newstring);
   }
   else
   {
      $slen=strlen($newstring);
      for($i=0; $i<$slen; $i++)
      {
         $stringTab$i]=$newstring{$i};
      }
    }
      foreach($stringTab as $letter)
      {
         if(in_array($letter, range('a', 'z')) || in_array($letter, $numbers))
         {
            $newStringTab]=$letter;
         }
      }
    if(count($newStringTab))
      {
         $newString=implode($newStringTab);
         if($maxlen>0)
         {
            $newString=substr($newString, 0, $maxlen);
         }
          $i=0;
      do{
        $newString = str_replace('--', '-', $newString);       
         $pos=strpos($newString, '--');
         $i++;
         if($i>100)
         {
            die('remove duplicates \'--\' loop error');
         }

      }while($pos!==false); 
      }
      else
      {
         $newString='';
      }      

      return $newString;   
}

je mets ici une version plus courte et optimisée du générateur de slug ci-dessus:
(elle corrige en réalité les insuffisances de la fonction proposée par Xtr3me)

public static function makeSlug($str,$maxlen=0) { 
    self::getInstance();
    $str = str_replace('&', 'et', trim($str));
  // On convertit la chaîne en UTF-8 si besoin est.
  if($str !== mb_convert_encoding(mb_convert_encoding($str,'UTF-32','UTF-8'),'UTF-8','UTF-32')) {
      $str = mb_convert_encoding($str,'UTF-8');
    }
  $str = htmlentities($str, ENT_NOQUOTES ,'UTF-8');
  // Quelques entités à remplacer par les lettres correspondantes.
  $str = preg_replace('`&([a-z]{1,2})(acute|uml|circ|grave|ring|cedil|orn|slash|th|tilde|caron|lig);`i','$1',$str);
  $str = preg_replace(array('`^a-z0-9]`i','`-]+`'),'-',$str);
 if($maxlen>0)
 {
    $str=substr($str, 0, $maxlen);
 }  
  return strtolower(trim($str,'-'));
}

Le premier preg_replace, un str_replace aurait suffit et le dernier aussi apparemment.
Pour les autres tu utilises des expressions régulières qui ne peuvent être utilisées avec une autre fonction donc pas trop le choix.
Pour le remplacement des underscores je serai toi je les mettrai en tiret ;) .
Après le mieux pour générer un slug automatique c'est de compter le nombre de fois qu'apparaît le mot dans le titre et l'article et de baser le slug les 3 mots les plus utilisés par exemple.

Par exemple tu as comme titre:
"Grafikart c'est trop de la balle".
Tu vas regarder dans ton article si pour chaque mot il y a une correspondance et combien il y en a en bannissant certains mots passe-partout(déterminant, pronom etc...). Tu seras ainsi certain de faire un slug qui correspond à l'article mais qui se base sur le titre.

Oui c'est vrai que, pourquoi ne rien mettre pour les underscores alors qu'un tiret est plus approprié.

Après essayer de voir avec les mots contenu dans le texte c'est pas mal, mais c'est énervant à cherché ce qui faut retenir, pour avoir vraiment l'essentiel. Il faudrait voir le système qu'utilise "Commentçamarche" car il est très bon pour repérer les mots utiles.

désolé mais les caractères cyrilliques ne s'affichent pas correctement
une recherche m'a permis de trouver une fonction prenant egalement c'es caracteres ici:
https://gist.github.com/sgmurphy/3098978

Moi j'utilise une classe pour avoir des urls au format que je souhaites (sans accents, sans espaces etc...).
Pour la fonction sans accents j'utilise ça:

public function noaccent($str){
            $str= htmlentities($str, ENT_NOQUOTES, 'utf-8');
            $str = preg_replace('#&([A-za-z])(?:acute|cedil|circ|grave|orn|ring|slash|th|tilde|uml);#', '\1', $str);
            $str = preg_replace('#&([A-za-z]{2})(?:lig);#', '\1', $str); // pour les ligatures e.g. 'œ'
            $str = preg_replace('#&^;]+;#', '', $str); // supprime les autres caractères
            return $str;
          }

Je réécris toutes mes URLS avec la classe ainsi j'ai des urls propres.

Perso j'utilise celle-ci qui marche relativement bien :

/**
     * Fonction de ré-écriture des URLs
     * @var string  $name   URL a re-ecrire
     **/
    public static function ValideUrl($name)
    {
        $alias=mb_strtolower($name,'UTF-8');
        $alias=mb_strtolower(trim($alias)); 

        $search=array(utf8_decode('@ÈÉÊËèéêë]@i'),utf8_decode('@ÀÁÂÃÄÅàáâãäå]@i'),utf8_decode('@ÌÍÎÏìíîï]@i'),utf8_decode('@ÙÚÛÜùúûü]@i'),utf8_decode('@ÒÓÔÕÖðòóôõö]@i'),utf8_decode('@çÇ]@i'),utf8_decode('@Ýýÿ]@i'),utf8_decode('@,;:!§/.?*°+\'\-]@i'),utf8_decode('@\s]@')); 
        $replace=array('e','a','i','u','o','c','y','','-'); 
        $alias=preg_replace($search,$replace,utf8_decode($alias));
        $search=array('.',',','?',';',':','/','!','§','%','ù','*','µ','¨','^','$','£','ø','=','+','}',')','°',']','@','^','\\','|','','{','#','~','}',']','&','²'); 
        $alias=str_replace($search,'',$alias); 
        $search=array('@-{2,}@i'); 
        $alias=preg_replace($search,'-',$alias); 
        $alias=utf8_encode($alias);

    return $alias;
    }

Merci du partage, ça va certainement m'inspirer car je suis moi aussi en train d'améliorer ce MVC, et sur certains points je galère.

D'ailleurs, si l'un d'entre vous pouvait expliquer brièvement l'utilisation de ces fonctions, ça serait cool.
J'ai pas encore regardé attentivement mais à priori, ces fonctions doivent être placée dans le fichier Model.php non?
Je suppose également que ce n'est pas la seule chose à faire?

Bref, quelques explications en cas de besoin seraient top!

En vous remerciant,
bonne journée!