Scusa, ma ti ripeto, a me non piace l'idea di usare un ORM (su PHP) perché introduce vari strati in più che introducono aumento di risorse e complessità.
Tra l'altro poi un orm come doctrine che implementa il suo layer di astrazione del database che poggia su PDO, che è un framework di astrazione del database, che a sua volta poi, ovviamente, poggia sulle librerie di interfaccia di mysql è un'esagerazione ... almeno non avesse il suo layer di astrazione visto che sta usando PDO
Poi, personalmente, mi sono fatto degli strumenti che mi permettono di farne a meno con estrema tranquillità.
A tempi, quando ho iniziato a dare un occhiata agli ORM ho guardato sia doctrine sia propel, parlo di tre anni fa (anche tre e mezzo volendo), ma benché il concetto di ORM era interessante non mi è piaciuto più di tanto il come era implementato motivo per il quale mi sono realizzato, a tempi, degli strumenti che svolgono operazioni quasi simili e, ancora oggi, benché di tanto in tanto aggiunga qualche feature, si comportano più che bene e fanno il loro lavoro egregiamente.
Ma me li sono scritti in modo da ridurre il consumo di risorse al minimo senza compromettere lo sviluppo del codice di per se.
La memoria utilizzata dal mio CMS (costruito sul mio framework) di rado supera il MB e mezzo di memoria utilizzato e i tempi di esecuzione stanno sotto il decimo di secondo, conteggiato misurando anche il tempo di invio al browser (per fare le misurazioni utilizzo un htaccess con auto_prepend_file registra una funzione di shutdown che scrive in un file le informazioni che mi interessano tra cui le query eseguite, i tempi di esecuzioni delle query, i tempi di esecuzioni globali, la memoria utilizzata globale, la memoria utilizzata dai dati estratti con le query e via dicendo)
Ultimo appunto: perché nel mio framework faccio uso delle funzioni mysql_*? semplice motivo, queste funzioni sono una mappatura quasi diretta delle funzioni delle librerie di mysql e quindi non ci sono vari layer di astrazione come ci sono invece per PDO.
L'estensione mysqli, sinceramente, non l'ho più guardata perché se non ricordo male era buggata ed il suo sviluppo era stato fermato/rallentato in seguito a PDO, non so poi come le cose si siano messe relativamente a quell'estensione
Molto in generale, i file dei modelli dei dati estendono una classe che interfacciandosi con il database permette la semplice generazione di query di select, update, insert (on duplicate key) e delete.
Nello specifico i vari metodi di acquisizione (es. GetByPk, GetByUserId, GetByXYZ) mi corrispondono +/- alle chiavi che costruisco nel database, tutte comunque poggiano sul metodo GetByFilter che si occupa di prendere i filtri passati e, insieme ad altro materiale, costruirci la query tramite l'apposito metodo di supporto della classe base.
Una volta costruita la query questa viene mandata in esecuzione sul mio layer di astrazione dei database (che è abbastanza semplicistico e attualmente supporta mysql, sqlite, odbc e db2) e poi costruisce l'oggetto da tornarmi (o l'array di oggetti da tornarmi indicizzati tramite chiave primaria).
Per costruirmi l'oggetto, acquisisco l'array che prendo dal database e, nel ciclo while, lo faccio passare da un metodo che si occupa di tirarmi fuori un oggetto in base al nome della colonna ed in base al prefisso.
Inoltre, in automatico, mi converte i nomi del database, che scrivo sempre strutturati in un certo modo, in camel case, e lo fa in modo veloce e semplice
ESEMPIO:
il campo person_first_name o person_last_name in automatico diventa $oggetto->FirstName o $oggetto->LastName
nel momento in cui estraggo più tabelle lancio più volte la procedura di generazione della mappatura sempre in base al prefisso.
ESEMPIO
person_first_name, person_last_name, person_residence_address, person_residence_city, person_residence_zipcode, person_residence_province
con il prefisso person_ mi tira fuori $oggetto->FirstName, $oggetto->LastName
con il prefisso person_residence_ estrae invece $oggetto->Address, $oggetto->City, $oggetto->Zipcode, $oggetto->Province
fondamentalmente non faccio altro che fare
$person = $this->dbal->BuildObjectFromRow($row, 'person_');
$person->Residence = $this->dbal->BuildObjectFromRow($row, 'person_residence_');
Per i casi più complessi ho una procedura che mi fa la mappatura manuale alla quale passo un elenco di nome dell'oggetto e nome del campo/funzione da associare.
E' veloce, mi funziona bene, e mi accelera nella scrittura del codice a sufficienza, motivo per il quale, personalmente, non sento la necessità di usare un ORM.
E, ripeto, se dovessi (potessi) scegliere, lavorerei direttamente con un database oo e/o con uno storage per la persistenza degli oggetti
In generale, comunque, con questi semplici strumenti non sento la mancanza di un ORM e nel contempo ho prestazioni elevate e un consumo di risorse molto basso => questa procedura elabora 10000 records composti da 20 campi da mappare in circa 1.6s, ovvero, mediamente, 0.0001s a record