
2008-6-13 17:57
sentrychen
对Zend_Db_Table的一个扩展
我是刚学zf的水平有限,Zend_Db_Table给我感觉功能很不错,不过我还是根据自己的需要做了扩展。现在拿出来给大家参考一下。
希望大家给点意见和指出其中的错误。
主要是重写了__call方法l,增加了根据字段名直接查询的方法。另外在查询的时候会根据映射关系将全部父表的记录查出来。
比如有一个user表,dept表和company表。user表中有dept_id做为外键指向dept表。dept表中有外键company_id指向company表
如果我想查询全体男user按age排序的20条记录并从第10条开始查的时候只需要执行
$user = new User();
$rows = $user->findBySex('M','age',20,10);
然后就可以得到一个rowset,里面包含了user表的信息,dept表的信息和company表的信息。
相当于执行以下的一条sql语句。
select user.*,dept.*,company.* from user left join dept on user.dept_id = dept.id left join company on dept.company_id = company.id
where user.sex = 'M' order by age limit 20 offset 10;
同时也对row进行了扩展。比如你想获得其中一条记录中的所有dept信息时
可以这样
$row = $rows->current();
$row_dept = $row->getRowByDept(); //不会再查询数据库,Dept是映射表中的ruleKey而不是Class名,这点要注意。
如果你想直接获得dept的name信息时
可以这样
$name = $row->Dept_name;
也可以
$name = $row->getRowByDept('name');
如果你想获得Company的name时
$name = $row->Dept_Company_name;
或
$name = $row->getRowByDept()->getRowByCompany('name');
$name = $row->getRowByDept()->Company_name;
hmmm...有点注意的是,设定ruleKey的时候不要设成和数据库字段的前缀相同。
如果要进行比较复杂点的检索就用findAll()
Itc_Db_Table.php
[php]
<?php
/**
*
*
* LICENSE
*
* @category Itc
* @package Itc_Db_Table
* @subpackage Table
* @copyright Copyright (c) 2005-2008 Itc
* @license
*/
require_once 'Zend/Db/Table/Abstract.php';
require_once 'Itc/Db/Exception.php';
require_once 'Zend/Loader.php';
class Itc_Db_Table extends Zend_Db_Table_Abstract
{
const REF_TABLE = 'refTable';
protected $_rowClass = 'Itc_Db_Row';
protected $_rowsetClass = 'Itc_Db_Rowset';
public function findAll($where = null, $order = null, $count = null, $offset = null)
{
$select = $this->_db->select()
->from($this->_name);
try{
$this->_joinReferenceTable($select);
}catch (Itc_Exception $e)
{
throw new Itc_Db_Exception($e->getMessage());
}
if ($where !== null) {
$where = (array) $where;
foreach ($where as $key => $val) {
if (is_int($key)) {
$val = $this->_name . (($v = strstr($val, '.')) ? $v : '.' .$val);
$select->where($val);
} else {
$key = $this->_name . (($v = strstr($key, '.')) ? $v : '.' . $key);
$select->where($key, $val);
}
}
}
if ($order !== null) {
$order = (array) $order;
foreach ($order as $val) {
$val = $this->_name . (($v = strstr($val, '.')) ? $v : '.' .$val);
$select->order($val);
}
}
if ($count !== null || $offset !== null) {
$select->limit($count, $offset);
}
$stmt = $this->_db->query($select);
$stmt->setFetchMode(Zend_Db::FETCH_ASSOC);
$rows = $stmt->fetchAll();
$data = array(
'table' => $this,
'data' => $rows,
'readOnly' => false,
'rowClass' => $this->_rowClass,
'stored' => true
);
try {
@Zend_Loader::loadClass($this->_rowsetClass);
} catch (Zend_Exception $e) {
throw new Itc_Db_Exception($e->getMessage());
}
return new $this->_rowsetClass($data);
}
/*
*
* 魔术方法,自动生成数据表检索方法。
*
* findByColumn1AndColumn2...()
* @prama
* @return :Itc_Db_Rowset 查询结果集
* 1.根据表字段生成检索方法,多个字段用And串联。
*/
protected function __call($method, array $args)
{
//参数检查
$matches = array();
if (preg_match('/^findBy(\w+?)(?:And(\w+))*?$/', $method, $matches)) {
$columnNum = count($matches) - 1;
$argsNum = count($args);
$where = null;
$order = null;
$count = null;
$offset = null;
if ($columnNum > $argsNum){
throw new Itc_Db_Exception("Wrong parameter count for method '$method()'");
}
// $where = array();
for($i = 0; $i < $columnNum; ++$i) {
$column = $this->_getMatchColumnName($matches[$i + 1]);
$where[] = $this->_db->quoteInto($column .' = ? ', $args[$i]);
}
//order
if (isset($args[$i]))
{
$order = $args[$i];
}
//count offset
if (isset($args[$i + 2]))
{
$count = (int) $args[$i + 1];
$offset = (int) $args[$i + 2];
}
return $this->findAll($where, $order, $count, $offset);
}
throw new Itc_Db_Exception("Unrecognized method '$method()'");
}
/**
*
*/
protected function _joinReferenceTable(Zend_Db_Select $select, $alise = '')
{
foreach ($this->_getReferenceMapNormalized() as $rule => $map) {
$t = $this->getParentTable($rule);
$cond = '';
if ($alise ==''){
$curAlise = $this->_name;
$refAlise = $rule;
}
else
{
$curAlise = $alise;
$refAlise = $alise . '_' . $rule;
}
for ($i = 0; $i < count($map[self::COLUMNS]); ++$i) {
$col = $this->_db->foldCase($map[self::COLUMNS][$i]);
$refCol = $this->_db->foldCase($map[self::REF_COLUMNS][$i]);
$cond .= $curAlise . '.' . $col . ' = ' . $refAlise . '.' . $refCol;
}
$cols = $t->getAliseCols($refAlise);
$select->joinLeft($t->info('name') . ' AS ' . $refAlise, $cond, $cols);
$t->_joinReferenceTable($select, $refAlise);
}
return $select;
}
/**
*
*/
public function getAliseCols($asPrefix)
{
$asCols = array();
foreach ($this->_cols as $col)
{
$asCols[] = $col . ' AS ' . $asPrefix . '_' . $col;
}
return $asCols;
}
public function getPrefixCols($prefix)
{
$pfCols = array();
foreach ($this->_cols as $col)
{
$pfCols[] = $prefix . '_' . $col;
}
return $pfCols;
}
/**
*
*/
protected function _getMatchColumnName($name)
{
foreach ($this->_cols as $columnName)
{
if (strtolower($name) == strtolower($columnName))
return $columnName;
}
throw new Itc_Db_Exception('Specified column ' . $name . ' is not in the table ' . $this->_name);
}
/**
*
*/
public function getReferenceMap($ruleKey = null)
{
$thisClass = get_class($this);
$refMap = $this->_getReferenceMapNormalized();
if ($ruleKey !== null) {
if (!isset($refMap[$ruleKey])) {
throw new Itc_Db_Exception("No reference rule \"$ruleKey\" at table $thisClass ");
}
return $refMap[$ruleKey];
}
return $refMap;
}
/**
*
*/
public function getParentTable($ruleKey = null)
{
$parentTables = array();
$maps = $this->getReferenceMap($ruleKey);
if ($ruleKey !== null){
$maps = array($ruleKey => $maps);
}
$db = $this->getAdapter();
foreach ($maps as $key => $map)
{
if (isset($map[self::REF_TABLE]) && $map[self::REF_TABLE] instanceof Itc_Db_Table){
$parentTables[$key] = $map[self::REF_TABLE];
}
else{
$tableClass = $map[self::REF_TABLE_CLASS];
try {
@Zend_Loader::loadClass($tableClass);
} catch (Itc_Exception $e) {
throw new Itc_Db_Exception($e->getMessage());
}
$parentTables[$key] = new $tableClass(array(self::ADAPTER => $db));
$this->_referenceMap[$key][self::REF_TABLE] = $parentTables[$key];
}
}
if ($ruleKey !== null){
return $parentTables[$ruleKey];
}
else{
return $parentTables;
}
}
}
[/php]
2008-6-13 18:00
sentrychen
回复 #1 sentrychen 的帖子
Itc_Db_Row.php
[php]
<?php
/**
* Itc_Db_Row
*
* @author SentryChen
* @version 1.0
* @create at 2008-6-2 ����04:52:39
*/
require_once 'Zend/Db/Table/Row/Abstract.php';
require_once 'Itc/Db/Table.php';
require_once 'Zend/Loader.php';
class Itc_Db_Row extends Zend_Db_Table_Row_Abstract
{
/*
* 获得字段的值
*/
public function get($columnName)
{
return $this->__get($columnName);
}
/*
* 设置字段的值
*/
public function set($columnName, $value)
{
$this->__set($columnName, $value);
}
/**
*
*/
public function getByRule($ruleKey, $columnName = null)
{
if ($ruleKey === null){
return $this;
}
if ($columnName !== null){
return $this->__get($ruleKey . '_' . $columnName);
}
$parentTable = $this->_getTable()->getParentTable($ruleKey);
$prefixCols = $parentTable->getPrefixCols($ruleKey);
if (array_intersect($prefixCols, array_keys($this->_data)) == $prefixCols){
$rows = array();
foreach ($this->_data as $col => $val) {
if (strpos($col, $ruleKey . '_') === 0){
$rows[ltrim($col, $ruleKey . '_')] = $val;
}
}
$rowClass = $parentTable->getRowClass();
$data = array(
'table' => $parentTable,
'data' => $rows,
'readOnly' => $this->isReadOnly(),
'rowClass' => $rowClass,
'stored' => true
);
try{
@Zend_Loader::loadClass($rowClass);
}
catch (Exception $e){
require_once 'Itc/Db/Exception.php';
throw new Itc_Db_Exception($e->getMessage());
}
return new $rowClass($data);
}
else{
return $this->findParentRow($parentTable, $ruleKey);
}
}
protected function __call($method, array $args)
{
$matches = array();
if (preg_match('/^getRowBy(\w+?)$/', $method, $matches)) {
$ruleKey = $matches[1];
$columnName = isset($args[0])? $args[0] : null;
return $this->getByRule($ruleKey, $columnName);
}
else{
return parent::__call($method, $args);
}
}
}
[/php]
2008-6-13 18:03
sentrychen
[php]
<?php
/**
* User
*
* @desc
*
*
* @author [email]sentrychen@hotmail.com[/email]
* @version 1.0
* @copyright ITC(SHENZHEN) CO.,LTD
* created at 2008-6-6 10:00
*/
//require_once 'Itc/Db/Table.php';
class Tbl_User extends Itc_Db_Table
{
/**
* The default table name
*/
protected $_name = 'tbl_user';
protected $_dependentTables = array('Tbl_CoeTimeLimit', 'Tbl_Workflow');
protected $_referenceMap = array(
'Dept' => array(
self::COLUMNS=> 'dept_id', // 外键
self::REF_TABLE_CLASS => 'Tbl_Dept', // 外键引用的表
self::REF_COLUMNS => 'id', // 外键引用的表的主键
self::ON_UPDATE => self::CASCADE
),
'Part_time_dept' => array(
self::COLUMNS=> 'part_time_dept_id', // 外键
self::REF_TABLE_CLASS => 'Tbl_Dept', // 外键引用的表
self::REF_COLUMNS => 'id', // 外键引用的表的主键
self::ON_UPDATE => self::CASCADE
)
);
}
[/php]
2008-6-16 09:32
c61811
这才是真正的牛人啊
页:
[1]
Powered by Discuz! Archiver 5.5.0
© 2001-2006 Comsenz Inc.