【问题标题】:Zend Framework relationships - defining column names in findManyToManyRowset()?Zend 框架关系 - 在 findManyToManyRowset() 中定义列名?
【发布时间】:2009-09-17 12:56:29
【问题描述】:

我正在开发一个使用 Zend Framework 开发的应用程序。我已经在模型中定义了关系,并且可以愉快地使用它们,例如:

$rowset = $row->findManyToManyRowset('People', 'Jobs');

但是,我遇到了一个问题,即返回的行集在“人员”和“工作”中具有相同的列名,因此合并了数组键,从而丢失了最终行集中的一些数据。

我知道我可以将Zend_Db_Select 对象作为参数之一传递给findManyToManyRowset(),但找不到任何说明在这种情况下如何使用它的文档,例如:

$select = $this->select()->from(array(
                                     'p' => 'people', 
                                     'j' => 'jobs'
                                     ),
                                array( 
                                     'person_id' => 'p.id',
                                     'job_id' => 'j.id',
                                     'person_code' => 'p.code',
                                     'job_code' => 'j.code'
                                     )
                                );  

如果我尝试使用上面的代码,我会收到一条消息,例如:

Error: No reference rule "" from table People to table Jobs

谁能告诉我这应该怎么做?我知道我可以更改数据库中的列名,但我更喜欢更改代码,而不是重新设计我的数据库结构并更新所有相关代码。

注意:如果没有上述某种形式的列别名,返回的行集看起来像这样(即,它合并了具有相同名称的列):

[_data:protected] => Array
    (
        [id] => 1
        [code] => SX342
    )

干杯,
马特

【问题讨论】:

    标签: zend-framework zend-db zend-db-table relationships


    【解决方案1】:

    我知道这个答案来得有点晚,但这里有一些事情需要指出。

    1) findManyToManyRowset($matchTable, $intersectionTable, $callerRefRule, $matchRefRule, $select); -- 如果您传递的是 Zend_Db_Table_Select,那么您将希望传递 null 以获取规则。

    2) 传递给findManyToManyRowset()Zend_Db_Table_Select 应该从$matchTable 创建,并且可以安全地假设在where 子句中i 是交集表的别名,m 是匹配表的别名。

    3) 在发生冲突的情况下,m 将赢得 php 中返回的关联数组中的键名。执行的查询如下所示:

      SELECT 
        `i`.*, `m`.* 
      FROM 
        `interscetTable` AS `i` 
      INNER JOIN 
        `matchTable` AS `m` 
      ON
        `i`.`fk_m` = `m`.`pk` WHERE (`i`.`fk_o` = ?)  
    

    4) 不管怎样,findManyToManyRowset() 的返回值将是一个从$matchTable 创建的 Rowset,因此,如果您需要从相交表中捕获任何信息,同时还要为匹配表捕获数据,您可能需要自定义 Zend_Db_Select 并避免使用 Zend_Db_Table 东西来映射数据。

    所以一个工作示例,使用“人”作为匹配表,“工人”作为交集表,让我们说“客户”作为原始表。在这个例子中,假设表链接在一起,如下所示: People.id:... -> 工人.person_id:client_id:job_id -> 客户:id:...

    $client = $clientTable->fetchRow(); /// grab a random client
    
    // fetch all people that have worked for the client ordered by their last name.
    $client->findManyToManyRowset("People", "Workers", null, null, 
      $peopleTable->select()->order('m.lastname')); 
    
    // fetch all people that have worked for the client ordered by their hire date:
    // `workers`.`hiredate`
    $client->findManyToManyRowset("People", "Workers", null, null, 
      $peopleTable->select()->order('i.hiredate')); 
    

    【讨论】:

      【解决方案2】:

      我的第一个建议是,您不应将列命名为像 idcode 这样的通用名称。这些名称没有意义,而且正如您所发现的,当您在关联数组中获取结果时,它们也会导致冲突。

      您还错误地使用了“选择”界面。每个from() 调用或join() 调用应该只指定一个表。

      最后,我从不尝试通过Zend_Db_Table 关系接口进行复杂的查询。它仅适用于简单的情况。如果您有更复杂的查询,只需显式编写 SQL 查询即可。

      另见How to do a joined query in the ZF tables interface?

      【讨论】:

      • 感谢比尔的回复。对于如何命名列,或者在更广泛的范围内,关于数据库设计最佳实践的优秀教程,您有什么建议吗?
      • 例如,您可以在两个表中使用“person_id”,而不是在一个表中使用“person_id”,在另一个表中使用“id”。在可能的情况下,使具有相同内容的列在表中具有相同的名称。同样是“person_code”而不是简单的“code”。基本上,使表中的列名不同,至少当它们是可能在查询中连接在一起的表时。
      • 阅读“Joe Celko 为 Smarties 编写的 SQL 编程风格”的第一章。 Google 图书在其在线预览中包含第一章:books.google.com/books?id=a9jtyioHfp8C
      • person.id 不是没有意义的,恕我直言
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多