Un developer Magento ha sostituito 300 chiamate separate a ProductRepositoryInterface::getById() con un'unica query di collezione. Le chiamate al database sono scese da 300 a 1 e la pagina di categoria si è caricata sensibilmente più velocemente. Il rovescio della medaglia? Alcuni prodotti sono scomparsi dal negozio online, lasciando confusi sia i clienti che i proprietari.

Il problema N+1 in una pagina di categoria Magento

La pagina elencava 300 prodotti. Per ognuno di essi, il codice recuperava due attributi personalizzati tramite il metodo getById() del repository, generando una query per prodotto: il classico pattern N+1. Sostituire questi caricamenti per singolo prodotto con una collezione che estrae tutte le righe necessarie in un'unica query ha drasticamente ridotto il numero di query. La latenza del front-end è migliorata, ma l'elenco dei prodotti ora ometteva articoli che prima erano presenti.

Perché la collezione nasconde gli articoli esauriti

Il modulo CatalogInventory di Magento aggiunge automaticamente un filtro "in-stock" a qualsiasi collezione di prodotti creata per il frontend. Il filtro si attiva quando l'impostazione del negozio Display Out of Stock Products è disattivata, una scelta comune per i commercianti che non vogliono mostrare articoli non disponibili.

Al contrario, il repository non applica mai un filtro di stock. Verifica semplicemente che un prodotto esista e lo restituisce, indipendentemente dal livello di inventario. Quando il codice è passato dalle chiamate al repository a una collezione, il filtro di stock ha rimosso silenziosamente ogni prodotto la cui quantità era pari a zero. Nessun errore registrato; la collezione ha semplicemente restituito meno righe di quelle previste dallo sviluppatore.

Cosa significa questo per i commercianti

Un negozio online che elimina silenziosamente gli SKU esauriti crea diversi problemi:

  • I componenti del front-end ricevono voci mancanti, producendo etichette vuote o prezzi errati.
  • Il debugging diventa più difficile perché il sintomo — la mancanza di prodotti — non genera avvisi.

Poiché la maggior parte dei test automatizzati utilizza fixture di prodotti disponibili, il bug spesso rimane nascosto finché il sito non viene eseguito con l'inventario reale.

Come mantenere la velocità senza nascondere l'inventario

  1. Saltare il filtro di stock predefinito – Rimuovere esplicitamente il filtro dalla collezione se è necessario ogni prodotto indipendentemente dalla disponibilità. Magento offre metodi per disabilitare o sostituire il plugin di stock per singola query.
  2. Usare il repository quando la precisione è fondamentale – Il repository garantisce che ogni ID prodotto richiesto venga restituito, anche se esaurito. Sfrutta la cache dei risultati o carica solo gli ID necessari per contenere il numero di query extra.
  3. Utilizzare un resource model o SQL raw – Interrogare direttamente la tabella dei prodotti per gli attributi richiesti. Questo bypassa tutti i plugin della collezione e offre il pieno controllo sulle righe incluse.

Velocità contro correttezza

Sostituire un loop N+1 rumoroso con un'unica query di collezione sembra naturale; il calo della latenza è tangibile. Tuttavia, una query più veloce che restituisce un set errato di prodotti è un difetto, non un'ottimizzazione. Gli sviluppatori devono bilanciare la velocità pura con il rischio di mostrare un catalogo incompleto.

Cosa monitorare in seguito

  • Deriva della configurazione – Verificare che il flag Display Out of Stock Products corrisponda al comportamento previsto di qualsiasi codice di collezione personalizzato.
  • Effetti collaterali dei plugin – Altri moduli potrebbero aggiungere i propri filtri alle collezioni. Esaminare lo stack dei plugin ogni volta che si cambiano le strategie di query.

La lezione è chiara: risolvere un problema N+1 con una collezione è vantaggioso solo se si sottopongono a revisione anche i filtri predefiniti della collezione stessa. Ignorare il filtro di stock integrato in Magento può potare silenziosamente il catalogo, trasformando un miglioramento delle prestazioni in una perdita di fatturato.