Transformer une chaîne de caractères accentués en chaîne URL encodée

Travaillant en PHP pour générer des pages web il m'arrive régulièrement de devoir construire des URL à partir d'informations provenant de bases de données. C'est surtout le cas quand on veut des URL de fiches produits en lien avec le nom du produit de la fiche (pour faire du SEO par exemple).

Le hic avec ça, c'est que les accents ne passent que rarement bien. Même si les URL et noms de domaines sont censés pouvoir en posséder ça ne fait pas ce que l'on veut.

On a toujours pu utiliser la fonction urlencode() de PHP, mais elle ne traite pas les caractères accentués en les laissant lisibles. Elle fait son job: elle encode tout...

Il m'a donc fallu ruser dès le départ et j'utilise toujours la fonction suivante (ou une variante) quand je veux une URL à partir d'une chaîne de caractères potentiellement accentués.

	// return human readable text without accents for URL encoding for text
	function toUrl($ch, $lowercase = true) {
		$let1 = array("à","â","ä","é","è","ë","ê","î","ï","ô","ö","ù","ü","û","%","'",",","ç","&","/","\\");
		$let2 = array("a","a","a","e","e","e","e","i","i","o","o","u","u","u","pourcent"," "," ","c","-","-","-");
		if ($lowercase) {
			$ch = str_replace($let1,$let2,trim(strtolower(stripslashes($ch)))); // lowercase string
		}
		else {
			$ch = str_replace($let1,$let2,trim(stripslashes($ch))); // normal string
		}
		$res = "";
		for ($i = 0; $i < strlen ($ch); $i++) {
			$c = substr ($ch, $i, 1);
			if ((($c >= "A") && ($c <= "Z")) || (($c >= "a") && ($c <= "z")) || (($c >= "0") && ($c <= "9")) || ($c == "-") || ($c == "_") || ($c == ",") || ($c == " ")) {
				$res .= $c;
			}
		}
		return substr(urlencode(substr(str_replace("--", "-", str_replace(" ", "-", trim($res))),0,128)),0,128);
	}

Pour voir ce que ça donne, consultez l'un des gros sites sur lesquels j'interviens depuis plus de 10 ans : Le Choix des Libraires.