【问题标题】:Adding virtual columns to current table in Doctrine?在 Doctrine 中向当前表添加虚拟列?
【发布时间】:2011-02-03 19:50:03
【问题描述】:

我将 Doctrine 1.2 与 Symfony 1.4 一起使用。假设我有一个 User 模型,它有一个 Profile。这些定义为:

用户:

  • 身份证
  • 用户名
  • 密码
  • created_at
  • updated_at

简介:

  • 身份证
  • user_id
  • 名字
  • 姓氏
  • 地址
  • 城市
  • 邮政编码

我通常会得到这样的数据:

$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 对象来做到这一点?

【问题讨论】:

    标签: join symfony1 doctrine calculated-columns doctrine-1.2


    【解决方案1】:

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

    然后向连接管理器注册您的 hydrator:

    $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 逻辑进行一些微调才能获得所需的确切数组结构。但这是可以接受的方式来做你想做的事。

    【讨论】:

    • 现在我知道我在寻找什么,这里有一个有用的链接,对于那些在 Symfony 中做类似事情的人(就像我一样):symfony-project.org/more-with-symfony/1_4/en/…
    • 最后一个小提示:我需要我的保湿器来扩展Doctrine_Hydrator_ArrayDriver,而不是Doctrine_Hydrator_ArrayHierarchyDriver
    • 有没有办法让它在学说 2 中扩展 ObjectHyrdator 而不会失去很多默认行为?请参阅stackoverflow.com/questions/24364352/… 了解更多信息。
    【解决方案2】:

    您的示例并不完全正确:如果您从上面指定的 DQL 中获取,您将只会获得一个 User 对象,而不是包含 User 和 Profile 的数组。如果您想访问配置文件,则必须通过在您的用户中设置的关系来完成,如果您在架构中指定了一个。

    尽管如此,您的问题还是有解决方案的。在 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;
    

    【讨论】:

      【解决方案3】:

      我不经常使用阵列水合,所以也许我没有注意到,但我可以发誓你正在寻找的结构是由以下人员生产的:

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

      【讨论】:

      • 我对您的代码示例感到困惑...看起来您只是复制并粘贴了我在原始问题中写的内容,除非我遗漏了什么。
      • 使用 from 而不是 createQuery 是唯一的区别......但看起来你在某个时候改变了它......
      • 是的,我可能在您回答的同时对其进行了编辑... createQuery 是在这里将我的原始代码复制为伪代码的错误。对于那个很抱歉。 :)
      【解决方案4】:

      改用 setHydrationMode(Doctrine_Core::HYDRATE_SCALAR)。

      它以矩形方式获取结果,并使用表的别名作为前缀和列的别名作为名称。所以所有的列都可以通过 tableAlias_columnAlias 访问。

      【讨论】:

        猜你喜欢
        • 2015-04-14
        • 2015-08-31
        • 1970-01-01
        • 2011-08-05
        • 2011-05-08
        • 1970-01-01
        • 2018-12-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多