composer update algolia/algoliasearch-client-php. Cette commande, lancée pour appliquer un correctif de sécurité signalé par un audit de dépendances, a suffi à faire disparaître silencieusement l’indexation des nouveaux produits d’une boutique WooCommerce, sans qu’aucune erreur ne remonte dans les journaux applicatifs.
Le SDK PHP d’Algolia a changé de forme entre ses versions majeures : les méthodes qui manipulaient un objet d’index dédié ont été remplacées par des appels directs sur le client, avec un nom d’index passé en paramètre. Un connecteur écrit pour l’ancienne forme continue de s’exécuter sans lever d’exception PHP, car les anciennes méthodes existent encore sur certaines versions transitoires — mais elles n’écrivent plus rien d’utile.
Symptôme
Le connecteur maison enregistrait les produits via un objet d’index obtenu par initIndex() :
$index = $client->initIndex('produits_boutique');
$index->saveObject([
'objectID' => $produit->get_id(),
'nom' => $produit->get_name(),
'prix' => $produit->get_price(),
]);
Après la montée de version, cette méthode n’est plus disponible sur le client tel qu’instancié par la fabrique du SDK : la classe retournée n’expose plus initIndex(). Le connecteur, lui, avait été écrit avec une vérification défensive method_exists() qui évitait toute erreur fatale mais abandonnait purement et simplement l’appel en cas d’absence de la méthode — d’où l’absence de journal d’erreur malgré l’échec réel de l’indexation.
Diagnostic

Le test qui aurait dû détecter le problème existait, mais il mockait l’objet d’index directement, sans jamais passer par la fabrique réelle du client :
public function test_indexation_produit(): void
{
$index = $this->createMock(SearchIndex::class);
$index->expects($this->once())->method('saveObject');
$connecteur = new ConnecteurAlgolia($index);
$connecteur->indexer($produit);
}
Ce test valide la logique interne du connecteur, mais pas la compatibilité avec le SDK réellement installé : puisque le mock impose l’existence de SearchIndex, il continue de passer même quand cette classe n’est plus celle instanciée en production. Le vrai point de défaillance — la fabrique du client qui ne retourne plus le même type d’objet — n’est jamais exercé.
- Repérer que le test mocke une classe intermédiaire disparue du SDK réel
- Vérifier la classe effectivement instanciée par
Algolia\AlgoliaSearch\Api\SearchClient::create() - Comparer la liste des méthodes disponibles avant et après la montée de version
Correctif
La nouvelle forme du SDK indexe directement via le client, avec le nom d’index en paramètre explicite :
$client->saveObjects('produits_boutique', [[
'objectID' => $produit->get_id(),
'nom' => $produit->get_name(),
'prix' => $produit->get_price(),
]]);
Le connecteur a été réécrit pour recevoir directement une instance de SearchClient plutôt qu’un objet d’index abstrait. Le test unitaire a lui aussi été récrit pour mocker SearchClient et vérifier l’appel exact à saveObjects() avec le nom d’index attendu, ce qui aurait immédiatement révélé la régression si ce test avait existé avant la montée de version :
public function test_indexation_produit_nouveau_sdk(): void
{
$client = $this->createMock(SearchClient::class);
$client->expects($this->once())
->method('saveObjects')
->with('produits_boutique', $this->isType('array'));
$connecteur = new ConnecteurAlgolia($client, 'produits_boutique');
$connecteur->indexer($produit);
}
Un test d’intégration complémentaire, exécuté contre une véritable application Algolia de test (et non un mock), reste la seule vérification qui aurait détecté à coup sûr le problème dès la mise à jour de la dépendance :
public function test_indexation_reelle_contre_application_de_test(): void
{
$client = SearchClient::create(getenv('ALGOLIA_APP_ID_TEST'), getenv('ALGOLIA_API_KEY_TEST'));
$client->saveObjects('produits_test', [['objectID' => '1', 'nom' => 'Produit test']]);
$resultat = $client->getObject('produits_test', '1');
$this->assertSame('Produit test', $resultat['nom']);
}
Prévention
Trois réflexes limitent le risque de récidive lors de la prochaine montée de version majeure du SDK :
- Bannir
method_exists()comme garde silencieuse autour d’un appel SDK critique : préférer laisser l’erreur remonter - Ajouter un test d’intégration contre une vraie application Algolia de test dans un pipeline CI dédié, exécuté avant chaque mise à jour de dépendance
- Épingler la version majeure du SDK dans
composer.jsonet exiger une revue explicite avant tout changement de version majeure
Un connecteur qui avale silencieusement l’absence d’une méthode se protège contre un plantage, mais garantit en échange une panne invisible : mieux vaut un test qui échoue bruyamment qu’une indexation qui s’arrête sans bruit.
En résumé
La montée de version d’un SDK tiers ne se limite jamais à un changement de numéro dans composer.json : quatre méthodes du connecteur ont dû être revues sur ce projet, et seul un test d’intégration contre une vraie instance de test aurait détecté la régression avant qu’elle n’atteigne la production. Prévoir ce test dès l’écriture du connecteur, plutôt qu’après le premier incident, reste la meilleure garantie.