Zend Framework教程之Zend_Db_Table表关联实例详解


Posted in PHP onMarch 23, 2016

本文实例讲述了Zend Framework中Zend_Db_Table表关联用法。分享给大家供大家参考,具体如下:

介绍:

在RDBMS中,表之间有着各种关系,有一多对应,多多对应等等。

Zend框架提供了一些方法来方便我们实现这些关系。

定义关系:

下面是本文用的例子的关系定义:

<?php
class Accounts extends Zend_Db_Table_Abstract
{
  protected $_name      = 'accounts';
  protected $_dependentTables = array('Bugs');
}
class
class
  protected
  protected
class
  protected
}
Products extends Zend_Db_Table_Abstract
{
  protected $_name      = 'products';
  protected $_dependentTables = array('BugsProducts');
}
Bugs extends Zend_Db_Table_Abstract
{
  protected $_name      = 'bugs';$_dependentTables = array('BugsProducts');$_referenceMap  = array(
    'Reporter' => array(
      'columns'      => 'reported_by',
      'refTableClass'   => 'Accounts',
      'refColumns'    => 'account_name'
    ),
    'Engineer' => array(
      'columns'      => 'assigned_to',
      'refTableClass'   => 'Accounts',
      'refColumns'    => 'account_name'
    ),
    'Verifier' => array(
      'columns'      => array('verified_by'),
      'refTableClass'   => 'Accounts',
      'refColumns'    => array('account_name')
    )
  );
}
BugsProducts extends Zend_Db_Table_Abstract
{
  protected $_name = 'bugs_products';$_referenceMap  = array(
    'Bug' => array(
      'columns'      => array('bug_id'),
      'refTableClass'   => 'Bugs',
      'refColumns'    => array('bug_id')
    ),
    'Product' => array(
      'columns'      => array('product_id'),
      'refTableClass'   => 'Products',
      'refColumns'    => array('product_id')
    )
  );

我们看到例子中定义了四个类:Accounts,Products,Bugs,BugsProducts。其中Accounts,Products和Bugs是三个实体表,而BugsProducts是关系表。

我们再来分析一下这三个实体,一个Account有多个Bug,他们之间是一对多的关系,而Bug和Product是多对多的关系。

$_dependentTables是一个与该对象关联的对象名,这里注意,要写对象名而不是关联的数据库名。

$_referenceMap数组用来定义和其他表的关系,在这里可以设置和那些表有关系,有什么样的关系。第一个设置的是Rule Key,也就是上面例子的'Reporter', 'Engineer'之类的。Rule Key的作用其实就是一个关系的名字,并不需要和其他数据库表名或者其他对象名的名字一样。只是为了标记的,在后面的时候,我们可以看到这个Rule Key的作用。

每一个Rule下面都有如下的一些定义:(没有特殊说明,都以如上'Reporter'关系进行说明)

columns=> 设置和别的表关联的字段名,如上的'report_by'就是数据库中表Bugs的report_by字段。这里只有一个字段,也可以设置多个字段。

refTableClass=>用于设置与这个表发生关系的表。这里要注意,一定使用目标表的对象的名字而不是表名字,例子中就和'Account'对象发生了关联。

refColumns =>设置发生联系的表的字段。可以写多个,如果和多个字段发生联系的话,这里要和columns对应。这个设置其实是可选的,如果为空,关联字段自动被设置成为关联表的主键。上面例子中并没有使用主键作为关联字段,所以手动设置。

onDelete=>可选字段,设置当删除是的动作。
onUpdate=>可选字段,设置当更新表时的动作。

以上定义关系。

从关联表中取数据:

如果我们已经得到了一个查询结果,我们可以通过一下语句去取得这个结果相关联的表的查询结果:

$row->findDependentRowset($table, [$rule]);

这个方法一般使用与一多对应的两个实体表中,在多多对应的两个实体表和一个关系表如何从一个实体表取出另一个实体表的数据,我们会在下面叙述。

第一个字段$table是指和这个表想相联系的表对应的类名。第二个字段是可选的,是我们刚刚说到的rule key,就是这个关系的名字,如果省略,则默认为这个表中的第一个关系。下面是例子:

<?php
$accountsTable   = new Accounts();
$accountsRowset   = $accountsTable->find(1234);
$user1234      = $accountsRowset->current();
$bugsReportedByUser = $user1234->findDependentRowset('Bugs');

例子中,我们先读取了一个编号为1234的用户,然后去查找这个家伙报了什么bug,由于zend默认是第一个关联,所以这里和Account发生关联的第一个就是'Reporter,所以就取出了Reporter的记录。

如果我们想取出其他的记录,比如Engineer,可以按照下面的办法:

<?php
$accountsTable   = new Accounts();
$accountsRowset   = $accountsTable->find(1234);
$user1234      = $accountsRowset->current();
$bugsAssignedToUser = $user1234->findDependentRowset('Bugs', 'Engineer');

除了使用findDependentRowset之外,我们还可以使用叫做“魔术方法”(Magic Method)的机制。之所以这么叫,就是因为好像是在变魔术一样。所以方法findDependentRowset('<TableClass>', '<Rule>')就可以等价于如下:

- $row->find<TableClass>()
- $row->find<TableClass>By<Rule>()

注:这个机制是我们最一开始是在Ruby on Rails里面看到的。这里的<TableClass>和<Rule>一定要使用和相关联的类名以及关联名(Rule Key)完全一样的名字,才可以生效。下面是例子:

<?php
$accountsTable  = new Accounts();
$accountsRowset  = $accountsTable->find(1234);
$user1234     = $accountsRowset->current();
// Use the default reference rule
$bugsReportedBy  = $user1234->findBugs();// Specify the reference rule
$bugsAssignedTo  = $user1234->findBugsByEngineer();
<?php
$bugsTable     = new Bugs();
$bugsRowset    = $bugsTable->fetchAll('bug_status = ?', 'NEW');
$bug1       = $bugsRowset->current();
// Use the default reference rule
$reporter     = $bug1->findParentAccounts();// Specify the reference rule
$engineer     = $bug1->findParentAccountsByEngineer();

从父表取得字段:

刚刚我们介绍了一多关系中的从一去多的方法,现在我们反过来,从多取一,其实是从多中的一个取他相对应的那个记录。

类似的我们有这样的语句:

$row->findParentRow($table, [$rule]);

类似的,$table为类名,而可选参数$rule填入对应的Rule Key。下面是例子:

<?php
$bugsTable     = new Bugs();
$bugsRowset    = $bugsTable->fetchAll(array('bug_status = ?' => 'NEW'));
$bug1       = $bugsRowset->current();
$reporter     = $bug1->findParentRow('Accounts');

和上面不太一样的是,上面返回的是一个多个记录的集合,而这次返回的必然是一条记录。下面的例子是设置Rule:

<?php
$bugsTable     = new Bugs();
$bugsRowset    = $bugsTable->fetchAll('bug_status = ?', 'NEW');
$bug1       = $bugsRowset->current();
$engineer     = $bug1->findParentRow('Accounts', 'Engineer');

只需要吧Rule填入就好了。相似的,这个方法也有“魔术字段”。findParentRow('<TableClass>', '<Rule>')对应:

- $row->findParent<TableClass>()
- $row->findParent<TableClass>By<Rule>()

例子:

取得多对多关系表的字段:

上面两个方法讲述了一对多的使用,下面就是多对多了。我们使用如下方法取得多对多关系表的数据:

$row->findManyToManyRowset($table, $intersectionTable, [$rule1, [$rule2]]);

这里参数变成了4个,因为需要增加一个关系表来存储多对多的关系。

$table是与之发生多对多关系的表的类名,$intersectionTable是中间存储关系的关系表的类名。$rule1和$rule2是上面两个数据表的Rule Key。省略Rule Key的例子如下:

<?php
$bugsTable    = new Bugs();
$bugsRowset    = $bugsTable->find(1234);
$bug1234     = $bugsRowset->current();
$productsRowset  = $bug1234->findManyToManyRowset('Products', 'BugsProducts');

下面是该方法的全部参数调用例子:

<?php
$bugsTable    = new Bugs();
$bugsRowset    = $bugsTable->find(1234);
$bug1234     = $bugsRowset->current();
$productsRowset  = $bug1234->findManyToManyRowset('Products', 'BugsProducts', 'Bug');

这次的“魔术方法”是,对应 findManyToManyRowset('<TableClass>', '<IntersectionTableClass>', '<Rule1>', '<Rule2>')
- $row->find<TableClass>Via<IntersectionTableClass>()
- $row->find<TableClass>Via<IntersectionTableClass>By<Rule1>()
- $row->find<TableClass>Via<IntersectionTableClass>By<Rule1>And<Rule2>()

例子:

<?php
$bugsTable    = new Bugs();
$bugsRowset    = $bugsTable->find(1234);
$bug1234     = $bugsRowset->current();
// Use the default reference rule
$products     = $bug1234->findProductsViaBugsProducts();// Specify the reference rule
$products     = $bug1234->findProductsViaBugsProductsByBug();

希望本文所述对大家基于Zend Framework框架的PHP程序设计有所帮助。

PHP 相关文章推荐
PHP 程序员也要学会使用“异常”
Jun 16 PHP
PHP 函数学习简单小结
Jul 08 PHP
Windows 下的 PHP-PEAR 安装方法
Nov 20 PHP
PHP实现手机归属地查询API接口实现代码
Aug 27 PHP
php中导出数据到excel时数字变为科学计数的解决方法
Feb 03 PHP
基于PHP文件操作的详细诠释
Jun 21 PHP
PHP curl实现抓取302跳转后页面的示例
Jul 04 PHP
php和editplus正则表达式去除空白行
Apr 17 PHP
PHP读取汉字的点阵数据
Jun 22 PHP
php生成固定长度纯数字编码的方法
Jul 09 PHP
php脚本守护进程原理与实现方法详解
Jul 20 PHP
PHP7变量处理机制修改
Mar 09 PHP
SSO单点登录的PHP实现方法(Laravel框架)
Mar 23 #PHP
Zend Framework开发入门经典教程
Mar 23 #PHP
php resizeimage 部分jpg文件 生成缩略图失败的原因分析及解决办法
Mar 23 #PHP
Zend Framework教程之Zend_Config_Ini用法分析
Mar 23 #PHP
PHP正则获取页面所有图片地址
Mar 23 #PHP
Zend Framework教程之Zend_Config_Xml用法分析
Mar 23 #PHP
php获取文件后缀的9种方法
Mar 22 #PHP
You might like
php中静态类与静态变量用法的区别分析
2015/01/15 PHP
php实现俄罗斯乘法实例
2015/03/07 PHP
php中define用法实例
2015/07/30 PHP
深入解析Laravel5.5中的包自动发现Package Auto Discovery
2017/09/13 PHP
PHP单元测试配置与使用方法详解
2019/12/27 PHP
用一段js程序来实现动画功能
2007/03/06 Javascript
ext checkboxgroup 回填数据解决
2009/08/21 Javascript
学习ExtJS TextField常用方法
2009/10/07 Javascript
js定义对象或数组直接量时各浏览器对多余逗号的处理(json)
2011/03/05 Javascript
JavaScript高级程序设计 阅读笔记(二十一) JavaScript中的XML
2012/09/14 Javascript
终于解决了IE8不支持数组的indexOf方法
2013/04/03 Javascript
form表单只提交数据而不进行页面跳转的解决方案
2013/09/18 Javascript
JavaScript实现同步于本地时间的动态时间显示方法
2015/02/02 Javascript
使用纯javascript实现放大镜效果
2015/03/18 Javascript
Bootstrap编写一个兼容主流浏览器的受众巨幕式风格页面
2016/07/01 Javascript
Bootstrap CSS组件之按钮下拉菜单
2016/12/17 Javascript
详解如何将 Vue-cli 改造成支持多页面的 history 模式
2017/11/20 Javascript
js读取本地文件的实例
2017/12/22 Javascript
微信小程序框架wepy之动态控制类名
2018/09/14 Javascript
通过vue.extend实现消息提示弹框的方法记录
2021/01/07 Vue.js
[03:40]DOTA2英雄梦之声_第01期_炼金术士
2014/06/23 DOTA
[01:12]快闪回顾DOTA2亚洲邀请赛(DAC) 静候2018新征程开启
2018/03/11 DOTA
python 快速排序代码
2009/11/23 Python
python冒泡排序算法的实现代码
2013/11/21 Python
Python version 2.7 required, which was not found in the registry
2014/08/26 Python
CentOS下使用yum安装python-pip失败的完美解决方法
2017/08/16 Python
使用numpy和PIL进行简单的图像处理方法
2018/07/02 Python
Python bisect模块原理及常见实例
2020/06/17 Python
Python wordcloud库安装方法总结
2020/12/31 Python
html5中valid、invalid、required的定义
2014/02/21 HTML / CSS
德国高端单身人士交友网站:ElitePartner
2018/12/02 全球购物
初三班主任寄语大全
2014/04/04 职场文书
廉洁校园实施方案
2014/05/25 职场文书
反四风个人对照检查材料
2014/09/26 职场文书
2015学生会文艺部工作总结
2015/04/03 职场文书
Java日常练习题,每天进步一点点(38)
2021/07/26 Java/Android