2009-08-28 14 views
8

Quindi sto lavorando a un progetto per un agente immobiliare. Ho i seguenti oggetti/tabelle MySQL nel mio progetto:PHP/MySQL OOP: caricamento di oggetti complessi da SQL

Complexes 
Units 
Amenities 
Pictures 
Links 
Documents 
Events 
Agents 

Queste sono le relazioni tra gli oggetti di cui sopra.

Complexes have a single Agent. 
Complexes have multiple Units, Amenities, Pictures, Links, Documents, and Events. 
Units have multiple Pictures, Links, and Documents. 

Servizi, immagini, link, documenti, eventi e tutti hanno le chiavi esterne necessarie nel database per specificare quale unità/nel complesso a cui appartengono.

Ho bisogno di caricare gli oggetti necessari dal database in PHP in modo da poterli utilizzare nel mio progetto.

Se provo a selezionare tutti i dati dalla tabella in 1 query, utilizzando LEFT JOINS, otterrò ALMENO (numero di collegamenti) * (numero di immagini) * (numero di documenti) righe per ogni unità unica. Aggiungi servizi ed eventi a questo e io ricevo tutto questo * # di servizi * # di eventi per ogni complesso ... Non sono sicuro di voler provare ad occuparmi di caricarlo in un oggetto in PHP.

L'altra possibilità è per ogni complesso/unità, eseguire 1 istruzione SQL separati ciascuno per link, immagini, documenti, eventi e servizi

Le mie domande sono le seguenti:

Se correttamente indice di tutta la mia tabelle, è davvero una cattiva idea eseguire 3-5 query aggiuntive per ogni complesso/unità?

In caso contrario, in quale altro modo posso ottenere i dati che devo caricare in un oggetto PHP. Idealmente, avrei un oggetto come segue: per le unità

Unit Object 
(
    [id] 
    [mls_number] 
    [type] 
    [retail_price] 
    [investor_price] 
    [quantity] 
    [beds] 
    [baths] 
    [square_feet] 
    [description] 
    [featured] 
    [year_built] 
    [has_garage] 
    [stories] 
    [other_features] 
    [investor_notes] 
    [tour_link] 
    [complex] => Complex Object 
     (
      [id] 
      [name] 
      [description] 
      etc. 
     ) 
    [agent] => Agent Object 
     (
      [id] 
      [first_name] 
      [last_name] 
      [email] 
      [phone] 
      [phone2] 
      etc. 

     ) 
    [pictures] => Array 
     (
      [1] => Picture Object 
       (
       ) 
     ) 
    [links] => Array 
     (
      [1] => Link Object 
       (
       ) 
     ) 
    [documents] => Array 
     (
      [1] => Document Object 
       (
       ) 
     )  
) 

non sempre bisogno di tutte queste informazioni, a volte ho solo bisogno la chiave primaria del complesso, a volte ho solo bisogno della chiave primaria della agente, ecc. Ma ho pensato che il modo corretto per farlo sarebbe quello di caricare l'intero oggetto ogni volta che lo istanziato.

Ho fatto molte ricerche su OO PHP, ma la maggior parte degli esempi in linea (leggi tutto) usa solo 1 tabella. Questo ovviamente non aiuta poiché il progetto a cui sto lavorando ha molte relazioni complesse. Qualche idea? Sono totalmente fuori luogo qui?

Grazie

[UPDATE]

D'altra parte, di solito sul front-end, che tutti potranno vedere, ho bisogno di tutte le informazioni. Per esempio, quando qualcuno vuole informazioni su un complesso specifico, ho bisogno di visualizzare tutte le unità appartenenti a quel complesso, tutte le immagini, i documenti, i collegamenti, gli eventi per il complesso e tutte le immagini, i documenti e i collegamenti per l'unità.

Quello che speravo di evitare era, durante il caricamento di una pagina, l'esecuzione di una query per ottenere il complesso di cui ho bisogno. Quindi un'altra query per ottenere le 20 unità associate al complesso. Poi per ognuna delle 20 unità, eseguendo una query per l'immagine, un'altra per i documenti, un'altra per i collegamenti, ecc. Volevo averle tutte in una volta, con un solo passaggio nel database.

[EDIT 2] Inoltre, si noti che le query per selezionare le immagini, i documenti, i collegamenti, gli eventi e l'agente dal database sono piuttosto semplici. Semplicemente SELECT [lista di colonne] FROM [table] WHERE [primary_key] = [value] con l'occasionale INNER JOIN. Non sto facendo calcoli o subquery complessi, solo cose di base.

