$options = array(
'tb1'=>'id,name',
'tb2'=>'age, name AS newname'
);转成:tb1.id,tb1.name,tb2.age,tb2.name AS newname 查询字段为此,我自己在CommonModel封装了一下field方法
/**
* 转换成带有表名的字段
* $options 表名对应字段字符串
* 示例:
* $options = array('tb1'=>'id,name,age', 'tb2'=>'id2,name2 AS newname, age2');
*/
public function field($options, $except=false){
if(is_string($options)) return parent::field($field,$except);
$field = '';
foreach($options as $table => $value){
$value = ',' . preg_replace(array('/\s\s+/', '/\s*,\s*/', '/\s(AS|as)\s/'), array(' ', ',', ' '), $value);
$value = preg_replace(array('/\s/', '/,/'), array('` `', "`,`$table`.`"), $value);
$field .= '`'.ltrim($value, '`,').'`,';
}
return parent::field(rtrim($field, ','), $except);
}二、D函数的优化,D函数能传入两个参数,一个模型名,一个模型层名称,模型名,同时也决定了表名。但是,有时候我们没必要写许多模型文件,因为有时候是比较零散的模型方法,我们更愿意把它们集中到一个文件中去。但是,D方法限定了一个模型指向一个表名。为此,我也改写了一个D函数/**
* 实例化模型类 格式 [资源://][模块/]模型[.模型层名称]
* @param string $name 资源地址
* @return Think\Model
*/
function model($name, $table='', $prefix='', $connection=''){
list($name, $layer) = explode('.', $name);//例如: home://index/Help.Model
if(empty($table)) $table = basename($name);
static $_model = array();
$layer = $layer? : C('DEFAULT_M_LAYER');
if(isset($_model[$name.$layer]))
return $_model[$name.$layer];
$class = parse_res_name($name,$layer);
if(class_exists($class)) {
$model = new $class($table, $prefix, $connection);
}elseif(false === strpos($name,'/')){
// 自动加载公共模块下面的模型
if(!C('APP_USE_NAMESPACE')){
import('Common/'.$layer.'/'.$class);
}else{
$class = '\\Common\\'.$layer.'\\'.$name.$layer;
}
$model = class_exists($class)? new $class($table, $prefix, $connection) : new Think\Model($table, $prefix, $connection);
}
$_model[$name.$layer] = $model;
return $model;
}三、join方法自动加表前缀的格式是表名大写并且两边带双底杠如:__TABLE__,我是觉得这种方式有点怪异,就像模板里调用函数时 {$time|date="y-m-d",###}一样,我觉得很怪,什么###代表当前变量,明明可以写{:date('y-m-d', $time)}的标准形式,join方法建议可以传三个参数join($join,$type='INNER', $tablePrefix='') 如果type不在合法的类型之中,则认定为表前缀,表前缀为空时,取配置参数,为null时,表示无.四、访问的方法不存在时,就查找相应的模板文件,并实例化显示,我觉得这种特性不是我们想要的,有未知的安全隐患,我们要自己决定哪些模板可以直接显示。为此,我们可以直接在总控制器里定义一个 _empty()方法:
protected function _empty($method,$args){
$static = array('aboutus','nationwide', 'fzlc', 'store', 'contact', 'hzhb', 'job', 'shzr');
if(in_array($method, $static)){
$this->display();
}else{
E(L('_ERROR_ACTION_').':'.ACTION_NAME);
}
}五、数据分页时,首先要得到总记录数,然后使用Page类得到查询limit条件,接着进行查询。查总记录数与查分页记录的sql语句几乎是一样的。M()->where()->count() 与 M()->where()->limit()->select(); 最近,我就在想能不能提供一种解决方法,我不喜欢写两遍呀...六、用 M('table', 'b_', 'DB2')的这种传数据库配置参数的方式之后,以后再用M('table2')无配置参数的方式时,无法还原到默认的数据库配置,查了一下源码,大概知道原因,好像把 'DB_DEPLOY_TYPE' => 0, // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器),改成 1就可以了,可我测试好像还是不行。我觉得不管怎么说,一个主配置,一个临时动态配置,不能说临时改了,就非要再手动变回来。
七、 create方法会处理许多事件,比如自动令牌验证,但是我遇到一个问题,就是我自己封装了一个insert方法如下:
//插入数据
public function insert($data='', $options=array(), $replace=false){
$token = C('TOKEN_NAME', null, '__hash__');
if($_POST[$token] && !empty($data)) $data[$token] = $_POST[$token];
if($this->create($data, self::MODEL_INSERT)){
$insert = $this->add('', $options, $replace);
}
if($insert){
$return = array('status'=>1, 'id'=>$insert, 'info'=>'success');
}else{
$return = array('status'=>-1, 'error'=>$this->error);
}
return $return;
}当我开启令牌配置,然后调用 M('table')->insert();时,不传参数,默认取POST数据,这样是没有问题的. 但是,如果我接收POST数据,组装成data数组,传进去时,忘了把令牌数据也放进去时,它就会报令牌错误.为此,我只有在从POST里取到令牌,追加到data数组中... 最佳答案