Originariamente inviato da oly1982
Codice PHP:
$prodotti_esistenti = array(
        
'scarpe di ginnastica',
        
'giubotto sportivo',
        
'maglione di lana');

function 
stringa_univoca($nuovo$esistenti$ciclo null){
    
// se la nuova stringa non è presente... ok
    
if(!in_array($nuovo $ciclo$esistenti)){
        return 
$nuovo $ciclo;
        }
    
// se presente
    
else{
        if(
is_null($ciclo))
            
$ciclo 1;
        
$ciclo++;
        return 
stringa_univoca($nuovo$esistenti$ciclo);
        }
    }
    
// proviamo ad aggiungere un prodotti con lo stesso nome... di quelli esistenti
$prodotti_esistenti[] = stringa_univoca('scarpe di ginnastica'$prodotti_esistenti);
$prodotti_esistenti[] = stringa_univoca('scarpe di ginnastica'$prodotti_esistenti);
$prodotti_esistenti[] = stringa_univoca('scarpe di ginnastica'$prodotti_esistenti);
$prodotti_esistenti[] = stringa_univoca('giubotto sportivo'$prodotti_esistenti);
$prodotti_esistenti[] = stringa_univoca('giubotto sportivo'$prodotti_esistenti);
$prodotti_esistenti[] = stringa_univoca('maglione di lana'$prodotti_esistenti);
// e un prodotto totalmente nuovo
$prodotti_esistenti[] = stringa_univoca('giacca elegante'$prodotti_esistenti);
sort($prodotti_esistenti);
echo 
'<pre>';
print_r($prodotti_esistenti); 
In pratica gestisci la collisione aggiungendo un indice numerico alla fine della stringa! Diciamo che a meno della stringa fai ne più ne meno di quanto farebbe un'autoincrement.

Non utilizzare la ricorsione, perché stai passando un array come argomento della funzione. Dato che in PHP gli array sono passati per valore (copiati) e non per riferimento, ad ogni chiamata hai la duplicazione dell'array. Con array piccoli e ricorsioni brevi non succede nulla, ma al crescere dell'array puoi esaurire la memoria e mandare in crash lo script.

In più, all'aumentare delle collisioni questo ciclo diventa sempre più lungo. So che vedi solo un'istruzione + un incremento all'interno del ciclo, ma quell'istruzione è una ricerca lineare all'interno di un array.

Il consiglio è di non memorizzare solo l'elenco delle stringhe esistenti, ma per ognuna anche l'ultimo indice utilizzato. Nel momento in cui aggiungi un prodotto puoi accedere all'elenco delle stringhe, verificarne l'esistenza e se non la trovi l'aggiungi all'elenco dando indice associato 1 e facendo restituire come ID la sola stringa. Se invece lo trovi, recuperi l'indice e lo aggiorni al valore successivo nell'elenco delle esistenti; quindi restituisci la stringa.indiceRecuperato. Nella sostanza stai implementando un repertorio il cui nome è il nome prodotto e per il primo valore di repertorio staccato, in vece dello 0, utilizzi la stringa vuota. L'elenco degli esistenti (i repertori) è su DB in modo da poter effettuare una transazione per ottenere l'indice ed aggiornarlo o utilizzando il blocco delle tabelle con myisam, mettendoti al riparo da accessi concorrenti.

Pseudocodice in cui si accede ad una sola tabella che ha due colonne:
nome -> chiave primaria (nome del prodotto o repertorio)
indice -> valore intero (numero di prodotto o repertorio successivo)
codice:
Funzione GeneraIDPer(nome){
    AccediAlDB;
    [INIZIO TRANSAZIONE]
        indice='';
        Se(CercaNelDB(nome) è Trovato){
            indice=OttieniIndiceDaRecordTrovato;
            AggiornaRecordTrovato(nome,indice+1);
        }altrimenti{
            InserisciRecord(nome,1);
        }
    [FINE TRANSAZIONE]
    StaccatiDalDB;
    Ritorna indice;
}
Ottieni così l'indice numerico che se vuoi concateni al nome.