query inner getrepository findbyid join symfony1 doctrine calculated-columns doctrine-1.2

join - inner - ¿Agregar columnas virtuales a la tabla actual en Doctrine?



findbyid doctrine (4)

No uso la hidratación de la matriz mucho, así que tal vez no me he dado cuenta, pero podría haber jurado que la estructura que estás buscando es la que produce:

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

Estoy usando Doctrine 1.2 con Symfony 1.4. Digamos que tengo un modelo de usuario, que tiene un perfil. Estos se definen como:

Usuario:

  • carné de identidad
  • usuario
  • contraseña
  • Creado en
  • updated_at

Perfil:

  • carné de identidad
  • identidad de usuario
  • nombre de pila
  • apellido
  • dirección
  • ciudad
  • código postal

Normalmente obtendría datos como este:

$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);

Esto generaría algo como lo siguiente:

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

Sin embargo, me gustaría que el usuario incluyera columnas "virtuales" (no estoy seguro de si este es el término correcto), de modo que los campos del perfil se vean como parte del usuario. En otras palabras, me gustaría ver que la declaración print_r se parezca más a:

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

¿Hay alguna manera de hacerlo a través de mi archivo schema.yml o a través de mi objeto Doctrine_Query?


La forma de hacer lo que desea es usar un Hidrador personalizado .

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

Luego registre su hidratador con el administrador de conexión:

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

Luego hidratas tu consulta así:

$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" ) )

Es posible que tenga que multar un poco la lógica del hyrdator para obtener la estructura de matriz exacta que desee. Pero esta es la forma aceptable de hacer lo que quieras.


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. Entonces digamos que haces 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 único objeto de usuario, con todas las propiedades de un usuario más 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. Entonces, debería poder hacer lo siguiente:

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


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

Obtuvo resultados de manera rectangular y usa 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.