DAO类autoCheck()函数,非必填项未填写时仍检测
2017-06-29 11:09:48
杨桢
  • 访问次数: 59
  • 注册日期: 2017-06-29
  • 最后登录: 2017-11-09
  • 我的积分: 2580
  • 门派等级: 释迦 等级3 比丘

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 );
        }
    }
}

100 杨桢 最后编辑, 2017-06-29 11:19:04
沙发
2017-06-29 11:20:31
王春生
  • 访问次数: 938
  • 注册日期: 2014-05-02
  • 最后登录: 2023-09-12
  • 我的积分: 1310
  • 门派等级: 无门派
谢谢反馈。奖励100积分。:)
1/1