$config); } if ($config) { $this->setOptions($config); } if (! is_object($this->_db)) { $this->_db = Zeed_Db::instance('default', $config); if (Zeed_Db::$metaCacheEnable) { Zend_Db_Table_Abstract::setDefaultMetadataCache(Zeed_Cache::instance()); } } if ($this->_prefix != '') { $this->_name = $this->_prefix . $this->_name; } // Global table prefix, should defined in application/APPNAME/config/database.php or config/bootstrap.php if (defined('ZEED_DB_TABLEPREFIX')) $this->_name = ZEED_DB_TABLEPREFIX . $this->_name; } /** * 切换数据库连接 * * @param string $name * @param array $config * @return Zeed_Db_Model */ public function changeAdapter($name, $config = null) { $this->_db = Zeed_Db::instance($name, $config); return $this; } /** * (non-PHPdoc) * * @see Zend_Db_Table_Abstract::insert() */ public function insert(array $data) { $this->_db->insert($this->getTable(), $data); return $this->_db->lastInsertId($this->getTable(), $this->_primary); } /** * (non-PHPdoc) * * @see Zend_Db_Table_Abstract::update() */ public function update(array $data, $where) { return $this->_db->update($this->getTable(), $data, $where); } /** * * @param string $name * @return Zeed_Db_Model */ public function setTable($name) { $this->_name = (string) $name; return $this; } /** * * @return string */ public function getTable() { return $this->_name; } /** * 内部表前缀 * * @return string */ public function getPrefix() { return $this->_prefix; } /** * Leave autocommit mode and begin a transaction. * * @return Zend_Db_Adapter_Abstract */ public function beginTransaction() { $this->_db->beginTransaction(); return true; } /** * Commit a transaction and return to autocommit mode. * * @return Zend_Db_Adapter_Abstract */ public function commit() { $this->_db->commit(); return true; } /** * Roll back a transaction and return to autocommit mode. * * @return Zend_Db_Adapter_Abstract */ public function rollBack() { $this->_db->rollBack(); return true; } /** * Prepares and executes an SQL statement with bound data. * * @param mixed $sql The SQL statement with placeholders. * May be a string or Zend_Db_Select. * @param mixed $bind An array of data to bind to the placeholders. * @return Zend_Db_Statement_Interface */ public function query($sql, $bind) { return $this->_db->query($sql, $bind); } public function query_byan($sql, $bind) { $this->_db->query($sql, $bind); return $this->_db->lastInsertId($this->getTable(), $this->_primary); } /** * 检查当前数据库中是否存在指定表 * * @param string $tablename * @return boolean */ public function isExistDB($tablename = null) { if (null === $tablename) { $tablename = $this->_name; } $sql = $this->_db->quoteInto('SHOW TABLES LIKE ?', $tablename); $row = $this->_db->query($sql)->fetchColumn(0); if ($row && $row == $tablename) { return true; } return false; } /** * 移动记录到指定表内 * 注意:最好在使用时,使用事务 * * @param string $where * @param string $sourceTable * @param string $targetTable * @return integer |false 成功移动返回影响行数,数据未找到返回 false * @throws Zeed_Exception */ public function moveRecord($where, $source, $dest = null) { $source = (string) $source; if (null === $dest) { $dest = $source . '_history'; } $selectSql = "SELECT * FROM {$source} WHERE {$where} FOR UPDATE"; $data = $this->_db->fetchAll($selectSql); if (is_array($data) && count($data)) { try { $copySql = "INSERT INTO {$dest} SELECT * FROM {$source} WHERE {$where}"; $insertAffected = $this->_db->query($copySql)->rowCount(); if (! $insertAffected) { throw new Zeed_Exception("copy record from {$source} to {$dest} failed, no affected."); } $deleteSql = "DELETE FROM {$source} WHERE {$where}"; $delectAffected = $this->_db->query($deleteSql)->rowCount(); if (! $delectAffected) { throw new Zeed_Exception("delete source $source record failed, no affected."); } return $insertAffected; } catch (Zend_Db_Exception $e) { $eMsg = $e->getMessage(); if (strpos($eMsg, '42S02') !== false || strpos($eMsg, 'Base table or view not found') !== false) { $this->copyTable($source, $dest); return $this->moveRecord($where, $source, $dest); }else { throw new Zeed_Exception($eMsg, 8); } } } return false; } /** * 同数据库拷贝表 * * @param string $source * @param string $dest * @return boolean */ public function copyTable($source, $dest) { $sourceTable = $this->_db->quoteIdentifier($source); $destTable = $this->_db->quoteIdentifier($dest); $sql = "CREATE TABLE {$destTable} LIKE {$sourceTable}"; $row = $this->_db->query($sql); if ($row) { return true; } return false; } /** * 根据MODEL中的定义PRIMARYKEY获取一行(一维)数据, 支持联合主键, 基本同parent::find()功能 * * @todo 联合主键时, 对代入的参数做进一步匹配检测 * @param integer $ |string|array $pkVal 当为联合主键时代入按主键字段顺序的数组 * @param array $ |string $cols 指定获取的字段 * @return array 二维数组 */ public function fetchByPK($pkVal, $cols = null) { if (is_null($cols)) { $cols = '*'; } if (empty($this->_primary)) { throw new Zeed_Exception('No primary key defiend.'); } if (empty($this->_name)) { throw new Zeed_Exception('Table name not defiend.'); } if (is_string($this->_primary)) { if (is_array($pkVal)) { $where = $this->_primary . ' IN (\'' . implode('\',\'', $pkVal) . '\')'; }else { $where = $this->getAdapter()->quoteInto($this->_primary . ' = ?', $pkVal); } $rows = $this->getAdapter()->select()->from($this->getTable(), $cols)->where($where)->query()->fetchAll(); }elseif (is_array($this->_primary)) { $select = $this->getAdapter()->select()->from($this->getTable(), $cols); if (is_string($pkVal) || is_int($pkVal)) { $pkVal = array(0 => $pkVal); // @see Zend_Db_Table_Abstract::_setupPrimaryKey() } foreach ($pkVal as $k => $v) { if (is_array($v) && count($v) == count($this->_primary)) { throw new Zeed_Exception('Multiple rows fetching by multi-column primary key NOT supported .'); } if (! is_null($v)) { $where = $this->getAdapter()->quoteInto($this->_primary[$k] . ' = ?', $v); $select->where($where); } } $rows = $select->query()->fetchAll(); }else { return null; } return is_array($rows) && ! empty($rows) ? $rows : null; } /** * 根据(最好有索引)字段名&值获取一行或多行数据. * * @param string $field 字段名 * @param string $ |integer|array $value 值 * @param array $ |string $cols 指定获取的字段 * @return array |null */ public function fetchByFV($field, $value, $cols = null) { if (is_null($cols)) { $cols = '*'; } $select = $this->getAdapter()->select()->from($this->getTable(), $cols); if (is_array($value)) { $rows = $select->where($field . ' IN (\'' . implode('\',\'', $value) . '\')')->query()->fetchAll(); }else { $rows = $select->where($field . ' = ?', $value)->query()->fetchAll(); } return (is_array($rows) && count($rows) > 0) ? $rows : null; } /** * 通用的自定义WHERE田间搜索 * * @param string $ |array $where * @param array $order 排序 * @param integer $count * @param integer $offset * @return array |null */ public function fetchByWhere($where = null, $order = null, $count = null, $offset = null, $cols = null) { if (is_null($cols)) { $cols = '*'; } $select = $this->getAdapter()->select()->from($this->getTable(), $cols); if (is_string($where)) { $select->where($where); }elseif (is_array($where) && count($where)) { /** * 数组, 支持两种形式. */ foreach ($where as $key => $val) { if (preg_match("/^[0-9]/", $key)) { $select->where($val); }else { $select->where($key . '= ?', $val); } } } if ($order !== null) { $select->order($order); } if ($count !== null || $offset !== null) { $select->limit($count, $offset); } $rows = $select->query()->fetchAll(); return (is_array($rows) && count($rows)) ? $rows : null; } /** * 通用的自定义WHERE田间搜索 * * @param string $ |array $where * @param array $group 分组 * @param array $order 排序 * @param integer $count * @param integer $offset * @return array |null */ public function fetchByWhereGroup($where = null,$group = null ,$order = null, $count = null, $offset = null, $cols = null) { if (is_null($cols)) { $cols = '*'; } $select = $this->getAdapter()->select()->from($this->getTable(), $cols); if (is_string($where)) { $select->where($where); }elseif (is_array($where) && count($where)) { /** * 数组, 支持两种形式. */ foreach ($where as $key => $val) { if (preg_match("/^[0-9]/", $key)) { $select->where($val); }else { $select->where($key . '= ?', $val); } } } if ($group !== null) { $select->group($group); } if ($order !== null) { $select->order($order); } if ($count !== null || $offset !== null) { $select->limit($count, $offset); } $rows = $select->query()->fetchAll(); return (is_array($rows) && count($rows)) ? $rows : null; } /** * 通用的自定义WHERE关联表搜索 * * @param string $ |array $where * @param array $order * @param integer $count * @param integer $offset * @return array null */ public function getJoinListByWhere ($table, $joinTables, $where = null, $order = null, $count = null, $offset = null, $cols = null) { if (is_null($cols)) { $cols = '*'; } if (is_array($joinTables)) { $select = $this->getAdapter()->select()->from($table, $cols); /** * 循环关联子表 */ foreach ($joinTables as $k => $v) { $select = $select->joinLeft($v['table'], $v['on']); } } if (is_string($where)) { $select->where($where); }elseif (is_array($where) && count($where)) { /** * 数组, 支持两种形式. */ foreach ($where as $key => $val) { if (preg_match("/^[0-9]/", $key)) { $select->where($val); }else { $select->where($key . '= ?', $val); } } } if ($order !== null) { $select->order($order); } if ($count !== null || $offset !== null) { $select->limit($count, $offset); } $rows = $select->query()->fetchAll(); return (is_array($rows) && count($rows)) ? $rows : array(); } /** * 根据字段名&值检测是否存在数据行 * * @param string $field 字段名 * @param string $ |mixed $value 值 * @return boolean */ public function rowExistsByFV($field, $value) { $row = $this->getAdapter()->select()->from($this->getTable(), array($field))->where($field . ' = ?', $value)->query()->fetch(); return (is_array($row) && count($row) > 0) ? true : false; } /** * 由字段的KEY-VAL数组构建WHERE条件(AND连接). * 数组格式如下: * * $rows = array('field1' = > '123', 'field2' => 'abc'); * * 该方法主要是用于兼容原Kohana中Database Query Builder的Where() * * @param array $ |string $rows * @return string */ public function batchWhere($rows) { if (is_array($rows) && count($rows) > 0) { $where = array(); foreach ($rows as $k => $v) { $where[] = $this->getAdapter()->quoteInto($k . ' = ?', $v); } return implode(' AND ', $where); }elseif (is_string($rows)) { return $rows; } return ''; } /** * 批量数据库记录插入, 不检测字段名是否相配, 谨慎使用 * * @param array $binds 二维数组 * @param string $tablename * @return integer 返回插入影响条数 */ public function batchInsert($binds, $table = null) { $cols = array(); $rows = array(); foreach ($binds as $bind) { // extract and quote col names from the array keys $cols = array(); $vals = array(); foreach ($bind as $col => $val) { $cols[] = $this->_db->quoteIdentifier($col, true); $vals[] = ($val instanceof Zend_Db_Expr) ? $val->__toString() : $this->_db->quote($val); } $rows[] = $vals; } // build the statement $insertValues = array(); foreach ($rows as $vals) { $insertValues[] = '(' . implode(', ', $vals) . ')'; } if (null === $table) { $table = $this->getTable(); } $sql = "INSERT INTO " . $this->_db->quoteIdentifier($table, true) . ' (' . implode(', ', $cols) . ') VALUES ' . implode(', ', $insertValues); return $this->_db->query($sql, array())->rowCount(); } /** * 快速获取指定MODEL的实例 * * @param string $name Model Name. * @throws Zeed_Exception * @return Zeed_Db_Model */ public static function getModel($name) { return self::_instance($name); } /** * 获取'Com_Model_'前缀的Model-Class, 即将废弃 * * @param string $name * @return Zeed_Db_Model |null */ public static function getComModel($name) { if (! is_string($name) || '' == $name) { return null; } if (strpos($name, '_') !== false) { $part = explode('_', $name); foreach ($part as $k => $v) { $part[$k] = ucfirst($v); } $name = implode('_', $part); }else { $name = ucfirst($name); } if (strpos($name, 'Com_Model_') !== 0) { $name = 'Com_Model_' . $name; } return self::getModel($name); } /** * 获取数据表记录对象的主键唯一的值 *该值是一个根据主键数字,自增的值 * @return integer */ public function getUniqueId() { return false; } /** * 获取数据表记录对象的主键最大值 * * @return integer */ public function getMaxId() { $id = 0; if (strlen($this->_primary) > 0) { $stmt = $this->_db->query(sprintf('SELECT MAX(%s) FROM `%s` WHERE 1', $this->_primary, $this->getTable())); $result = $stmt->fetchColumn(); if (is_numeric($result)) { $id = (int) $result; } } return $id; } /** * 获取数据表设计中的枚举值 * 参数:table 表名 * 参数:collum 列表 * @return 枚举值的类型 */ public function getColumType($table, $collum) { $query = "show columns from " . $table . " like '" . $collum . "'"; $stmt = $this->_db->query($query); while ($row = $stmt->fetchAll()) { $type = $row[0]['Type']; } return $type; } /** * 统计表记录条目数 * * @param string $ |array $where * @return integer */ public function getCount($where = null) { $select = $this->getAdapter()->select()->from($this->getTable(), array("count_num" => "count(*)")); if (is_string($where)) { $select->where($where); }elseif (is_array($where) && count($where)) { /** * 数组, 支持两种形式. */ foreach ($where as $key => $val) { if (preg_match("/^[0-9]/", $key)) { $select->where($val); }else { $select->where($key . '= ?', $val); } } } $row = $select->query()->fetch(); return $row ? $row["count_num"] : 0; } /** * 添加记录(根据 entity 字段映射关系过滤字段) * * @param array $set * @return integer */ public function addForEntity($set) { $entity = $this->_getEntity(); if ($entity) { if ($set instanceof $entity) { $data = $set->toArray(); }else { $entity = new $entity(); $data = $entity->fromArray($set)->toArray(); } }else { $data = $set; } return $this->insert($data); } /** * 更新记录 * * @param array $set * @param string $id * @return integer */ public function updateForEntity($set, $id) { $entity = $this->_getEntity(); if ($entity) { if ($set instanceof $entity) { $data = $set->toArray(); }else { $entity = new $entity(); $data = $entity->fromArray($set)->toArray(); } }else { $data = $set; } return $this->update($data, "{$this->_primary}='{$id}'"); } /** * 根据主键 ID 删除一条记录 * * @param integer $id * @return integer */ public function deleteByPK($id) { return $this->delete(array("{$this->_primary} = ?" => $id)); } /** * 根据(最好有索引)字段名&值删除一行或多行数据. * * @param string $field 字段名 * @param string $ |integer|array $value 值 * @return array |null */ public function deleteByFV($field, $value) { if (is_array($value)) { return $this->delete($field . ' IN (\'' . implode('\',\'', $value) . '\')'); }else { return $this->delete($field . ' = ' . $value); } } /** * 获取 entity */ private function _getEntity() { $table = $this->getTable(); $table_arr = explode('_', $table); $entity_arr = array(); foreach ($table_arr as $k => $v) { $entity_arr[] = ucfirst($v); if ($k == 0) { $entity_arr[] = 'Entity'; } } $entity = implode('_', $entity_arr); return $entity ? $entity : null; } /** * MODEL单列模式 * 在子类中(注意注释中填写正确的返回值类型, 一般为类名): * * public static function instance() * { * return parent::_instance(__CLASS__); * } * * * @param string $model * @throws Zeed_Exception * @return Zeed_Db_Model */ protected static function _instance($model) { if (isset(self::$instanceInternalCache[$model]) && is_subclass_of(self::$instanceInternalCache[$model], __CLASS__)) { return self::$instanceInternalCache[$model]; }elseif (class_exists($model)) { self::$instanceInternalCache[$model] = new $model(); return self::$instanceInternalCache[$model]; } throw new Zeed_Exception('Model( ' . $model . ' ) not exists.'); } } // End ^ LF ^ UTF-8