Une bibliothèque de recherche floue pour PHP
Il s'agit d'un portage PHP du génial projet Fuse.js et vise à fournir une compatibilité API complète dans la mesure du possible.
Consultez leur démo et leurs exemples pour avoir une bonne idée de ce dont cette bibliothèque est capable.
Dernière version Fuse.js compatible : 7.0.0
Table des matières:
Ce package est disponible via Composer. Pour l'ajouter à votre projet, exécutez simplement :
composer require loilo/fuse
Notez qu'au moins PHP 7.4 est nécessaire pour utiliser Fuse.
Voici un exemple d'utilisation simple :
<?php
require_once ' vendor/autoload.php ' ;
$ list = [
[
' title ' => " Old Man's War " ,
' author ' => ' John Scalzi ' ,
],
[
' title ' => ' The Lock Artist ' ,
' author ' => ' Steve Hamilton ' ,
],
[
' title ' => ' HTML5 ' ,
' author ' => ' Remy Sharp ' ,
],
[
' title ' => ' Right Ho Jeeves ' ,
' author ' => ' P.D Woodhouse ' ,
],
];
$ options = [
' keys ' => [ ' title ' , ' author ' ],
];
$ fuse = new Fuse Fuse ( $ list , $ options );
$ fuse -> search ( ' hamil ' );
Cela conduit aux résultats suivants (où item
de chaque résultat fait référence à l'entrée correspondante elle-même et refIndex
fournit la position de l'élément dans le $list
d'origine) :
[
[
' item ' => [
' title ' => ' The Lock Artist ' ,
' author ' => ' Steve Hamilton ' ,
],
' refIndex ' => 1 ,
],
[
' item ' => [
' title ' => ' HTML5 ' ,
' author ' => ' Remy Sharp ' ,
],
' refIndex ' => 2 ,
],
];
Fuse propose de nombreuses options pour affiner votre recherche :
isCaseSensitive
bool
false
Indique si les comparaisons doivent être sensibles à la casse.
includeScore
bool
false
Indique si le score doit être inclus dans l'ensemble de résultats. Un score de 0
indique une correspondance parfaite, tandis qu’un score de 1
indique une inadéquation totale.
includeMatches
bool
false
Indique si les correspondances doivent être incluses dans le jeu de résultats. Lorsque true
, chaque enregistrement du jeu de résultats inclura les indices des caractères correspondants. Ceux-ci peuvent par conséquent être utilisés à des fins de mise en évidence.
minMatchCharLength
int
1
Seules les correspondances dont la longueur dépasse cette valeur seront renvoyées. (Par exemple, si vous souhaitez ignorer les correspondances à un seul caractère dans le résultat, définissez-le sur 2
).
shouldSort
bool
true
S'il faut trier la liste des résultats, par score.
findAllMatches
bool
false
Lorsque cela est vrai, la fonction de correspondance continuera jusqu'à la fin d'un modèle de recherche même si une correspondance parfaite a déjà été localisée dans la chaîne.
keys
array
[]
Liste des clés qui seront recherchées. Cela prend en charge les chemins imbriqués, la recherche pondérée, la recherche dans des tableaux de chaînes et d'objets.
location
int
0
Détermine approximativement où dans le texte se trouve le motif attendu.
threshold
float
0.6
À quel moment l’algorithme de correspondance abandonne-t-il. Un seuil de 0.0
nécessite une correspondance parfaite (des lettres et de l'emplacement), un seuil de 1.0
correspondrait à n'importe quoi.
distance
int
100
Détermine à quel point la correspondance doit être proche de l'emplacement flou (spécifié par location
). Une correspondance exacte de lettres située distance
des caractères de l'emplacement flou serait considérée comme une inadéquation totale. Une distance
de 0
nécessite que la correspondance se déroule à l' location
exact spécifié. Une distance de 1000
nécessiterait qu'une correspondance parfaite se situe à moins de 800
caractères de l' location
à trouver en utilisant un threshold
de 0.8
.
ignoreLocation
bool
false
Lorsque true
, la recherche ignorera location
et distance
, donc peu importe où le modèle apparaît dans la chaîne.
Astuce : Les options par défaut recherchent uniquement les 60 premiers caractères. Cela devrait suffire si l’on peut raisonnablement s’attendre à ce que la correspondance se situe dans cette fourchette. Pour modifier ce comportement, définissez la combinaison appropriée de
location
,threshold
etdistance
(ouignoreLocation
).Pour mieux comprendre comment ces options fonctionnent ensemble, lisez la théorie de la notation de Fuse.js.
useExtendedSearch
bool
false
Lorsque true
, cela permet l’utilisation de commandes de recherche de type Unix. Voir exemple.
getFn
callable
La fonction à utiliser pour récupérer la valeur d'un objet au chemin fourni. La valeur par défaut recherchera également les chemins imbriqués.
sortFn
callable
La fonction à utiliser pour trier tous les résultats. La valeur par défaut sera triée par score de pertinence croissant, index croissant.
ignoreFieldNorm
bool
false
Lorsque true
, le calcul du score de pertinence (utilisé pour le tri) ignorera la norme de longueur de champ.
Astuce : La seule fois où il est judicieux de définir
ignoreFieldNorm
surtrue
c'est lorsque le nombre de termes n'a pas d'importance, mais uniquement l'existence du terme de requête.
fieldNormWeight
float
1
Détermine dans quelle mesure la norme de longueur de champ affecte le score. Une valeur de 0
équivaut à ignorer la norme de longueur de champ. Une valeur de 0.5
réduira considérablement l’effet de la norme de longueur de champ, tandis qu’une valeur de 2.0
l’augmentera considérablement.
Vous pouvez accéder et manipuler les valeurs par défaut de toutes les options ci-dessus via la méthode config
:
// Get an associative array of all options listed above
Fuse :: config ();
// Merge associative array of options into default config
Fuse :: config ([ ' shouldSort ' => false ]);
// Get single default option
Fuse :: config ( ' shouldSort ' );
// Set single default option
Fuse :: config ( ' shouldSort ' , false );
Les méthodes suivantes sont disponibles sur chaque instance FuseFuse
:
search
Recherche dans toute la collection de documents et renvoie une liste de résultats de recherche.
public function search( mixed $ pattern , ? array $ options ): array
Le $pattern
peut être l'un des suivants :
Les $options
:
limit
(type : int
) : désigne le nombre maximum de résultats de recherche renvoyés.setCollection
Définir/remplacer toute la collection de documents. Si aucun index n'est fourni, un sera généré.
public function setCollection( array $ docs , ? Fuse Core FuseIndex $ index ): void
Exemple:
$ fruits = [ ' apple ' , ' orange ' ];
$ fuse = new Fuse ( $ fruits );
$ fuse -> setCollection ([ ' banana ' , ' pear ' ]);
add
Ajoute un document à la collection et met à jour l'index en conséquence.
public function add( mixed $ doc ): void
Exemple:
$ fruits = [ ' apple ' , ' orange ' ];
$ fuse = new Fuse ( $ fruits );
$ fuse -> add ( ' banana ' );
sizeof ( $ fruits ); // => 3
remove
Supprime tous les documents de la liste pour lesquels le prédicat renvoie la vérité et renvoie un tableau des documents supprimés. Le prédicat est invoqué avec deux arguments : ($doc, $index)
.
public function remove(? callable $ predicate ): array
Exemple:
$ fruits = [ ' apple ' , ' orange ' , ' banana ' , ' pear ' ];
$ fuse = new Fuse ( $ fruits );
$ results = $ fuse -> remove (fn( $ doc ) => $ doc === ' banana ' || $ doc === ' pear ' );
sizeof ( $ fuse -> getCollection ()); // => 2
$ results ; // => ['banana', 'pear']
removeAt
Supprime le document à l'index spécifié.
public function removeAt( int $ index ): void
Exemple:
$ fruits = [ ' apple ' , ' orange ' , ' banana ' , ' pear ' ];
$ fuse = new Fuse ( $ fruits );
$ fuse -> removeAt ( 1 );
$ fuse -> getCollection (); // => ['apple', 'banana', 'pear']
getIndex
Renvoie l'index Fuse généré.
public function getIndex(): Fuse Core FuseIndex
Exemple:
$ fruits = [ ' apple ' , ' orange ' , ' banana ' , ' pear ' ];
$ fuse = new Fuse ( $ fruits );
$ fuse -> getIndex ()-> size (); // => 4
Les méthodes suivantes sont disponibles sur chaque instance FuseFuse
:
Fuse::createIndex
Pré-générez l'index à partir de la liste et transmettez-le directement dans l'instance Fuse. Si la liste est (considérablement) longue, cela accélère l’instanciation.
public static function createIndex( array $ keys , array $ docs , array $ options = []): Fuse Core FuseIndex
Exemple:
$ list = [ ... ]; // See the example from the 'Usage' section
$ options = [ ' keys ' => [ ' title ' , ' author.firstName ' ] ];
// Create the Fuse index
$ myIndex = Fuse :: createIndex ( $ options [ ' keys ' ], $ list );
// Initialize Fuse with the index
$ fuse = new Fuse ( $ list , $ options , $ myIndex );
Fuse::parseIndex
Analyse un index Fuse sérialisé JSON.
public static function parseIndex( array $ data , array $ options = []): Fuse Core FuseIndex
Exemple:
// (1) When the data is collected
$ list = [ ... ]; // See the example from the 'Usage' section
$ options = [ ' keys ' => [ ' title ' , ' author.firstName ' ] ];
// Create the Fuse index
$ myIndex = Fuse :: createIndex ( $ options [ ' keys ' ], $ list );
// Serialize and save it
file_put_contents ( ' fuse-index.json ' , json_encode ( $ myIndex ));
// (2) When the search is needed
// Load and deserialize index to an array
$ fuseIndex = json_decode ( file_get_contents ( ' fuse-index.json ' ), true );
$ myIndex = Fuse :: parseIndex ( $ fuseIndex );
// Initialize Fuse with the index
$ fuse = new Fuse ( $ list , $ options , $ myIndex );
Fuse.js | Fusible PHP | |
---|---|---|
Obtenir la version de Fuse | Fuse.version | – |
Accéder à la configuration globale | Propriété Fuse.config | Méthode Fuse::config |
Modification de liste | L'utilisation de fuse.add() etc. modifie la liste d'origine transmise au new Fuse . | En PHP, les tableaux sont un type de données primitif, ce qui signifie que votre liste d'origine n'est jamais modifiée par Fuse. Pour recevoir la liste actuelle après avoir ajouté/supprimé des éléments, la méthode $fuse->getCollection() peut être utilisée. |
Veuillez noter que je m'efforce d'atteindre la parité des fonctionnalités avec Fuse.js et que je n'ajouterai donc ni fonctionnalités ni correctifs à la logique de recherche qui ne sont pas reflétés dans Fuse.js lui-même.
Si vous rencontrez des problèmes avec les résultats de recherche qui ne sont pas manifestement des bogues dans ce port PHP et que vous connaissez JavaScript, veuillez vérifier si votre cas d'utilisation fonctionne correctement dans la démo en ligne de Fuse.js car il s'agit de l'implémentation canonique de Fuse. Si le problème apparaît également, veuillez ouvrir un problème dans leur dépôt.
Pour démarrer le développement sur Fuse, vous avez besoin de git, PHP (≥ 7.4) et Composer.
Étant donné que le code est formaté à l'aide de Prettier, il est également recommandé d'installer Node.js/npm ainsi que d'utiliser un éditeur prenant en charge le formatage Prettier.
Clonez le dépôt et insérez cd
y :
git clone https://github.com/loilo/fuse.git
cd fuse
Installer les dépendances de Composer :
composer install
Installez les dépendances npm (facultatif mais recommandé). Ceci n'est nécessaire que pour le formatage du code, car les dépendances npm incluent les plugins Prettier utilisés par ce projet.
npm ci
Il existe différents types de vérifications de code pour ce projet. Tous ces éléments sont exécutés lorsqu'une pull request est soumise, mais peuvent également être exécutés localement :
Commande | But | Description |
---|---|---|
vendor/bin/phpcs | vérifier le style du code | Exécutez PHP_CodeSniffer pour vérifier que le code source de Fuse respecte le style de codage PSR-12. |
vendor/bin/psalm | analyse statique | Exécutez Psalm sur la base de code pour éviter les erreurs liées au type et les modèles de codage dangereux. |
vendor/bin/phpunit | vérifier la logique du programme | Exécutez tous les tests PHPUnit à partir du dossier test . |
Avant de soumettre une pull request, veuillez ajouter les tests pertinents au dossier test
.