2011-02-03 16 views
6

Estoy usando Doctrine 1.2 con Symfony 1.4. Digamos que tengo un modelo de usuario, que tiene un perfil. Estos se definen como:¿Agregar columnas virtuales a la tabla actual en Doctrine?

usuario:

  • Identificación
  • nombre de usuario
  • contraseña
  • created_at
  • updated_at

Perfil:

  • Identificación
  • user_id
  • nombre apellido
  • apellidos
  • dirección
  • ciudad
  • postal_code

Me normalmente recibe datos como estos:

$query = Doctrine_Query::create() 
    ->select('u.id, u.username, p.first_name, p.last_name') 
    ->from('User u') 
    ->leftJoin('Profile p') 
    ->where('u.username = ?', $username); 
$result = $query->fetchOne(array(), Doctrine_Core::HYDRATE_ARRAY); 
print_r($result); 

Esta salida algo sería como el siguiente:

Array (
    "User" => Array (
     "id" => 1, 
     "username" => "jschmoe" 
    ), 
    "Profile" => Array (
     "first_name" => "Joseph", 
     "last_name" => "Schmoe" 
    ) 
) 

Sin embargo, me gustaría para el usuario para incluir columnas "virtuales" (no estoy seguro si este es el término correcto) de tal manera que los campos de perfil en realidad parece que es parte del usuario En otras palabras, me gusta para ver la declaración print_r vea más como:

Array (
    "User" => Array (
     "id" => 1, 
     "username" => "jschmoe", 
     "first_name" => "Joseph", 
     "last_name" => "Schmoe" 
    ) 
) 

¿Hay una manera de hacerlo a través de mi archivo schema.yml oa través de mi objetivo Doctrine_Query?

Respuesta

6

La manera de hacer lo que quiere es utilizar un custom Hydrator.

class Doctrine_Hydrator_MyHydrator extends Doctrine_Hydrator_ArrayHierarchyDriver 
{ 
    public function hydrateResultSet($stmt) 
    { 
     $results = parent::hydrateResultSet($stmt); 
     $array = array(); 

     $array[] = array('User' => array(
      'id'   => $results['User']['id'], 
      'username' => $results['User']['username'], 
      'first_name' => $results['Profile']['first_name'], 
      'last_name' => $results['Profile']['last_name'], 
     )); 

     return $array(); 
    } 
} 

continuación, se registra que Hidratante con el administrador de conexión:

$manager->registerHydrator('my_hydrator', 'Doctrine_Hydrator_MyHydrator'); 

Entonces hidratar su consulta como esta:

$query = Doctrine_Query::create() 
    ->select('u.id, u.username, p.first_name, p.last_name') 
    ->from('User u') 
    ->leftJoin('Profile p') 
    ->where('u.username = ?', $username); 

$result = $query->fetchOne(array(), 'my_hydrator'); 
print_r($result); 

/* outputs */ 
Array (
    "User" => Array (
     "id" => 1, 
     "username" => "jschmoe", 
     "first_name" => "Joseph", 
     "last_name" => "Schmoe" 
    ) 
) 

puede que tenga que multas la lógica hyrdator un poco para conseguir la estructura de matriz exacta que desea. Pero esta es la forma aceptable de hacer lo que quieras.

+0

Excelente, muchas gracias, ¡esto es muy útil! –

+0

Ahora que sé lo que estoy buscando, aquí hay un enlace útil para aquellos que están haciendo algo similar en Symfony (como yo): http://www.symfony-project.org/more-with-symfony/1_4/en/08-Advanced-Doctrine-Usage # chapter_08_sub_using_the_hydrator –

+0

Una última pequeña nota: necesitaba mi hidratador para extender 'Doctrine_Hydrator_ArrayDriver', no' Doctrine_Hydrator_ArrayHierarchyDriver'. –

0

no utilizo gama de hidratación mucho así que tal vez yo no he notado, pero podría haber jurado la estructura que usted está buscando es cuál es producido por:

Doctrine_Query::create() 
    ->select('u.id, u.username, p.first_name, p.last_name') 
    ->from('User u') 
    ->leftJoin('Profile p') 
    ->where('u.username = ?', $username); 
+0

Estoy confundido por su código de muestra ... parece que acaba de copiar y pegar lo que escribí en la pregunta original, a menos que me falta algo. –

+0

usando 'from' en lugar de' createQuery' es la única diferencia ... pero parece que lo cambiaste en algún momento ... – prodigitalson

+0

Sí, podría haberlo editado al mismo tiempo que estabas respondiendo ... el createQuery fue un error al copiar mi código original en pseudocódigo aquí. Lo siento por eso. :) –

0

Uso setHydrationMode (Doctrine_Core :: HYDRATE_SCALAR) en su lugar.

Obtuvo resultados de forma rectangular y utiliza alias de tablas como prefijos y alias de la columna como nombre. Entonces, todos los colunm serían accesibles a través de tableAlias_columnAlias.

1

Su ejemplo no es del todo correcto: si obtiene del DQL que especificó anteriormente, solo obtendrá un objeto Usuario, no una matriz con un Usuario y un Perfil. Si desea acceder al perfil, deberá hacerlo a través de la relación establecida en su Usuario, si especificó uno en el esquema.

Sin embargo, hay una solución a su problema. En DQL, si usa alias de columna al seleccionar elementos, se podrá acceder a las columnas con alias en cada instancia que se devuelva como si fueran parte del modelo.Así que digamos que hace lo siguiente:

$query = Doctrine_Query::create() 
    ->select('u.id, u.username, p.first_name as prof_first_name, p.last_name as prof_last_name') 
    ->from('User u') 
    ->leftJoin('Profile p') 
    ->where('u.username = ?', $username); 

$result = $query->fetchOne(); 

En este caso el resultado será un solo objeto Usuario, con todas las propiedades de un usuario, además de 2 propiedades adicionales: prof_first_name y prof_last_name. Tenga en cuenta que si bien utilicé "prof_" como prefijo, no tiene ningún significado semántico, podría haber usado cualquier otra cosa también. Por lo que debe ser capaz de hacer lo siguiente:

echo "User " . $result->username ."'s first name is " . $result->prof_first_name; 
Cuestiones relacionadas