Phonex

Description

Tout comme soundex2, ceci est une adaptation php de l'algo phonex qui a été créé, et décrit ici : http://sqlpro.developpez.com/cours/soundex/ par Frédéric BROUARD.

PRECISIONS SUR L'UTILITE :
Ces algo, soundex, soundex2, phonex, metaphone, assigne un code à une chaîne donnée. Ce code est calculé en fonction de la phonétique, donc de la prononciation de cette chaîne.
En l'occurence, les 2 algo présents par défaut dans php, soundex () et metaphone () ne prennent en compte que la prononciation anglaise.
Celui-ci, basé sur phonex (un algo plus performant que soundex ou soundex2), est francisé.

Evidemment, 2 chaînes différentes peuvent avoir le même code. Par exemple, ici, 'gros' aura le même code phonex que 'grau'.
Ce qui veut dire, dans le cadre d'une recherche sur une base de données contenant des noms, par exemple, on peut effecyuer une recherche phonétique aussi! Bref, le mec a parlé avec un cilent par téléphone, mais il ne s'est pas comment s'écrit exactement son nom de famille...gros, graus, grau, graux, greaux...? etc... Il tape par exemple gros, et effectue une recherche phonex. Cette recherche lui ressortira tous les noms dont le code phonex est le même que 'gros'. Donc si le client s'appelait 'Graux', il le trouvera.

Couplé à l'algo de levenshtein (fonction interne php) en plus, on peut avoir une recherche phonétique par pertinence...les codes identiques en premiers, puis ceux un peu différents, etc...jusqu'à un degré de différence voulu.

Le mieux, dans le cadre d'une bdd, est évidemment de stocker le code phonex dans la base, histoire de ne pas le recalculer à chaque recherche.

Source / Exemple :


