2011-02-03 78 views
6

我在Symfony 1.4中使用Doctrine 1.2。比方说,我有一个用户模型,它有一个配置文件。这些被定义为:在Doctrine的当前表中添加虚拟列?

用户:

  • ID
  • 用户名
  • 密码
  • created_at
  • 的updated_at

资料:

  • ID
  • USER_ID
  • FIRST_NAME
  • 姓氏
  • 地址
  • 城市
  • 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对象做到这一点?

回答

6

做你想做的事情的方法是使用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(); 
    } 
} 

然后注册你的连接管理器保湿:

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

您可能需要罚款hyrdator逻辑一点点地得到你想要的确切阵列结构。但这是可以接受的方式来做你想做的事情。

0

我不使用阵列水化多,所以也许我还没有注意到的,但我可以发誓您是在寻找什么是所产生的结构:

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

我对你的代码示例感到困惑......它看起来像你只是复制和粘贴了我在原始问题中写的东西,除非我错过了一些东西。 – 2011-02-03 20:36:17

+0

使用`from`而不是`createQuery`是唯一的区别...但它看起来像你在某个时候改变了... – prodigitalson 2011-02-03 21:08:40

0

使用setHydrationMode(Doctrine_Core :: HYDRATE_SCALAR)来代替。

它提取在矩形的方式的结果和使用表作为前缀和姓名栏的别名的别名。所以所有的柱子都可以通过tableAlias_columnAlias进入。

1

您的例子并不完全正确的:如果你从上面指定的DQL取,你只会得到一个用户对象,而不是与用户和个人资料的数组。如果要访问配置文件,则必须通过在用户中设置的关系来完成配置,如果您在架构中指定了一个。

不过,您的问题有一个解决方案。在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(); 

在这种情况下,结果将是一个单一的用户对象,与用户的所有属性加2个额外的属性:prof_first_name和prof_last_name。请注意,尽管我使用“prof_”作为前缀,但它没有语义含义,我也可以使用其他任何内容。所以你应该能够做到以下几点:

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