如何在Zend_Db_Table之上以高效的方式使用RDBMS? (如果有...)

时间:2011-02-14 21:38:50

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

当我在Zend Framework项目上工作时,我的想法正在发生这种持续的战争 - 良好的应用程序设计要求最小化数据库查询的数量。就延迟和RDBMS计算时间而言,每个查询都很昂贵。并且Zend_Db_Table鼓励您进行大量查询 - 例如,没有内置的方法可以与其他Zend_Db_Tables一起使用。并且在给定Zend_Db_Table的实例的情况下无法提取基础表的名称,这使得使用Zend_Db_Table编写Zend_Db_Select查询变得困难。从某种意义上说,Zend_Db_Table鼓励您实现RDBMS已经在PHP中提供的功能,这显然不是最理想的。

另一方面,Zend_Db_Table通过抽象SQL查询本身使表格更像本机PHP对象。用户不必担心经常引用所有这些,并且SQL操作作为简单的PHP方法公开。

什么会很好,像Zend_Db_Table,但会使用延迟操作(如Microsoft与LINQ-to-SQL / Entity Framework /等),以便将似乎多个PHP语句压缩成一个单独的(或至少更少)RDBMS查询(y | ies)。

这样的事情存在吗?它是否包含在Zend中?

3 个答案:

答案 0 :(得分:0)

有些要点需要澄清:

  1. 就像你说的那样 - Zend_Db_Table没有实现“自动加入”,另一种方式可以称为急切加载。如果您需要此类功能,请查看PHP-AR
  2. 可以自己在Zend_Db_Table中实现预先加载 - 我花了一些时间考虑它,我很确定,它可以完成。但我没有时间去做:)。
  3. 但从另一方面看 - Zend_Db_Table是您应用模型的一部分。您应该担心如何获取数据,您对数据本身感兴趣。更进一步 - 如果您使用胖模型,瘦/瘦控制器态度,您可以快速实现内部方法所需的连接,这对于大多数情况都是足够的。
    示例:http://pastebin.com/pNwideWf(我正在链接到粘贴bin,因为代码格式化在编辑器中对我不起作用)。
  4. 不幸的是,使用该方法,您将无法在连接的表中保存数据,并且必须注意列名:您不能$row->joined_table->field_from_joined_table - 而不是这样$row->joined_table_field_from_joined_table }}。

    总结 - 如果你想要性能,使用前面提到的胖模型 - 在你的案例Zend_Db_Table中存储所有在模型类中提取/过滤数据的逻辑。

答案 1 :(得分:0)

我同意你的观点,Zend_Db_Table有时会成为寻找钉子的锤子。使用连接编写自定义的高性能查询并不总是最自然的工具。在我看来,Zend_Db_Table主要适用于没有连接的单个表。但仍然可以使用Zend_Db组件的各个方面进行最佳数据库查询。

正如@singles所指出的,所有这些db访问都应该隐藏在模型中(对于ActiveRecord类型的方法)或者在mapper(对于DataMapper方法)或实体管理器(如Doctrine2)中。< / p>

例如,您的自定义BlogPost模型可以提供自定义BlogPostDataAccess的实例,该实例将被提供Zend_Db_Adapter的实例。您的所有查询(包括优化的连接)都将驻留在BlogPost_DataAccess类中。 DataAccess类中的SELECT查询可以使用像(伪代码)这样​​的东西来编写:

$select = $adapter->select()
        ->join()
        ->join()
        // etc.
        ->join()
        ->where()
        ->limit()
        ->order();

明白我的意思?

<强>更新

$tableMap成员变量怎么样?类似的东西:

public static $tableMap = array(
    'posts'        => 'table_posts',
    'users'        => 'table_users',
    'categories'   => 'table_categories',
    // etc
);

然后在您的查询中,您可以使用以下内容:

$select = $adapter->select();
$select->from(self::$tableMap['users'], array('name', 'email'));

可能添加名为setTableMap($tableMap)getTableMap()getTable($k)setTable($k)的方法,将初始映射数据存储在配置文件中,然后在引导程序期间填充静态成员。 / p>

答案 2 :(得分:0)

查看NotORM数据库层。那可能做你需要的事情;)