2009-08-28 9 views
8

Así que estoy trabajando en un proyecto para un agente de bienes raíces. Tengo los siguientes objetos/tablas MySQL en mi diseño:PHP/MySQL OOP: Cargando objetos complejos desde SQL

Complexes 
Units 
Amenities 
Pictures 
Links 
Documents 
Events 
Agents 

Estas son las relaciones entre los objetos anteriores.

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

Servicios, imágenes, enlaces, documentos y eventos todos tienen las claves externas necesarias en la base de datos para especificar qué unidad/complejo al que pertenecen.

Necesito cargar los objetos necesarios de la base de datos en PHP para poder usarlos en mi proyecto.

Si trato de seleccionar todos los datos fuera de la tabla en 1 consulta, usando UNIONES IZQUIERDAS, obtendré POR LO MENOS (# de enlaces) * (# de imágenes) * (# de documentos) filas para cada unidad única. Agregue servicios y eventos a eso y obtendré todo * * de comodidades * # de eventos para cada complejo ... No estoy seguro de querer tratar de cargar eso en un objeto en PHP.

La otra posibilidad es que cada complejo/unidad, ejecutar 1 instrucción SQL por separado cada uno de los enlaces, imágenes, documentos, eventos y servicios

Mis preguntas son las siguientes:

Si adecuadamente índice de toda mi tablas, ¿REALMENTE es una mala idea ejecutar 3-5 consultas adicionales para cada complejo/unidad?

Si no, ¿cómo más puedo obtener los datos que necesito para cargar en un objeto PHP. Idealmente, me gustaría tener un objeto de la siguiente manera: para las unidades

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 
       (
       ) 
     )  
) 

yo no siempre necesitan toda esta información, a veces sólo necesito la clave principal del complejo, a veces sólo necesito la clave principal de la agente, etc. Pero pensé que la forma correcta de hacerlo sería cargar todo el objeto cada vez que lo instanciara.

He estado investigando mucho sobre OO PHP, pero la mayoría (lea todo) de ejemplos en línea usan solo 1 tabla. Obviamente, eso no ayuda, ya que el proyecto en el que estoy trabajando tiene muchas relaciones complejas. ¿Algunas ideas? ¿Estoy totalmente fuera de lugar aquí?

Gracias

[ACTUALIZACIÓN]

Por otro lado, por lo general en el front-end, que todo el mundo verá, necesitaré toda la información. Por ejemplo, cuando alguien quiere información sobre un complejo específico, necesito mostrar todas las unidades que pertenecen a ese complejo, todas las imágenes, documentos, enlaces, eventos para el complejo, así como todas las imágenes, documentos y enlaces de la unidad.

Lo que esperaba evitar fue, durante una carga de página, ejecutar una consulta para obtener el complejo que necesito. Luego otra consulta para obtener las 20 unidades asociadas al complejo. Luego, para cada una de las 20 unidades, ejecutando una consulta de imagen, otra para documentos, otra para enlaces, etc. Quería obtenerlos todos a la vez, con un viaje a través de la base de datos.

[EDIT 2] Además, tenga en cuenta que las consultas para seleccionar las imágenes, documentos, enlaces, eventos y agentes de la base de datos son bastante simples. Solo básico SELECCIONE [lista de columnas] FROM [table] WHERE [primary_key] = [value] con el INNER JOIN ocasional. No estoy haciendo cálculos complejos o subconsultas, solo cosas básicas.

