Добавление виртуальных столбцов в текущую таблицу в Doctrine? - PullRequest
7 голосов
/ 03 февраля 2011

Я использую Doctrine 1.2 с Symfony 1.4.Допустим, у меня есть модель пользователя, которая имеет один профиль.Они определены как:

Пользователь:

  • id
  • имя пользователя
  • пароль
  • созданный_ат
  • updated_at

Профиль:

  • id
  • user_id
  • first_name
  • last_name
  • address
  • city
  • postal_code

Обычно я получаю данные, подобные этим:

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

Это выдает что-то вроде следующего:

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

Однако я бы хотел, чтобы пользователь включил «виртуальные» столбцы (не уверен, что это правильный термин), чтобы поля из профиля действительно выглядели как часть пользователя.Другими словами, я бы хотел бы , чтобы оператор print_r выглядел больше как:

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

Есть ли способ сделать это либо через мой файл schema.yml, либо через мой Doctrine_Queryобъект

Ответы [ 4 ]

6 голосов
/ 16 февраля 2011

Способ сделать то, что вы хотите, это использовать пользовательский Гидратор .

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

Затем зарегистрируйте свой гидратор в диспетчере соединений:

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

Затем вы выполняете запрос следующим образом:

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

Возможно, вам придется немного улучшить логику гирдатора, чтобы получить точную структуру массива, которую вы хотите. Но это приемлемый способ делать то, что вы хотите.

1 голос
/ 16 февраля 2011

Ваш пример не совсем корректен: если вы извлекаете данные из DQL, который вы указали выше, вы получите только объект User, а не массив с пользователем и профилем. Если вы хотите получить доступ к профилю, вам придется сделать это с помощью отношений, установленных в вашем пользователе, если вы указали их в схеме.

Тем не менее, есть решение вашей проблемы. В DQL, если вы используете псевдонимы столбцов при выборе объектов, столбцы с псевдонимами будут доступны в каждом возвращаемом экземпляре, как если бы они были частью модели. Допустим, вы делаете следующее:

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

В этом случае результатом будет один объект User со всеми свойствами пользователя плюс 2 дополнительных свойства: prof_first_name и prof_last_name. Обратите внимание, что хотя я использовал «prof_» в качестве префикса, он не имеет семантического значения, я мог бы использовать и что-нибудь еще. Таким образом, вы должны быть в состоянии сделать следующее:

echo "User " . $result->username ."'s first name is " . $result->prof_first_name;
0 голосов
/ 15 февраля 2011

Вместо этого используйте setHydrationMode (Doctrine_Core :: HYDRATE_SCALAR).

Он выбирает результаты в прямоугольной форме и использует псевдонимы таблиц в качестве префиксов и псевдонимы столбцов в качестве имени.Таким образом, все столбцы будут доступны через tableAlias_columnAlias.

0 голосов
/ 03 февраля 2011

Я не использую увлажнение массива, поэтому, может быть, я не заметил, но я мог бы поклясться, что структура, которую вы ищете, это то, что производится:

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