<?php
/**


*

  • author Johan Barbier <barbier_johan@hotmail.com>
  • /
class phonex { /**
  • The public string we will work on
  • /
public $sString = ''; /**
  • private replacement array
  • /
private $aReplaceGrp1 = array ( 'gan' => 'kan', 'gam' => 'kam', 'gain' => 'kain', 'gaim' => 'kaim' ); /**
  • private replacement array
  • /
private $aReplaceGrp2 = array ( '/(ain)([aeiou])/' => 'yn$2', '/(ein)([aeiou])/'=> 'yn$2', '/(aim)([aeiou])/' => 'yn$2', '/(eim)([aeiou])/'=> 'yn$2', ); /**
  • private replacement array
  • /
private $aReplaceGrp3 = array ( 'eau' => 'o', 'oua' => '2', 'ein' => '4', 'ain' => '4', 'eim' => '4', 'aim' => '4' ); /**
  • private replacement array
  • /
private $aReplaceGrp4 = array ( 'é' => 'y', 'è' => 'y', 'ê' => 'y', 'ai' => 'y', 'ei' => 'y', 'er' => 'yr', 'ess' => 'yss', 'et' => 'yt' ); /**
  • private replacement array
  • /
private $aReplaceGrp5 = array ( '/(an)($|[^aeiou1234])/' => '1$2', '/(am)($|[^aeiou1234])/' => '1$2', '/(en)($|[^aeiou1234])/' => '1$2', '/(em)($|[^aeiou1234])/' => '1$2', '/(in)($|[^aeiou1234])/' => '4$2' ); /**
  • private replacement array
  • /
private $aReplaceGrp6 = array ( '/([aeiou1234])(s)([aeiou1234])/' => '$1z$3' ); /**
  • private replacement array
  • /
private $aReplaceGrp7 = array ( 'oe' => 'e', 'eu' => 'e', 'au' => 'o', 'oi' => '2', 'oy' => '2', 'ou' => '3' ); /**
  • private replacement array
  • /
private $aReplaceGrp8 = array ( 'ch' => '5', 'sch' => '5', 'sh' => '5', 'ss' => 's', 'sc' => 's' ); /**
  • private replacement array
  • /
private $aReplaceGrp9 = array ( '/(c)([ei])/' => 's$2' ); /**
  • private replacement array
  • /
private $aReplaceGrp10 = array ( 'c' => 'k', 'q' => 'k', 'qu' => 'k', 'gu' => 'k', 'ga' => 'ka', 'go' => 'ko', 'gy' => 'ky' ); /**
  • private replacement array
  • /
private $aReplaceGrp11 = array ( 'a' => 'o', 'd' => 't', 'p' => 't', 'j' => 'g', 'b' => 'f', 'v' => 'f', 'm' => 'n' ); /**
  • private replacement array
  • /
private static $aReplaceGrp12 = array ( '1', '2', '3', '4', '5', 'e', 'f', 'g', 'h', 'i', 'k', 'l', 'n', 'o', 'r', 's', 't', 'u', 'w', 'x', 'y', 'z' ); /**
  • private replacement array
  • /
private $aEnd = array ( 't', 'x' ); /**
  • public function build ()
  • main method, building the phonex code of a given string
  • @Param string sString : the string!
  • /
public function build ($sString) { if (is_string ($sString)) { $this -> sString = $sString; } $this -> sString = strtolower ($this -> sString); $this -> sString = str_replace ('y', 'i', $this -> sString); $this -> sString = preg_replace ('/(?<![csp])h/', '', $this -> sString); $this -> sString = str_replace ('ph', 'f', $this -> sString); $this -> aReplace ($this -> aReplaceGrp1); $this -> aReplace ($this -> aReplaceGrp2, true); $this -> aReplace ($this -> aReplaceGrp3); $this -> aReplace ($this -> aReplaceGrp4); $this -> aReplace ($this -> aReplaceGrp5, true); $this -> aReplace ($this -> aReplaceGrp6, true); $this -> aReplace ($this -> aReplaceGrp7); $this -> aReplace ($this -> aReplaceGrp8); $this -> aReplace ($this -> aReplaceGrp9, true); $this -> aReplace ($this -> aReplaceGrp10); $this -> aReplace ($this -> aReplaceGrp11); $this -> sString = preg_replace( '`(.)\1`', '$1', $this -> sString ); $this -> trimLast (); $this -> getNum (); } /**
  • private function aReplace ()
  • method used to replace letters, given an array
  • @Param array aTab : the replacement array to be used
  • @Param bool bPreg : is the array an array of regular expressions patterns : true => yes`| false => no
  • /
private function aReplace (array $aTab, $bPreg = false) { if (false === $bPreg) { $this -> sString = str_replace (array_keys ($aTab), array_values ($aTab), $this -> sString); } else { $this -> sString = preg_replace (array_keys ($aTab), array_values ($aTab), $this -> sString); } } /**
  • private function trimLast ()
  • method to trim the bad endings
  • /
private function trimLast () { $length = strlen ($this -> sString) - 1; if (in_array ($this -> sString{$length}, $this -> aEnd)) { $this -> sString = substr ($this -> sString, 0, $length); } } /**
  • private static function mapNum ()
  • callback method to create the phonex numeric code, base 22
  • @Param int val : current value
  • @Param int clef : current key
  • @Returns int num : the calculated base 22 value
  • /
private static function mapNum ($val, $clef) { $num = array_search ($val, self::$aReplaceGrp12); $num *= pow (22, - ($clef + 1)); return $num; } /**
  • private function getNum ()
  • method to get a numeric array from the main string
  • we call the callback function mapNum and we add every values of the obtained array to get the final phonex code
  • /
private function getNum () { $aString = str_split ($this -> sString); $aNum = array_map (array ('self', 'mapNum'), array_values ($aString), array_keys ($aString)); $this -> sString = (string) array_sum ($aNum); } } ?>

Conclusion :


Reste des imperfections et des étrangetés...si quelqu'un veut s'amuser à débugger, il le peut. Je fais de même de mon côté :-)

Je remercie Malik qui m'a aidé a débugger un peu l'algo :-) Quelques bugs subsistaient sur l'algo que j'ai suivi.
Maintenant, il ne devrait plus y en avoir!
Seul bémol : php n'utilise pas des nombres de taille suffisemment grande pour que le code phonex base22 soit aussi long que celui de l'algo original.
Je travaille à contourner ce problème, mais j'ai quelques petits soucis avec bcmath :-)
Ceci dit, ça tourne en l'état, et plutôt pas mal même :-)

Codes Sources

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.