[BENCHMARK] Quindi dopo aver letto tutte le risposte alla mia domanda, ho deciso di eseguire un punto di riferimento su ciò che ho deciso di fare. Quello che faccio è caricare tutte le unità di cui ho bisogno. Poi, quando ho bisogno di mostrare immagini, documenti, blah blah, li carico in quel momento. Ho creato 30.000 unità di test, ciascuna con 100 immagini, 100 documenti e 100 collegamenti. Poi ho caricato un certo numero di unità (ho iniziato con 1000, poi 100, poi il più realistico 10), ho fatto il looping di esse, quindi ho caricato tutte le immagini, i documenti e i collegamenti associati all'unità. Con 1000 unità, ci sono voluti circa 30 secondi. Con 100 unità, ci sono voluti circa 3 secondi. Con 10 unità, ci sono voluti circa 0,5 secondi. C'era molta varianza con i risultati. A volte, con 10 unità, sarebbero necessari 12 secondi. Allora ci vorrebbe .8. Allora forse .5. Quindi .78. Era davvero dappertutto. Tuttavia, sembrava in media circa mezzo secondo. In realtà, però, potrei aver bisogno solo di 6 unità alla volta e ognuna di esse potrebbe avere solo 10 immagini, 5 link e 5 documenti associati ... quindi penso che l'approccio "afferra i dati quando ne hai bisogno" sia la migliore scommessa in una situazione come questa. Se avessi bisogno di ottenere tutti questi dati contemporaneamente, varrebbe la pena presentare una singola istruzione SQL per caricare tutti i dati di cui hai bisogno in modo tale da farli scorrere solo una volta (6700 unità alla volta impiegarono 217 secondi mentre i 30.000 completi hanno fatto scadere la memoria del PHP).

risposta

4

Se indicizzo correttamente tutti i miei tavoli, è VERAMENTE una cattiva idea eseguire 3-5 query aggiuntive per ogni complesso/unità?

In breve, no. Per ognuna delle tabelle correlate, probabilmente dovresti eseguire una query separata. Questo è ciò che farebbero la maggior parte dei sistemi ORM (Object-Relational Mapping/Modelling).

Se le prestazioni sono davvero un problema (e, in base a quello che hai detto, non sarà), allora si potrebbe prendere in considerazione la memorizzazione nella cache i risultati utilizzando qualcosa come APC, memcache o XCache.

0

il punto di ORM non deve caricare interi oggetti ogni volta. il punto è rendere l'applicazione più semplice e trasparente per accedere all'oggetto.

detto questo, se è necessario l'oggetto unità, quindi caricare l'oggetto unità e solo l'oggetto unità. se è necessario l'oggetto agente, caricarlo quando è necessario, non quando si carica l'oggetto unità.

+0

Il problema più grande è che per la sezione di amministrazione, questi pezzi sono segmentati per consentire una gestione granulare. Ma sul front-end, 1 pagina visualizzerà un complesso, tutte le sue unità, tutte le relative immagini, documenti, eventi e collegamenti, nonché l'Agente assegnato e le informazioni di contatto ... – SpaDusA

+0

dato che accederai ai tuoi dati tramite colonne indicizzate e in realtà utilizzando tutto questo, questo non dovrebbe essere un problema. la mia risposta è stata orientata a ritrarre tutti i dati perché l'ORM ha detto così, anziché perché verrà utilizzato. – longneck

0

Forse dovresti pensare a rompere questo.

Quando si avvia l'oggetto, ottenere solo i dettagli necessari per il funzionamento di tale oggetto. Se e quando hai bisogno di maggiori dettagli, allora vai a prenderli. Distribuisci il tuo carico ed elaborazione in questo modo: l'oggetto riceve solo il carico e l'elaborazione necessari per funzionare, e quando ce n'è più bisogno, lo ottiene in quel momento.

Quindi, nel tuo esempio, crea prima il complesso. Quando avete bisogno di accedere a un'unità, quindi creare quell'unità, quando si ha bisogno l'agente, quindi ottenere che l'agente, ecc

$complexDetails = array('id' => $id, etc); 
$complexUnits = array(); 
......... 
$complexUnits[] = new unit(); 
......... 
$complexDetails['agent'] = new Agent(); 
0

ho dovuto affrontare questo problema un po 'indietro quando ho architettato il mio framework MVC come un esperimento. Per limitare gli strati di dati caricati dal DB, ho passato un intero al costruttore. Ogni costruttore decrementerebbe questo intero prima di passarlo ai costruttori degli oggetti che ha istanziato. Quando è arrivato a 0, non saranno più istanziati gli oggetti secondari. Ciò significava, in sostanza, che int passato era il numero di layer caricati.

Quindi, se ho voluto solo un attributo dell'oggetto unità, farei questo:

 
$myUnit = new Unit($unitId,1); 
0

Se si desidera "Store" gli oggetti, il che significa cache di loro, proprio caricarli in un array PHP e serializzarlo. Quindi è possibile memorizzarlo nel database, in memcache o in qualsiasi altro luogo. Se si collega un'etichetta, è possibile recuperarla e includere un timestamp in modo da sapere quanti anni ha (vale a dire che deve essere aggiornato).

Se i dati non cambiano o cambiano raramente, non c'è davvero alcun motivo per eseguire più query complesse ogni volta. Semplici, come ottenere un primario, si potrebbe anche colpire direttamente il database.

+0

Non voglio archiviare gli oggetti, non penso. Quello che sto cercando di capire è come caricare le informazioni nel database in modo efficiente in PHP. – SpaDusA

Problemi correlati