【问题标题】:How does one use Zend_Db_Table with custom queries?如何将 Zend_Db_Table 与自定义查询一起使用?
【发布时间】:2011-10-11 14:11:45
【问题描述】:

我需要在 Zend_Db_Table 之上使用连接来实现一些东西。 It has come to my attention that Zend_Db_Table provides no easy method of doing joins by itself。因此,我决定简单地编写查询,然后使用Zend_Db_Adapter::fetchAll 获取结果。

但是,我仍然需要以Zend_Db_Table_Rowset 的形式获取结果,以便其他需要行集的代码仍然可以正常运行。因此,我需要将我从Zend_Db_Adapter 获得的数组手动转换为Zend_Db_Table_Rowset

我该怎么做?

【问题讨论】:

  • How to use Join in Zend Framework 的可能重复项,尽管这不允许您再使用Zend_Db_Rowset。如果这不能回答您的问题,请考虑使用 ORM(如 Doctrine,Zend_Db_* 根本不擅长)
  • @Gordon:这与Zend_Db_Table_Select 抛出的错误无关。我的查询工作得很好,但我只有一个数组的结果。不过,我需要将其公开为行集。
  • 我主要链接它是为了向您展示使用 Zend_Db_Table 进行连接的简单方法。但是,是的,正如该问题中公认的答案所说:“因为 Zend_Db_Table 提供行网关功能,如果您加入其他表,这些功能将不起作用,......” - 因此我建议使用 Doctrine (ORM) 而不是 TableDataGateway 和RowDataGateway 模式。如果您进行连接,则结果不再是一行。
  • @Gordon:这与我的问题完全无关。我不能依靠像 Doctrine 这样的东西来进行一两个查询——那太疯狂了。我的问题是“我的查询工作,我如何将其公开为行集”。您的链接问题是“我一开始就无法编写查询”
  • 查看我的同名回答。总结的很好。如果这不是您要问的,请更新问题,因为显然已经有两个人没有得到您要问的内容。

标签: php zend-framework zend-db


【解决方案1】:

这不是一个文档化的特性,但是你可以用任意的数据数组来实例化一个 Rowset 对象。这就是 Zend_Db_Table 在其 find()fetchall() 方法中所做的。

<?php

// this can be the result of any Zend_Db_Statement::fetchAll()
$query_result = array(
  array('id'=>123, 'foo'=>'bar'),
  array('id'=>456, 'foo'=>'baz')
);

$rowset = new Zend_Db_Table_Rowset(
  array(
    'readonly' => true,
    'data'     => $query_result
  )
);

foreach ($rowset as $row) {
  print "id  = " . $row->id . "\n";
  print "foo = " . $row->foo . "\n";
}

请注意,这不是“实时”行集。您不能将字段和save() 更改为数据库中的基表。行集或行中没有存储关于哪些基表包含与您的 Row 对象的字段对应的列的信息。原始 SQL 查询的某些列可能是表达式或聚合,因此无论如何save() 它们都没有确定性的方法。

所以这基本上没有比使用PDO::FETCH_OBJ 获取结果集作为对象而不是哈希数组的改进。


回复:

是的,您可以像使用反序列化的 Rowset 对象一样使用 setTable()。但是 Zend_Db_Table_Row 不知道每列属于哪个表。因此它将尝试根据 Row 对象的字段生成 UPDATE 或 INSERT 查询。如果您从中创建 Row 对象的结果集包含来自多个连接表的列,则此操作将失败。

您需要确保 Row 对象仅包含来自单个表的字段,并且包含主键列,并且 Row 是从表中的单个行明确映射的。

【讨论】:

  • +1。您可以使用SetTable 将其重新附加到实时表吗?
【解决方案2】:

Zend_Db_Table 顾名思义就是抽象一个数据库表。您可以加载数据、更改数据并保存结果。但是,这意味着您仅限于您的实例正在抽象的表。

您可以通过调用 select() 来更新对象的 select 语句。然后,您可以在其他表上 join(),然后 fetchall(select) 从连接的表中获取数据。然而,由于 zend_db_table 抽象了一个表,它不允许你这样做。

您可以通过在选择上执行 setIntegrityCheck(false) 来解决此问题,这将允许您加入。但是,这意味着您只能通过此对象读取数据。写入将被禁用。

或者,您可以使用 zend_db_select 对象,它不会映射到特定的表。

【讨论】:

  • +1 因为它回答了我从书面问题中理解的内容
  • 您询问了如何在 zend_db_select 上进行连接。我告诉你怎么做。怎么不远程回答问题?
  • @Gordon:不,我现在要求将Zend_Db_Select结果 放入Zend_Db_Table_Rowset
  • 您当时可能想在您原来的问题中明确说明这一点,因为从阅读 cmets 来看,我当然不是唯一一个误解您所问内容的人。
【解决方案3】:

我以前也受此困扰。我认为除非您自己编写实现,否则您不能返回 zend_db_table_rowset。尝试查看行集摘要以了解结构如何工作。 zend_db_table_rowset 是 zend_db_table_row 对象的集合。您从 zend_db_adapter 返回的内容不兼容*。您可能需要做的是以某种方式将结果转换为 zend_db_table_rows,然后将它们添加到新的 zend_db_table_rowset 以访问这些类的所有成员。

* 这描述了可以从 Zend_Db_Adapter 返回的内容,我不认为 Zend_Db_Table/Rowset/Row 作为选项: http://framework.zend.com/manual/en/zend.db.adapter.html#zend.db.adapter.select.fetch-mode

【讨论】:

    【解决方案4】:
      $table = new Zend_Db_Table('tableName');
    
        $myRowset = $table->fetchAll();
    

    最后,Zend_Db 提供了通过 Zend_Db_Select 连接表的绝佳方式。

    【讨论】:

      猜你喜欢
      • 2011-04-25
      • 1970-01-01
      • 2019-06-08
      • 1970-01-01
      • 2017-11-09
      • 2021-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多