[BENCHMARK] Luego de leer todas las respuestas a mi pregunta, decidí ejecutar un punto de referencia sobre lo que decidí hacer. Lo que hago es cargar todas las unidades que necesito. Luego, como necesito mostrar imágenes, documentar, bla, bla, las cargo en ese momento. Creé 30,000 unidades de prueba, cada una con 100 imágenes, 100 documentos y 100 enlaces. Luego cargué un cierto número de unidades (empecé con 1000, luego 100, luego el 10 más realista), las enrollé y luego cargué todas las imágenes, documentos y enlaces asociados a la unidad. Con 1000 unidades, tomó aproximadamente 30 segundos. Con 100 unidades, tomó aproximadamente 3 segundos. Con 10 unidades, tomó aproximadamente .5 segundos. Hubo mucha variación con los resultados. Algunas veces, con 10 unidades, tomaría .12 segundos. Entonces tomaría .8. Entonces tal vez .5. Entonces .78. Fue realmente por todo el lugar. Sin embargo, pareció promediar alrededor de medio segundo. En realidad, sin embargo, es posible que solo necesite 6 unidades a la vez, y cada una de ellas podría tener solo 10 imágenes, 5 enlaces y 5 documentos asociados a ellas ... así que creo que el enfoque de "tomar los datos cuando lo necesite" es la mejor apuesta en una situación como esta. Sin embargo, si necesita obtener todos estos datos de una vez, valdría la pena crear una única instrucción SQL para cargar todos los datos que necesita, de modo que solo esté recorriendo los datos una vez (6700 unidades a la vez tardan 217 segundos). mientras que los 30,000 completos hicieron que PHP se quedara sin memoria).

Respuesta

4

Si I correctamente índice de todas mis tablas, ¿es realmente una mala idea para ejecutar 3-5 consultas adicionales para cada complejo/unidad?

En resumen, no. Para cada una de las tablas relacionadas, probablemente debería ejecutar una consulta por separado. Eso es lo que harían la mayoría de los sistemas ORM (Object Relational Mapping/Modeling).

Si el rendimiento es realmente un problema (y, en base a lo que ha dicho, no será) entonces puede considerar almacenar en caché los resultados utilizando algo como APC, Memcache o Xcache.

0

El objetivo de ORM es no cargar objetos completos todo el tiempo. el objetivo es hacer que su aplicación tenga acceso fácil y transparente a los objetos.

Dicho esto, si necesita el objeto de la unidad, cargue el objeto de la unidad y solo el objeto de la unidad. si necesita el objeto agente, cárguelo cuando lo necesite, no cuando cargue el objeto de la unidad.

+0

El problema más grande es que para la sección de administración, estas piezas están segmentadas para permitir la administración granular. Pero en el front-end, 1 página mostrará un complejo, todas sus unidades, todas las imágenes relacionadas, documentos, eventos y enlaces, así como el agente asignado y la información de contacto ... – SpaDusA

+0

ya que estará accediendo a sus datos a través de columnas indexadas y realmente usándolo todo, esto no debería ser un problema. mi respuesta estaba orientada a retirar todos los datos porque el ORM lo decía, en lugar de porque se usará. – longneck

0

Quizás debería pensar en romper esto.

Cuando inicie su objeto, obtenga solo los detalles que necesita para que funcione ese objeto. Si necesitas más detalles, ve a buscarlos. Usted distribuye su carga y su procesamiento de esta manera: el objeto solo obtiene la carga y el procesamiento que necesita para funcionar, y cuando se necesita más, lo obtiene en ese momento.

Por lo tanto, en su ejemplo, cree primero el complejo. Cuando se necesita acceder a una unidad, a continuación, crear esa unidad, cuando se necesita el agente, a continuación, obtener ese agente, etc.

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

que tenía que tratar este tema hace un tiempo cuando me inventé mi propio marco MVC un experimento. Para limitar las capas de datos cargados desde el DB, pasé un entero al constructor. Cada constructor disminuiría este entero antes de pasarlo a los constructores de los objetos que creó. Cuando llegó a 0, no se crearían más instancias de subobjetos. Esto significa, básicamente, que el int pasado fue el número de capas cargadas.

Así que si yo sólo quería un atributo del objeto de unidad, lo haría esto:

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

Si quieres a "almacenar" los objetos, lo que significa caché ellos, sólo cargarlos en una matriz PHP y serializarlo. Luego puede almacenarlo en la base de datos, en Memcache o en cualquier otro lugar. Adjuntar una etiqueta le permitiría recuperarlo, e incluir una marca de tiempo para que sepa qué edad tiene (es decir, necesita actualizarse).

Si los datos no cambian, o cambian con poca frecuencia, realmente no hay razón para ejecutar múltiples consultas complejas todo el tiempo. Los más simples, como obtener una primaria, también podría simplemente golpear la base de datos directamente.

+0

No quiero almacenar los objetos, no creo. Lo que estoy tratando de averiguar es cómo cargar la información en la base de datos de manera eficiente en PHP. – SpaDusA

Cuestiones relacionadas