DAO类autoCheck()函数虽然提供了$skipFields字段,用来手动取消某些字段的验证。但无法做到智能判断某个非必填项字段在不填写时不用检测,填写信息时正常检测。根据系统设计思路(通过lib\dao\dao.class.php继承基础类baseDAO),在lib\dao\dao.class.php重写了部分函数。已修复此bug。代码如下:
<?php
/**
* ZenTaoPHP的dao和sql类。
* The dao and sql class file of ZenTaoPHP framework.
*
* The author disclaims copyright to this source code. In place of
* a legal notice, here is a blessing:
*
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
*/
helper::import ( dirname ( dirname ( __FILE__ ) ) . '/base/dao/dao.class.php' );
/**
* DAO类。
* DAO, data access object.
*
* @package framework
*/
class dao extends baseDAO {
/**
* 根据数据库结构检查字段。
* Check the fields according the the database schema.
*
* @param string $skipFields
* fields to skip checking
* @access public
* @return object the dao object self.
*/
public function autoCheck($skipFields = '') {
$fields = $this->getFieldsType ();
$skipFields = ",$skipFields,";
foreach ( $fields as $fieldName => $validater ) {
if (strpos ( $skipFields, $fieldName ) !== false)
continue; // skip it.
if (! isset ( $this->sqlobj->data->$fieldName ))
continue;
if ($validater ['rule'] == 'skip')
continue;
$options = array ();
if (isset ( $validater ['options'] ))
$options = array_values ( $validater ['options'] );
for($i = 0; $i < VALIDATER::MAX_ARGS; $i ++) {
${"arg$i"} = isset ( $options [$i] ) ? $options [$i] : null;
}
$this->check ( [
'name' => $fieldName,
'null' => $validater ['null']
], $validater ['rule'], $arg0, $arg1, $arg2 );
}
return $this;
}
/**
* 获取表的字段类型。
* Get the defination of fields of the table.
*
* @access public
* @return array
*/
public function getFieldsType() {
try {
$this->dbh->setAttribute ( PDO::ATTR_CASE, PDO::CASE_LOWER );
$sql = "DESC $this->table";
$rawFields = $this->dbh->query ( $sql )->fetchAll ();
$this->dbh->setAttribute ( PDO::ATTR_CASE, PDO::CASE_NATURAL );
} catch ( PDOException $e ) {
$this->sqlError ( $e );
}
foreach ( $rawFields as $rawField ) {
$firstPOS = strpos ( $rawField->type, '(' );
$type = substr ( $rawField->type, 0, $firstPOS > 0 ? $firstPOS : strlen ( $rawField->type ) );
$type = str_replace ( array (
'big',
'small',
'medium',
'tiny',
'var'
), '', $type );
$field = array ();
if ($type == 'enum' or $type == 'set') {
$rangeBegin = $firstPOS + 2; // 移除开始的引用符 Remove the first quote.
$rangeEnd = strrpos ( $rawField->type, ')' ) - 1; // 移除结束的引用符 Remove the last quote.
$range = substr ( $rawField->type, $rangeBegin, $rangeEnd - $rangeBegin );
$field ['rule'] = 'reg';
$field ['options'] ['reg'] = '/' . str_replace ( "','", '|', $range ) . '/';
} elseif ($type == 'char') {
$begin = $firstPOS + 1;
$end = strpos ( $rawField->type, ')', $begin );
$length = substr ( $rawField->type, $begin, $end - $begin );
$field ['rule'] = 'length';
$field ['options'] ['max'] = $length;
$field ['options'] ['min'] = 0;
} elseif ($type == 'int') {
$field ['rule'] = 'int';
} elseif ($type == 'float' or $type == 'double') {
$field ['rule'] = 'float';
} elseif ($type == 'date') {
$field ['rule'] = 'date';
} else {
$field ['rule'] = 'skip';
}
// 是否可以为空
$field ['null'] = $rawField->null;
$fields [$rawField->field] = $field;
}
return $fields;
}
/**
* 检查字段是否满足条件。
* Check a filed is satisfied with the check rule.
*
* @param string $fieldName
* the field to check
* @param string $funcName
* the check rule
* @param string $condition
* the condition
* @access public
* @return object the dao object self.
*/
public function check($fieldName, $funcName, $condition = '') {
if (is_array ( $fieldName ) && $fieldName ['name']) {
$fieldNull = $fieldName ['null'];
$fieldName = $fieldName ['name'];
}
/*
* 如果没数据中没有该字段直接返回。
* If no this field in the data, return.
*/
if (! isset ( $this->sqlobj->data->$fieldName ))
return $this;
/* 设置字段值。 */
/* Set the field label and value. */
global $lang, $config, $app;
if (isset ( $config->db->prefix )) {
$table = strtolower ( str_replace ( array (
$config->db->prefix,
'`'
), '', $this->table ) );
} elseif (strpos ( $this->table, '_' ) !== false) {
$table = strtolower ( substr ( $this->table, strpos ( $this->table, '_' ) + 1 ) );
$table = str_replace ( '`', '', $table );
} else {
$table = strtolower ( $this->table );
}
$fieldLabel = isset ( $lang->$table->$fieldName ) ? $lang->$table->$fieldName : $fieldName;
$value = isset ( $this->sqlobj->data->$fieldName ) ? $this->sqlobj->data->$fieldName : null;
// 跳过未填写的非必填项检查
if (empty ( $value ) && strtoupper ( $fieldNull ) == 'YES')
return $this;
/*
* 检查唯一性。
* Check unique.
*/
if ($funcName == 'unique') {
$args = func_get_args ();
$sql = "SELECT COUNT(*) AS count FROM $this->table WHERE `$fieldName` = " . $this->sqlobj->quote ( $value );
if ($condition)
$sql .= ' AND ' . $condition;
try {
$row = $this->dbh->query ( $sql )->fetch ();
if ($row->count != 0)
$this->logError ( $funcName, $fieldName, $fieldLabel, array (
$value
) );
} catch ( PDOException $e ) {
$this->sqlError ( $e );
}
} else {
/*
* 创建参数。
* Create the params.
*/
$funcArgs = func_get_args ();
unset ( $funcArgs [0] );
unset ( $funcArgs [1] );
for($i = 0; $i < VALIDATER::MAX_ARGS; $i ++) {
${"arg$i"} = isset ( $funcArgs [$i + 2] ) ? $funcArgs [$i + 2] : null;
}
$checkFunc = 'check' . $funcName;
if (validater::$checkFunc ( $value, $arg0, $arg1, $arg2 ) === false) {
$this->logError ( $funcName, $fieldName, $fieldLabel, $funcArgs );
}
}
return $this;
}
}
/**
* SQL类。
* The SQL class.
*
* @package framework
*/
class sql extends baseSQL {
/**
* 创建ORDER BY部分。
* Create the order by part.
*
* @param string $order
* @access public
* @return object the sql object.
*/
public function orderBy($order) {
if (strpos ( $order, 'convert(' ) !== false) {
if ($this->inCondition and ! $this->conditionIsTrue)
return $this;
$order = str_replace ( array (
'|',
'',
'_'
), ' ', $order );
$this->sql .= ' ' . DAO::ORDERBY . " $order";
return $this;
} else {
return parent::orderBy ( $order );
}
}
}
回贴