diff --git a/application/admin/controller/Action.php b/application/admin/controller/Action.php index 88aeb9af..1ca70355 100644 --- a/application/admin/controller/Action.php +++ b/application/admin/controller/Action.php @@ -140,9 +140,9 @@ class Action extends Admin { $result = db('Action')->where($map)->setField('status',$status); if ($result !== false) { action_log('setstatus_action', 'Action', $id, session('user_auth.uid')); - return $this->success('设置'.$message.'状态成功!',''); + return $this->success('设置'.$message.'状态成功!'); }else{ - return $this->error('设置'.$message.'状态失败!',''); + return $this->error('设置'.$message.'状态失败!'); } } diff --git a/application/admin/controller/Addons.php b/application/admin/controller/Addons.php index 611bc8eb..915dc7d3 100644 --- a/application/admin/controller/Addons.php +++ b/application/admin/controller/Addons.php @@ -60,10 +60,10 @@ class Addons extends Admin { if ($result) { return $this->success("创建成功!",url('admin/addons/index')); }else{ - return $this->error("创建失败!",''); + return $this->error("创建失败!"); } }else{ - return $this->error($this->addons->getError(),''); + return $this->error($this->addons->getError()); } }else{ $hooks = db('Hooks')->field('name,description')->select(); @@ -111,7 +111,7 @@ class Addons extends Admin { return $this->error($this->addons->getError()); } }else{ - return $this->error('插件不存在',''); + return $this->error('插件不存在'); } } @@ -123,7 +123,7 @@ class Addons extends Admin { if($result === false){ return $this->error($this->addons->getError(),''); }else{ - return $this->success('卸载成功!',''); + return $this->success('卸载成功!'); } } @@ -166,7 +166,7 @@ class Addons extends Admin { }else{ $id = input('id','','trim,intval'); if (!$id) { - return $this->error("非法操作!",''); + return $this->error("非法操作!"); } $info = $this->addons->find($id); if (!empty($info)) { diff --git a/application/admin/controller/Attribute.php b/application/admin/controller/Attribute.php index 891cd2da..95b616ae 100644 --- a/application/admin/controller/Attribute.php +++ b/application/admin/controller/Attribute.php @@ -101,7 +101,7 @@ class Attribute extends Admin { if ($result) { return $this->success("修改成功!",url('Attribute/index',array('model_id'=>$_POST['model_id']))); }else{ - return $this->error($this->model->getError(),''); + return $this->error($this->model->getError()); } }else{ $id = input('id','','trim,intval'); diff --git a/application/admin/controller/Category.php b/application/admin/controller/Category.php index a41c0f38..309b4665 100644 --- a/application/admin/controller/Category.php +++ b/application/admin/controller/Category.php @@ -19,12 +19,8 @@ class Category extends Admin{ public function index(){ $map = array('status' => array('gt', -1)); - $row = db('Category')->where($map)->order('sort asc,id asc')->select(); + $list = db('Category')->where($map)->order('sort asc,id asc')->column('*','id'); - $list = array(); - foreach ($row as $key => $value) { - $list[$value['id']] = $value; - } if (!empty($list)) { $tree = new \com\Tree(); $list = $tree->toFormatTree($list); @@ -240,9 +236,9 @@ class Category extends Admin{ $map['id'] = array('IN',$ids); $result = db('Category')->where($map)->setField('status', $status); if ($result) { - return $this->success("设置成功!",''); + return $this->success("设置成功!"); }else{ - return $this->error("设置失败!",''); + return $this->error("设置失败!"); } } } \ No newline at end of file diff --git a/application/admin/controller/Channel.php b/application/admin/controller/Channel.php index 5c86f9e5..375e7e28 100644 --- a/application/admin/controller/Channel.php +++ b/application/admin/controller/Channel.php @@ -21,7 +21,7 @@ class Channel extends Admin{ /* 获取频道列表 */ //$map = array('status' => array('gt', -1), 'pid'=>$pid); $map = array('status' => array('gt', -1)); - $list = db('Channel')->where($map)->order('sort asc,id asc')->select(); + $list = db('Channel')->where($map)->order('sort asc,id asc')->column('*','id'); if (!empty($list)) { $tree = new \com\Tree(); @@ -173,10 +173,10 @@ class Channel extends Admin{ if ($res !== false) { return $this->success('排序成功!',url('admin/channel/index')); } else { - return $this->error('排序失败!',''); + return $this->error('排序失败!'); } } else { - return $this->error('非法请求!',''); + return $this->error('非法请求!'); } } diff --git a/application/admin/controller/Config.php b/application/admin/controller/Config.php index d66491e1..bd15f252 100644 --- a/application/admin/controller/Config.php +++ b/application/admin/controller/Config.php @@ -203,7 +203,7 @@ class Config extends Admin{ $res = db('Config')->where(array('id' => $value))->setField('sort', $key + 1); } if ($res !== false) { - return $this->success('排序成功!', '', Cookie('__forward__')); + return $this->success('排序成功!', Cookie('__forward__')); } else { return $this->error('排序失败!'); diff --git a/application/admin/controller/Content.php b/application/admin/controller/Content.php index ff3f38a3..421802e1 100644 --- a/application/admin/controller/Content.php +++ b/application/admin/controller/Content.php @@ -55,7 +55,7 @@ class Content extends Admin{ unset($map['model_id']); } - $list = $this->model->where($map)->field($field)->order($order)->paginate(15); + $list = $this->model->where($map)->order($order)->paginate(15); $data = array( 'grid' => $grid_list, @@ -158,7 +158,7 @@ class Content extends Admin{ if ($result) { return $this->success("删除成功!"); }else{ - return $this->error("删除失败!", '', ""); + return $this->error("删除失败!"); } } @@ -188,9 +188,9 @@ class Content extends Admin{ $map['id'] = $id; $result = $model::where($map)->setField('is_top',$is_top); if (false !== $result) { - return $this->success("操作成功!", ''); + return $this->success("操作成功!"); }else{ - return $this->error("操作失败!!", ''); + return $this->error("操作失败!!"); } } diff --git a/application/admin/controller/Group.php b/application/admin/controller/Group.php index 0471f992..8218e53f 100644 --- a/application/admin/controller/Group.php +++ b/application/admin/controller/Group.php @@ -153,8 +153,8 @@ class Group extends Admin { return $this->error("非法操作!"); } if (IS_POST) { - $rule = input('rule',array()); - $extend_rule = input('extend_rule',array()); + $rule = $this->request->post('rule/a', array()); + $extend_rule = $this->request->post('extend_rule/a', array()); $extend_result = $rule_result = false; //扩展权限 $extend_data = array(); @@ -175,7 +175,7 @@ class Group extends Admin { if ($rule_result !== false || $extend_result !== false) { return $this->success("授权成功!", url('admin/group/index')); }else{ - return $this->error("授权失败!", ''); + return $this->error("授权失败!"); } }else{ $group = $this->group->where(array('id'=>$id))->find(); diff --git a/application/admin/controller/Index.php b/application/admin/controller/Index.php index be006cdf..ce456e03 100644 --- a/application/admin/controller/Index.php +++ b/application/admin/controller/Index.php @@ -27,8 +27,8 @@ class Index extends Admin{ $this->checkVerify($verify); $user = model('User'); - $info = $user->login($username,$password); - if ($info) { + $uid = $user->login($username,$password); + if ($uid > 0) { return $this->success('登录成功!',url('admin/index/index')); }else{ switch($uid) { diff --git a/application/admin/controller/Menu.php b/application/admin/controller/Menu.php index d59e536c..bae50802 100644 --- a/application/admin/controller/Menu.php +++ b/application/admin/controller/Menu.php @@ -19,7 +19,7 @@ class Menu extends Admin{ public function index(){ $map = array(); $title = trim(input('get.title')); - $list = db("Menu")->where($map)->field(true)->order('sort asc,id asc')->select(); + $list = db("Menu")->where($map)->field(true)->order('sort asc,id asc')->column('*','id'); int_to_string($list,array('hide'=>array(1=>'是',0=>'否'),'is_dev'=>array(1=>'是',0=>'否'))); if (!empty($list)) { diff --git a/application/admin/controller/Model.php b/application/admin/controller/Model.php index 87704ece..b166734c 100644 --- a/application/admin/controller/Model.php +++ b/application/admin/controller/Model.php @@ -139,7 +139,7 @@ class Model extends Admin{ if($res['status']){ return $this->success($res['info'], url('index')); }else{ - return $this->error($res['info'], ''); + return $this->error($res['info']); } } diff --git a/application/admin/controller/Seo.php b/application/admin/controller/Seo.php index c6b611b3..99c67caf 100644 --- a/application/admin/controller/Seo.php +++ b/application/admin/controller/Seo.php @@ -55,7 +55,7 @@ class Seo extends Admin{ if ($result) { return $this->success("添加成功!"); }else{ - return $this->error("添加失败!",""); + return $this->error("添加失败!"); } }else{ return $this->error($this->model->getError()); @@ -78,7 +78,7 @@ class Seo extends Admin{ if (false !== $result) { return $this->success("修改成功!"); }else{ - return $this->error("修改失败!",""); + return $this->error("修改失败!"); } }else{ return $this->error($this->model->getError()); diff --git a/application/admin/controller/User.php b/application/admin/controller/User.php index 80cfa82b..f841f4c4 100644 --- a/application/admin/controller/User.php +++ b/application/admin/controller/User.php @@ -94,7 +94,7 @@ class User extends Admin{ if (false != $reuslt) { return $this->success('修改成功!', url('admin/user/index')); }else{ - return $this->error('修改失败!', ''); + return $this->error('修改失败!'); } }else{ $info = $this->getUserinfo(); @@ -240,19 +240,19 @@ class User extends Admin{ //获取参数 $password = input('post.old'); if(empty($password)){ - return $this->error('请输入原密码',''); + return $this->error('请输入原密码'); } $data['password'] = input('post.password'); if (empty($data['password'])) { - return $this->error('请输入新密码',''); + return $this->error('请输入新密码'); } $repassword = input('post.repassword'); if (empty($repassword)) { - return $this->error('请输入确认密码',''); + return $this->error('请输入确认密码'); } if ($data['password'] !== $repassword) { - return $this->error('您输入的新密码与确认密码不一致',''); + return $this->error('您输入的新密码与确认密码不一致'); } $res = $user->updateUserFields(UID, $password, $data); if ($res) { diff --git a/application/admin/static/css/style.css b/application/admin/static/css/style.css index 20474e3e..ef836efb 100644 --- a/application/admin/static/css/style.css +++ b/application/admin/static/css/style.css @@ -2803,7 +2803,7 @@ input[type="radio"] { margin-bottom:20px; } #login-full-wrapper { - background:url(/Public/images/login-img.jpg) no-repeat center center; + background:url(/public/images/login-img.jpg) no-repeat center center; background-size:cover; width:100%; height:100%; diff --git a/application/admin/view/database/import.html b/application/admin/view/database/import.html index 5eccd3f6..2e1c02d7 100644 --- a/application/admin/view/database/import.html +++ b/application/admin/view/database/import.html @@ -17,9 +17,6 @@ - @@ -32,7 +29,6 @@ {volist name="list" id="data"} - diff --git a/application/admin/view/index/login.html b/application/admin/view/index/login.html index 47ed5d4d..a058c397 100644 --- a/application/admin/view/index/login.html +++ b/application/admin/view/index/login.html @@ -104,7 +104,10 @@ $(function(){ function success(data){ if(data.code){ - window.location.href = data.url; + $.messager.show(data.msg, {placement: 'center',type:'success'}); + setTimeout(function(){ + window.location.href = data.url; + },2000); } else { $.messager.show(data.msg, {placement: 'center',type:'success'}); //刷新验证码 diff --git a/application/common.php b/application/common.php index d200bcb6..7537fef1 100644 --- a/application/common.php +++ b/application/common.php @@ -8,7 +8,7 @@ // +---------------------------------------------------------------------- // SentCMS常量定义 -define('SENTCMS_VERSION', '3.0.20160408'); +define('SENTCMS_VERSION', '3.0.20160630'); define('SENT_ADDON_PATH', ROOT_PATH . DS . 'addons' . DS); //字符串解密加密 @@ -261,6 +261,22 @@ function get_cover($cover_id, $field = null){ return empty($field) ? $picture : $picture[$field]; } +/** + * 获取多图地址 + * @param array $covers + * @return 返回图片列表 + * @author molong + */ +function get_cover_list($covers){ + if ($covers == '') { + return false; + } + $cover_list = explode(',', $covers); + foreach ($cover_list as $item) { + $list[] = get_cover($item, 'path'); + } + return $list; +} /** * 字符串命名风格转换 diff --git a/application/common/controller/User.php b/application/common/controller/User.php index 99d5e725..b50ae1f2 100644 --- a/application/common/controller/User.php +++ b/application/common/controller/User.php @@ -34,6 +34,9 @@ class User extends Base{ array('title'=>'密码修改', 'url'=>'user/profile/editpw', 'icon'=>'key'), array('title'=>'更换头像', 'url'=>'user/profile/avatar', 'icon'=>'male'), ); + $menu['订单管理'] = array( + array('title'=>'我的订单', 'url'=>'user/order/index', 'icon'=>'shopping-bag'), + ); $contetnmenu = $this->getContentMenu(); if (!empty($contetnmenu)) { $menu['内容管理'] = $contetnmenu; diff --git a/application/common/model/Addons.php b/application/common/model/Addons.php index 582a7f0a..45a76e51 100644 --- a/application/common/model/Addons.php +++ b/application/common/model/Addons.php @@ -82,11 +82,16 @@ class Addons extends \app\common\model\Base { public function install($data){ if ($data) { - $result = $this->save($data); - if ($result) { - model('Hooks')->addHooks($data['name']); - return true; + $info = $this->where('name', $data['name'])->find(); + if (null == $info) { + $result = $this->save($data); + if ($result) { + return model('Hooks')->addHooks($data['name']); + }else{ + return false; + } }else{ + $this->error = "已安装!"; return false; } }else{ diff --git a/application/common/model/Content.php b/application/common/model/Content.php index 1164d265..dfed75c6 100644 --- a/application/common/model/Content.php +++ b/application/common/model/Content.php @@ -24,6 +24,10 @@ class Content extends Base{ 'cover_id' => 'integer', ); + protected function setUidAttr(){ + return session('user_auth.uid'); + } + protected function setCreateTimeAttr($value){ return $value ? strtotime($value) : time(); } @@ -41,7 +45,7 @@ class Content extends Base{ return date('Y-m-d H:i:s',$value); } - public function setInfo($name){ + public function extend($name){ $this->name = $name; return $this; } diff --git a/application/common/model/Hooks.php b/application/common/model/Hooks.php index e20d895f..80028396 100644 --- a/application/common/model/Hooks.php +++ b/application/common/model/Hooks.php @@ -33,8 +33,10 @@ class Hooks extends Base { } protected function setAddonsAttr($value){ - $string = implode(",", $value[1]); - return $string; + if ($value[1]) { + $string = implode(",", $value[1]); + return $string; + } } protected function getTypeTextAttr($value, $data){ @@ -71,7 +73,30 @@ class Hooks extends Base { return false; } $methods = get_class_methods($addons_class); - dump($methods); + foreach ($methods as $item) { + if ('Addon' === substr($item, -5, 5)) { + $info = $this->where('name', substr($item, 0, -5))->find(); + if (null == $info) { + $save = array( + 'name' => $addons_name, + 'description' => '', + 'type' => 1, + 'addons' => array($addons_name), + 'update_time' => time(), + 'status' => 1 + ); + $this->save($save); + }else{ + if ($info['addons']) { + # code... + }else{ + $addons = substr($item, 0, -5); + } + $this->where('name', $addons_name)->setField('addons', $addons); + } + } + } + return true; } public function removeHooks($addons_name){ diff --git a/application/common/model/Model.php b/application/common/model/Model.php index d6f6aef6..48354dd7 100644 --- a/application/common/model/Model.php +++ b/application/common/model/Model.php @@ -55,11 +55,13 @@ class Model extends Base{ if($data['extend'] == 1){ //默认文档前缀 $tablename = 'document_'.$data['name']; + $is_auto_increment = false; }else{ $tablename = $data['name']; + $is_auto_increment = true; } $sql = $db->start_table($tablename) - ->create_id('id', 11 , '主键' , false); + ->create_id('id', 11 , '主键' , $is_auto_increment); if ($data['extend'] != 1) { $sql = $sql->create_uid(); } diff --git a/application/common/view/default/ad/sider.html b/application/common/view/default/ad/sider.html index f0ffdd93..40bef426 100644 --- a/application/common/view/default/ad/sider.html +++ b/application/common/view/default/ad/sider.html @@ -1,24 +1,18 @@ \ No newline at end of file diff --git a/application/config.php b/application/config.php index a31664e5..da04c13c 100644 --- a/application/config.php +++ b/application/config.php @@ -10,7 +10,7 @@ return array( // 调试模式 - 'app_debug' => true, + 'app_debug' => false, 'charset' => 'UTF-8', 'lang_switch_on' => true, // 开启语言包功能 @@ -98,8 +98,8 @@ return array( 'path' => LOG_PATH, ), // 页面Trace信息 - // 'trace' =>array( - // //支持Html,Console 设为false则不显示 - // 'type' => false, - // ) + 'trace' =>array( + //支持Html,Console 设为false则不显示 + 'type' => 'Html', + ) ); \ No newline at end of file diff --git a/application/index/controller/Content.php b/application/index/controller/Content.php index 291136d3..f1526293 100644 --- a/application/index/controller/Content.php +++ b/application/index/controller/Content.php @@ -127,8 +127,8 @@ class Content extends Fornt{ $data = array( 'info' => $info ); - if ($name) { - $teamplate = 'content/'.$this->modelInfo['name'].'/'.$name; + if (isset($info['template_detail']) && $info['template_detail']) { + $teamplate = 'content/'.$this->modelInfo['name'].'/'.$info['template_detail']; }else{ $teamplate = 'content/'.$this->modelInfo['name'].'/detail'; } diff --git a/core/convention.php b/core/convention.php index f3523b5c..87fe69eb 100644 --- a/core/convention.php +++ b/core/convention.php @@ -144,17 +144,19 @@ return [ // +---------------------------------------------------------------------- 'log' => [ - // 日志记录方式,内置 file sae 支持扩展 - 'type' => 'File', + // 日志记录方式,内置 file socket 支持扩展 + 'type' => 'File', // 日志保存目录 - 'path' => LOG_PATH, + 'path' => LOG_PATH, + // 日志记录级别 + 'level' => [], ], // +---------------------------------------------------------------------- // | Trace设置 开启 app_trace 后 有效 // +---------------------------------------------------------------------- 'trace' => [ - // 内置Html Socket Console 支持扩展 + // 内置Html Console 支持扩展 'type' => 'Html', ], diff --git a/core/lang/zh-cn.php b/core/lang/zh-cn.php index be26c53a..44731c34 100644 --- a/core/lang/zh-cn.php +++ b/core/lang/zh-cn.php @@ -25,6 +25,7 @@ return [ 'module not exists' => '模块不存在', 'controller not exists' => '控制器不存在', 'class not exists' => '类不存在', + 'property not exists' => '类的属性不存在', 'template not exists' => '模板文件不存在', 'illegal controller name' => '非法的控制器名称', 'illegal action name' => '非法的操作名称', diff --git a/core/library/think/App.php b/core/library/think/App.php index 9226284e..4b26992f 100644 --- a/core/library/think/App.php +++ b/core/library/think/App.php @@ -187,7 +187,7 @@ class App $reflect = new \ReflectionFunction($function); $args = self::bindParams($reflect, $vars); // 记录执行信息 - self::$debug && Log::record('[ RUN ] ' . $reflect->getFileName() . '[ ' . var_export($vars, true) . ' ]', 'info'); + self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info'); return $reflect->invokeArgs($args); } @@ -213,7 +213,7 @@ class App } $args = self::bindParams($reflect, $vars); // 记录执行信息 - self::$debug && Log::record('[ RUN ] ' . $reflect->getFileName() . '[ ' . var_export($args, true) . ' ]', 'info'); + self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info'); return $reflect->invokeArgs(isset($class) ? $class : null, $args); } @@ -335,7 +335,7 @@ class App if (method_exists($instance, '_empty')) { $method = new \ReflectionMethod($instance, '_empty'); $data = $method->invokeArgs($instance, [$action, '']); - self::$debug && Log::record('[ RUN ] ' . $method->getFileName(), 'info'); + self::$debug && Log::record('[ RUN ] ' . $method->__toString(), 'info'); } else { throw new HttpException(404, 'method not exists:' . (new \ReflectionClass($instance))->getName() . '->' . $action); } diff --git a/core/library/think/Collection.php b/core/library/think/Collection.php index 9561e28f..68097131 100644 --- a/core/library/think/Collection.php +++ b/core/library/think/Collection.php @@ -40,10 +40,10 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria return empty($this->items); } - public function toArray() + public function toArray($allow = []) { return array_map(function ($value) { - return ($value instanceof Model || $value instanceof self) ? $value->toArray() : $value; + return ($value instanceof Model || $value instanceof self) ? $value->toArray($allow) : $value; }, $this->items); } @@ -74,7 +74,6 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria return new static(array_diff($this->items, $this->convertToArray($items))); } - /** * 交换数组中的键和值 * @@ -116,7 +115,6 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria return array_pop($this->items); } - /** * 通过使用用户自定义函数,以字符串返回数组 * @@ -199,7 +197,6 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria return $this; } - /** * 用回调函数过滤数组中的元素 * @param callable|null $callback @@ -228,13 +225,13 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria $result = []; foreach ($this->items as $row) { - $key = $value = null; + $key = $value = null; $keySet = $valueSet = false; - if ($index_key !== null && array_key_exists($index_key, $row)) { + if (null !== $index_key && array_key_exists($index_key, $row)) { $keySet = true; - $key = (string)$row[$index_key]; + $key = (string) $row[$index_key]; } - if ($column_key === null) { + if (null === $column_key) { $valueSet = true; $value = $row; } elseif (is_array($row) && array_key_exists($column_key, $row)) { @@ -252,7 +249,6 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria return $result; } - /** * 对数组排序 * @@ -275,7 +271,6 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria return new static($items); } - /** * 将数组打乱 * @@ -349,12 +344,13 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria /** * 转换当前数据集为JSON字符串 * @access public - * @param integer $options json参数 + * @param array $allow 允许输出的属性列表 + * @param integer $options json参数 * @return string */ - public function toJson($options = JSON_UNESCAPED_UNICODE) + public function toJson($allow = [], $options = JSON_UNESCAPED_UNICODE) { - return json_encode($this->toArray(), $options); + return json_encode($this->toArray($allow), $options); } public function __toString() @@ -373,6 +369,6 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria if ($items instanceof self) { return $items->all(); } - return (array)$items; + return (array) $items; } -} \ No newline at end of file +} diff --git a/core/library/think/File.php b/core/library/think/File.php index ef5d69da..1c541a13 100644 --- a/core/library/think/File.php +++ b/core/library/think/File.php @@ -11,6 +11,7 @@ namespace think; +use SplFileInfo; use SplFileObject; class File extends SplFileObject @@ -157,7 +158,7 @@ class File extends SplFileObject return false; } - return new \SplFileInfo($path . $savename); + return new SplFileInfo($path . $savename); } /** diff --git a/core/library/think/Log.php b/core/library/think/Log.php index 1db7dc13..135f6547 100644 --- a/core/library/think/Log.php +++ b/core/library/think/Log.php @@ -132,8 +132,21 @@ class Log // 检测日志写入权限 return false; } - $result = self::$driver->save(self::$log); + if (empty(self::$config['level'])) { + // 获取全部日志 + $log = self::$log; + } else { + // 记录允许级别 + $log = []; + foreach (self::$config['level'] as $level) { + if (isset(self::$log[$level])) { + $log[$level] = self::$log[$level]; + } + } + } + + $result = self::$driver->save($log); if ($result) { self::$log = []; } @@ -147,12 +160,19 @@ class Log * 实时写入日志信息 并支持行为 * @param mixed $msg 调试信息 * @param string $type 信息类型 + * @param bool $force 是否强制写入 * @return bool */ - public static function write($msg, $type = 'log') + public static function write($msg, $type = 'log', $force = false) { // 封装日志信息 - $log[$type][] = $msg; + if (true === $force || empty(self::$config['level'])) { + $log[$type][] = $msg; + } elseif (in_array($type, self::$config['level'])) { + $log[$type][] = $msg; + } else { + return false; + } // 监听log_write Hook::listen('log_write', $log); diff --git a/core/library/think/Model.php b/core/library/think/Model.php index cbcb1994..b3fc26ad 100644 --- a/core/library/think/Model.php +++ b/core/library/think/Model.php @@ -11,6 +11,7 @@ namespace think; +use InvalidArgumentException; use think\Cache; use think\Db; use think\db\Query; @@ -33,6 +34,7 @@ use think\paginator\Collection as PaginatorCollection; * @method static integer avg($field = '*') AVG查询 * @method static setField($field, $value = '') * @method static Query where($field, $op = null, $condition = null) 指定AND查询条件 + * @method static static findOrFail($data = null) 查找单条记录 如果不存在则抛出异常 * */ abstract class Model implements \JsonSerializable, \ArrayAccess @@ -171,7 +173,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess { if (!is_null($relation)) { // 执行关联查询 - return $this->db->relation($relation); + return $this->db()->relation($relation); } // 获取关联对象实例 @@ -204,7 +206,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess {} /** - * 设置数据对象值(不进行修改器处理) + * 设置数据对象值 * @access public * @param mixed $data 数据或者属性名 * @param mixed $value 值 @@ -212,12 +214,20 @@ abstract class Model implements \JsonSerializable, \ArrayAccess */ public function data($data, $value = null) { - if (is_object($data)) { - $this->data = get_object_vars($data); - } elseif (is_array($data)) { - $this->data = $data; - } else { + if (is_string($data)) { $this->data[$data] = $value; + } else { + if (is_object($data)) { + $data = get_object_vars($data); + } + if (true === $value) { + // 数据对象赋值 + foreach ($data as $key => $value) { + $this->setAttr($key, $value, $data); + } + } else { + $this->data = $data; + } } return $this; } @@ -227,6 +237,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess * @access public * @param string $name 字段名 留空获取全部 * @return mixed + * @throws InvalidArgumentException */ public function getData($name = null) { @@ -235,7 +246,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess } elseif (array_key_exists($name, $this->data)) { return $this->data[$name]; } else { - return false; + throw new InvalidArgumentException('property not exists:' . $this->class . '->' . $name); } } @@ -350,10 +361,17 @@ abstract class Model implements \JsonSerializable, \ArrayAccess * @access public * @param string $name 名称 * @return mixed + * @throws InvalidArgumentException */ public function getAttr($name) { - $value = $this->getData($name); + try { + $notFound = false; + $value = $this->getData($name); + } catch (InvalidArgumentException $e) { + $notFound = true; + $value = null; + } // 检测属性获取器 $method = 'get' . Loader::parseName($name, 1) . 'Attr'; @@ -362,11 +380,15 @@ abstract class Model implements \JsonSerializable, \ArrayAccess } elseif (isset($this->type[$name])) { // 类型转换 $value = $this->readTransform($value, $this->type[$name]); - } elseif (false === $value && method_exists($this, $name)) { - // 不存在该字段 获取关联数据 - $value = $this->relation()->getRelation($name); - // 保存关联对象值 - $this->data[$name] = $value; + } elseif ($notFound) { + if (method_exists($this, $name) && !method_exists('\think\Model', $name)) { + // 不存在该字段 获取关联数据 + $value = $this->relation()->getRelation($name); + // 保存关联对象值 + $this->data[$name] = $value; + } else { + throw new InvalidArgumentException('property not exists:' . $this->class . '->' . $name); + } } return $value; } @@ -450,19 +472,19 @@ abstract class Model implements \JsonSerializable, \ArrayAccess /** * 转换当前模型对象为数组 * @access public + * @param array $allow 允许输出的属性列表 * @return array */ - public function toArray() + public function toArray($allow = []) { $item = []; - if (!empty($this->append)) { - foreach ($this->append as $name) { - $item[$name] = $this->getAttr($name); - } + if (empty($allow)) { + $allow = array_keys($this->data); } + $allow = array_diff($allow, $this->hidden); foreach ($this->data as $key => $val) { - // 如果是隐藏属性不输出 - if (in_array($key, $this->hidden)) { + // 属性过滤输出 + if (!in_array($key, $allow)) { continue; } @@ -481,18 +503,25 @@ abstract class Model implements \JsonSerializable, \ArrayAccess $item[$key] = $this->getAttr($key); } } + // 追加属性(必须定义获取器) + if (!empty($this->append)) { + foreach ($this->append as $name) { + $item[$name] = $this->getAttr($name); + } + } return !empty($item) ? $item : []; } /** * 转换当前模型对象为JSON字符串 * @access public - * @param integer $options json参数 + * @param array $allow 允许输出的属性列表 + * @param integer $options json参数 * @return string */ - public function toJson($options = JSON_UNESCAPED_UNICODE) + public function toJson($allow = [], $options = JSON_UNESCAPED_UNICODE) { - return json_encode($this->toArray(), $options); + return json_encode($this->toArray($allow), $options); } /** @@ -557,7 +586,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess // 检测字段 if (!empty($this->field)) { if (true === $this->field) { - $this->field = $this->db->getTableInfo('', 'fields'); + $this->field = $this->db()->getTableInfo('', 'fields'); } foreach ($this->data as $key => $val) { if (!in_array($key, $this->field)) { @@ -989,8 +1018,8 @@ abstract class Model implements \JsonSerializable, \ArrayAccess if ($name instanceof Query) { return $name; } - $model = new static(); - $params = func_get_args(); + $model = new static(); + $params = func_get_args(); $params[0] = $model->db(); if ($name instanceof \Closure) { call_user_func_array($name, $params); @@ -1277,13 +1306,17 @@ abstract class Model implements \JsonSerializable, \ArrayAccess */ public function __isset($name) { - if (array_key_exists($name, $this->data)) { - return true; - } elseif ($this->getAttr($name)) { - return true; - } else { + try { + if (array_key_exists($name, $this->data)) { + return true; + } else { + $this->getAttr($name); + return true; + } + } catch (InvalidArgumentException $e) { return false; } + } /** diff --git a/core/library/think/Request.php b/core/library/think/Request.php index 355e84fd..3ca8f892 100644 --- a/core/library/think/Request.php +++ b/core/library/think/Request.php @@ -62,7 +62,7 @@ class Request /** * @var array 当前路由信息 */ - protected $route = []; + protected $routeInfo = []; /** * @var array 当前调度信息 @@ -81,6 +81,7 @@ class Request protected $get = []; protected $post = []; protected $request = []; + protected $route = []; protected $put; protected $delete; protected $session = []; @@ -608,21 +609,37 @@ class Request // 自动获取请求变量 switch ($method) { case 'POST': - $vars = $this->post(); + $vars = $this->post(false); break; case 'PUT': - $vars = $this->put(); + $vars = $this->put(false); break; case 'DELETE': - $vars = $this->delete(); + $vars = $this->delete(false); break; default: $vars = []; } // 当前请求参数和URL地址中的参数合并 - $this->param = array_merge($this->get(), $vars); + $this->param = array_merge($this->route(false), $this->get(false), $vars); } - return $this->input($this->param, $name, $default, $filter); + return false === $name ? $this->param : $this->input($this->param, $name, $default, $filter); + } + + /** + * 设置获取获取路由参数 + * @access public + * @param string|array $name 变量名 + * @param mixed $default 默认值 + * @param string|array $filter 过滤方法 + * @return mixed + */ + public function route($name = '', $default = null, $filter = null) + { + if (is_array($name)) { + return $this->route = array_merge($this->route, $name); + } + return false === $name ? $this->route : $this->input($this->route, $name, $default, $filter); } /** @@ -640,7 +657,7 @@ class Request } elseif (empty($this->get)) { $this->get = $_GET; } - return $this->input($this->get, $name, $default, $filter); + return false === $name ? $this->get : $this->input($this->get, $name, $default, $filter); } /** @@ -658,7 +675,7 @@ class Request } elseif (empty($this->post)) { $this->post = $_POST; } - return $this->input($this->post, $name, $default, $filter); + return false === $name ? $this->post : $this->input($this->post, $name, $default, $filter); } /** @@ -677,7 +694,7 @@ class Request if (is_null($this->put)) { parse_str(file_get_contents('php://input'), $this->put); } - return $this->input($this->put, $name, $default, $filter); + return false === $name ? $this->put : $this->input($this->put, $name, $default, $filter); } /** @@ -696,7 +713,7 @@ class Request if (is_null($this->delete)) { parse_str(file_get_contents('php://input'), $this->delete); } - return $this->input($this->delete, $name, $default, $filter); + return false === $name ? $this->delete : $this->input($this->delete, $name, $default, $filter); } /** @@ -713,7 +730,7 @@ class Request } elseif (empty($this->request)) { $this->request = $_REQUEST; } - return $this->input($this->request ?: $_REQUEST, $name, $default, $filter); + return false === $name ? $this->request : $this->input($this->request ?: $_REQUEST, $name, $default, $filter); } /** @@ -731,7 +748,7 @@ class Request } elseif (empty($this->session)) { $this->session = Session::get(); } - return $this->input($this->session, $name, $default, $filter); + return false === $name ? $this->session : $this->input($this->session, $name, $default, $filter); } /** @@ -749,7 +766,7 @@ class Request } elseif (empty($this->cookie)) { $this->cookie = $_COOKIE; } - return $this->input($this->cookie, $name, $default, $filter); + return false === $name ? $this->cookie : $this->input($this->cookie, $name, $default, $filter); } /** @@ -767,7 +784,7 @@ class Request } elseif (empty($this->server)) { $this->server = $_SERVER; } - return $this->input($this->server, $name, $default, $filter); + return false === $name ? $this->server : $this->input($this->server, $name, $default, $filter); } /** @@ -844,7 +861,7 @@ class Request } elseif (empty($this->env)) { $this->env = $_ENV; } - return $this->input($this->env, strtoupper($name), $default, $filter); + return false === $name ? $this->env : $this->input($this->env, strtoupper($name), $default, $filter); } /** @@ -882,25 +899,6 @@ class Request return isset($this->header[$name]) ? $this->header[$name] : $default; } - /** - * 获取PATH_INFO - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string|array $filter 过滤方法 - * @return mixed - */ - public function pathParam($name = '', $default = null, $filter = null) - { - $pathinfo = $this->pathinfo(); - if (!empty($pathinfo)) { - $depr = Config::get('pathinfo_depr'); - $input = explode($depr, trim($pathinfo, $depr)); - return $this->input($input, $name, $default, $filter); - } else { - return $default; - } - } - /** * 获取变量 支持过滤和默认值 * @param array $data 数据源 @@ -1279,17 +1277,17 @@ class Request } /** - * 获取当前请求的路由 + * 获取当前请求的路由信息 * @access public * @param array $route 路由名称 * @return array */ - public function route($route = []) + public function routeInfo($route = []) { if (!empty($route)) { - $this->route = $route; + $this->routeInfo = $route; } else { - return $this->route; + return $this->routeInfo; } } diff --git a/core/library/think/Route.php b/core/library/think/Route.php index 705c7e30..b8894d86 100644 --- a/core/library/think/Route.php +++ b/core/library/think/Route.php @@ -29,6 +29,10 @@ class Route 'HEAD' => [], 'OPTIONS' => [], '*' => [], + 'map' => [], + 'alias' => [], + 'domain' => [], + 'pattern' => [], ]; // REST路由操作方法定义 @@ -50,75 +54,44 @@ class Route 'DELETE' => 'delete', ]; - // URL映射规则 - private static $map = []; - // 子域名部署规则 - private static $domain = []; // 子域名 private static $subDomain = ''; - // 变量规则 - private static $pattern = []; // 域名绑定 private static $bind = []; // 当前分组 private static $group; // 当前参数 private static $option = []; - // 路由别名 - private static $alias = []; /** - * 注册或者获取URL映射规则 - * @access public - * @param string|array $map 映射名 - * @param string $route 路由地址 - * @return mixed - */ - public static function map($map = '', $route = '') - { - return self::setting('map', $map, $route); - } - - /** - * 注册或者获取变量规则 + * 注册变量规则 * @access public * @param string|array $name 变量名 * @param string $rule 变量规则 - * @return mixed + * @return void */ - public static function pattern($name = '', $rule = '') + public static function pattern($name = null, $rule = '') { - return self::setting('pattern', $name, $rule); + if (is_array($name)) { + self::$rules['pattern'] = array_merge(self::$rules['pattern'], $name); + } else { + self::$rules['pattern'][$name] = $rule; + } } /** - * 注册或者获取子域名部署规则 + * 注册子域名部署规则 * @access public * @param string|array $domain 子域名 * @param mixed $rule 路由规则 - * @return mixed + * @return void */ - public static function domain($domain = '', $rule = '') + public static function domain($domain = null, $rule = '') { - return self::setting('domain', $domain, $rule); - } - - /** - * 设置属性 - * @access public - * @param string $var 属性名称 - * @param string|array $name 变量名称 - * @param mixed $value 变量值 - * @return mixed - */ - private static function setting($var, $name = '', $value = '') - { - if (is_array($name)) { - self::${$var} = self::${$var}+$name; - } elseif (empty($value)) { - return empty($name) ? self::${$var} : self::${$var}[$name]; + if (is_array($domain)) { + self::$rules['domain'] = array_merge(self::$rules['domain'], $domain); } else { - self::${$var}[$name] = $value; + self::$rules['domain'][$domain] = $rule; } } @@ -166,12 +139,6 @@ class Route unset($rule['__pattern__']); } - // 检查路由映射 - if (isset($rule['__map__'])) { - self::map($rule['__map__']); - unset($rule['__map__']); - } - // 检查路由别名 if (isset($rule['__alias__'])) { self::alias($rule['__alias__']); @@ -193,14 +160,14 @@ class Route continue; } if (0 === strpos($key, '[')) { - $key = substr($key, 1, -1); - $result = ['routes' => $val, 'option' => [], 'pattern' => []]; + $key = substr($key, 1, -1); + self::group($key, $val); + } elseif (is_array($val)) { - $result = ['route' => $val[0], 'option' => $val[1], 'pattern' => isset($val[2]) ? $val[2] : []]; + self::setRule($key, $val[0], $type, $val[1], isset($val[2]) ? $val[2] : []); } else { - $result = ['route' => $val, 'option' => [], 'pattern' => []]; + self::setRule($key, $val, $type); } - self::$rules[$type][$key] = $result; } } @@ -212,39 +179,71 @@ class Route * @param string $type 请求类型 * @param array $option 路由参数 * @param array $pattern 变量规则 + * @return void + */ + public static function rule($rule, $route = '', $type = '*', $option = [], $pattern = []) + { + $group = self::$group; + $option = array_merge(self::$option, $option); + $type = strtoupper($type); + + if (strpos($type, '|')) { + $option['method'] = $type; + $type = '*'; + } + if (is_array($rule)) { + foreach ($rule as $key => $val) { + if (is_numeric($key)) { + $key = array_shift($val); + } + if (is_array($val)) { + $route = $val[0]; + $option1 = array_merge($option, $val[1]); + $pattern1 = array_merge($pattern, isset($val[2]) ? $val[2] : []); + } else { + $route = $val; + } + self::setRule($key, $route, $type, isset($option1) ? $option1 : $option, isset($pattern1) ? $pattern1 : $pattern, $group); + } + } else { + self::setRule($rule, $route, $type, $option, $pattern, $group); + } + + } + + /** + * 设置路由规则 + * @access public + * @param string $rule 路由规则 + * @param string $route 路由地址 + * @param string $type 请求类型 + * @param array $option 路由参数 + * @param array $pattern 变量规则 * @param string $group 所属分组 * @return void */ - public static function rule($rule, $route = '', $type = '*', $option = [], $pattern = [], $group = '') + protected static function setRule($rule, $route, $type = '*', $option = [], $pattern = [], $group = '') { - $group = $group ?: self::$group; - $type = strtoupper($type); - if (strpos($type, '|')) { - foreach (explode('|', $type) as $val) { - self::rule($rule, $route, $val, $option, $pattern, $group); - } + if ('$' == substr($rule, -1, 1)) { + // 是否完整匹配 + $option['complete_match'] = true; + $rule = substr($rule, 0, -1); + } + if ('/' != $rule) { + $rule = trim($rule, '/'); + } + $vars = self::parseVar($rule); + if ($group) { + self::$rules[$type][$group]['rule'][] = ['rule' => $rule, 'route' => $route, 'var' => $vars, 'option' => $option, 'pattern' => $pattern]; } else { - if (is_array($rule)) { - foreach ($rule as $key => $val) { - if (is_numeric($key)) { - $key = array_shift($val); - } - if (is_array($val)) { - $result = ['route' => $val[0], 'option' => array_merge($option, $val[1]), 'pattern' => isset($val[2]) ? $val[2] : []]; - } else { - $result = ['route' => $val, 'option' => $option, 'pattern' => $pattern]; - } - if ($group) { - self::$rules[$type][$group]['routes'][$key] = [$result['route'], $result['option'], $result['pattern']]; - } else { - self::$rules[$type][$key] = $result; - } - } - } else { - if ($group) { - self::$rules[$type][$group]['routes'][$rule] = [$route, $option, $pattern]; - } else { - self::$rules[$type][$rule] = ['route' => $route, 'option' => $option, 'pattern' => $pattern]; + if ('*' != $type && isset(self::$rules['*'][$rule])) { + unset(self::$rules['*'][$rule]); + } + self::$rules[$type][$rule] = ['rule' => $rule, 'route' => $route, 'var' => $vars, 'option' => $option, 'pattern' => $pattern]; + if ('*' == $type) { + // 注册路由快捷方式 + foreach (['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS'] as $method) { + self::$rules[$method][$rule] = true; } } } @@ -290,14 +289,41 @@ class Route } $type = strtoupper($type); if (!empty($name)) { + // 分组 if ($routes instanceof \Closure) { self::setGroup($name); call_user_func_array($routes, []); self::setGroup(null); + self::$rules[$type][$name]['route'] = ''; + self::$rules[$type][$name]['var'] = self::parseVar($name); self::$rules[$type][$name]['option'] = $option; self::$rules[$type][$name]['pattern'] = $pattern; + } else { - self::$rules[$type][$name] = ['routes' => $routes, 'option' => $option, 'pattern' => $pattern]; + foreach ($routes as $key => $val) { + if (is_numeric($key)) { + $key = array_shift($val); + } + if (is_array($val)) { + $route = $val[0]; + $option1 = array_merge($option, $val[1]); + $pattern1 = array_merge($pattern, isset($val[2]) ? $val[2] : []); + } else { + $route = $val; + } + $vars = self::parseVar($key); + $item[] = ['rule' => $key, 'route' => $route, 'var' => $vars, 'option' => isset($option1) ? $option1 : $option, 'pattern' => isset($pattern1) ? $pattern1 : $pattern]; + } + self::$rules[$type][$name] = ['rule' => $item, 'route' => '', 'var' => [], 'option' => $option, 'pattern' => $pattern]; + } + if ('*' == $type) { + foreach (['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS'] as $method) { + if (!isset(self::$rules[$method][$name])) { + self::$rules[$method][$name] = true; + } else { + self::$rules[$method][$name] = array_merge(self::$rules['*'][$name], self::$rules[$method][$name]); + } + } } } else { if ($routes instanceof \Closure) { @@ -319,12 +345,11 @@ class Route * @param string $route 路由地址 * @param array $option 路由参数 * @param array $pattern 变量规则 - * @param string $group 所属分组 * @return void */ - public static function any($rule, $route = '', $option = [], $pattern = [], $group = '') + public static function any($rule, $route = '', $option = [], $pattern = []) { - self::rule($rule, $route, '*', $option, $pattern, $group); + self::rule($rule, $route, '*', $option, $pattern); } /** @@ -334,12 +359,11 @@ class Route * @param string $route 路由地址 * @param array $option 路由参数 * @param array $pattern 变量规则 - * @param string $group 所属分组 * @return void */ - public static function get($rule, $route = '', $option = [], $pattern = [], $group = '') + public static function get($rule, $route = '', $option = [], $pattern = []) { - self::rule($rule, $route, 'GET', $option, $pattern, $group); + self::rule($rule, $route, 'GET', $option, $pattern); } /** @@ -349,12 +373,11 @@ class Route * @param string $route 路由地址 * @param array $option 路由参数 * @param array $pattern 变量规则 - * @param string $group 所属分组 * @return void */ - public static function post($rule, $route = '', $option = [], $pattern = [], $group = '') + public static function post($rule, $route = '', $option = [], $pattern = []) { - self::rule($rule, $route, 'POST', $option, $pattern, $group); + self::rule($rule, $route, 'POST', $option, $pattern); } /** @@ -364,12 +387,11 @@ class Route * @param string $route 路由地址 * @param array $option 路由参数 * @param array $pattern 变量规则 - * @param string $group 所属分组 * @return void */ - public static function put($rule, $route = '', $option = [], $pattern = [], $group = '') + public static function put($rule, $route = '', $option = [], $pattern = []) { - self::rule($rule, $route, 'PUT', $option, $pattern, $group); + self::rule($rule, $route, 'PUT', $option, $pattern); } /** @@ -379,12 +401,11 @@ class Route * @param string $route 路由地址 * @param array $option 路由参数 * @param array $pattern 变量规则 - * @param string $group 所属分组 * @return void */ - public static function delete($rule, $route = '', $option = [], $pattern = [], $group = '') + public static function delete($rule, $route = '', $option = [], $pattern = []) { - self::rule($rule, $route, 'DELETE', $option, $pattern, $group); + self::rule($rule, $route, 'DELETE', $option, $pattern); } /** @@ -457,12 +478,10 @@ class Route */ public static function alias($rule = null, $route = '', $option = []) { - if (is_null($rule)) { - return self::$alias; - } elseif (is_array($rule)) { - self::$alias = array_merge(self::$alias, $rule); + if (is_array($rule)) { + self::$rules['alias'] = array_merge(self::$rules['alias'], $rule); } else { - self::$alias[$rule] = $option ? [$route, $option] : $route; + self::$rules['alias'][$rule] = $option ? [$route, $option] : $route; } } @@ -504,26 +523,29 @@ class Route * @param string $route 路由地址 * @param string $method 请求类型 * @param array $option 路由参数 - * @param string $group 路由分组 * @return void */ - public static function miss($route, $method = '*', $option = [], $group = '') + public static function miss($route, $method = '*', $option = []) { - self::rule('__miss__', $route, $method, $option, [], $group); + self::rule('__miss__', $route, $method, $option, []); } /** - * 获取路由定义 + * 获取或者批量设置路由定义 * @access public - * @param string $method 请求类型 + * @param mixed $rules 请求类型或者路由定义数组 * @return array */ - public static function getRules($method = '') + public static function rules($rules = '') { - if ($method) { - return self::$rules[$method]; + if (is_array($rules)) { + self::$rules = $rules; + } elseif ($rules) { + return self::$rules[$rules]; } else { - return array_merge_recursive(self::$rules['*'], self::$rules['GET'], self::$rules['POST'], self::$rules['PUT'], self::$rules['DELETE']); + $rules = self::$rules; + unset($rules['pattern'], $rules['alias'], $rules['domain']); + return $rules; } } @@ -536,7 +558,7 @@ class Route public static function checkDomain($request) { // 域名规则 - $rules = self::$domain; + $rules = self::$rules['domain']; // 开启子域名部署 支持二级和三级域名 if (!empty($rules)) { $host = $request->host(); @@ -636,151 +658,148 @@ class Route $url = str_replace($depr, '/', $url); } - if (isset(self::$map[$url])) { - // URL映射(完整静态URL匹配) - return self::parseModule(self::$map[$url], $depr); - } - - if (strpos($url, '/') && isset(self::$alias[strstr($url, '/', true)])) { - // 路由别名 - $array = explode('/', $url, 2); - $item = self::$alias[$array[0]]; - - if (is_array($item)) { - list($rule, $option) = $item; - } else { - $rule = $item; + if (strpos($url, '/') && isset(self::$rules['alias'][strstr($url, '/', true)])) { + // 检测路由别名 + $result = self::checkRouteAlias($request, $url, $depr); + if (false !== $result) { + return $result; } - // 参数有效性检查 - if (isset($option) && !self::checkOption($option, $url, $request)) { - // 路由不匹配 - } elseif (0 === strpos($rule, '\\')) { - // 路由到类 - return self::bindToClass($array[1], substr($rule, 1), $depr); - } elseif (0 === strpos($url, '@')) { - // 路由到控制器类 - return self::bindToController($array[1], substr($rule, 1), $depr); - } else { - // 路由到模块/控制器 - return self::bindToModule($array[1], $rule, $depr); - } - } - - // 获取当前请求类型的路由规则 - $rules = self::$rules[$request->method()]; - - if (!empty(self::$rules['*'])) { - // 合并任意请求的路由规则 - $rules = array_merge_recursive(self::$rules['*'], $rules); } // 检测域名部署 if ($checkDomain) { self::checkDomain($request); } + // 检测URL绑定 $return = self::checkUrlBind($url, $rules, $depr); - if ($return) { + if (false !== $return) { return $return; } + // 获取当前请求类型的路由规则 + $rules = self::$rules[$request->method()]; + + if (isset($rules[$url])) { + // 静态路由规则检测 + $rule = $rules[$url]; + if (true === $rule) { + $rule = self::$rules['*'][$url]; + } + return self::parseRule($url, $rule['route'], $url, $rule['option']); + } + // 路由规则检测 if (!empty($rules)) { - foreach ($rules as $rule => $val) { - $option = isset($val['option']) ? $val['option'] : []; - $pattern = isset($val['pattern']) ? $val['pattern'] : []; + return self::checkRoute($request, $rules, $url); + } + return false; + } - // 参数有效性检查 - if (!self::checkOption($option, $url, $request)) { - continue; - } - if ('__miss__' == $rule) { - // 指定分组MISS路由 - $miss = $val['route']; - continue; - } - if (!empty($val['routes'])) { - // 分组路由 - if (($pos = strpos($rule, ':')) || ($pos = strpos($rule, '<'))) { - $str = substr($rule, 0, $pos); - } else { - $str = $rule; - } - if (0 !== strpos($url, $str)) { - continue; - } - $missGroup = false; - // 匹配到路由分组 - foreach ($val['routes'] as $key => $route) { - if (is_numeric($key)) { - $key = array_shift($route); - } - // 检查规则路由 - if (is_array($route)) { - $option1 = $route[1]; - // 检查参数有效性 - if (!self::checkOption($option1, $url, $request)) { - continue; - } - $pattern = array_merge($pattern, isset($route[2]) ? $route[2] : []); - $route = $route[0]; - $option = array_merge($option, $option1); - } - if ('__miss__' == $key) { - // 指定分组MISS路由 - $missGroup = $route; - continue; - } - $key = $rule . ($key ? '/' . ltrim($key, '/') : ''); - $result = self::checkRule($key, $route, $url, $pattern, $option); - if (false !== $result) { - $request->route(['rule' => $key, 'route' => $route, 'pattern' => $pattern, 'option' => $option]); - return $result; - } - } - if ($missGroup) { - // 未匹配所有路由的路由规则处理 - if ($missGroup instanceof \Closure) { - // 执行闭包 - return ['type' => 'function', 'function' => $missGroup, 'params' => []]; - } else { - return self::parseRule('', $missGroup, $url, []); - } - } - } else { - if (is_numeric($rule)) { - $rule = array_shift($val); - } - // 单项路由 - $route = !empty($val['route']) ? $val['route'] : ''; - // 规则路由 - $result = self::checkRule($rule, $route, $url, $pattern, $option); - if (false !== $result) { - $request->route(['rule' => $rule, 'route' => $route, 'pattern' => $pattern, 'option' => $option]); - return $result; - } - } + /** + * 检测路由规则 + * @access private + * @param Request $request + * @param array $rules 路由规则 + * @param string $url URL地址 + * @param string $group 路由分组名 + * @return mixed + */ + private static function checkRoute($request, $rules, $url, $group = '') + { + foreach ($rules as $key => $item) { + if (true === $item) { + $item = self::$rules['*'][$key]; } - if (isset($miss)) { - // 未匹配所有路由的路由规则处理 - if ($miss instanceof \Closure) { - // 执行闭包 - return ['type' => 'function', 'function' => $miss, 'params' => []]; + $rule = $item['rule']; + $route = $item['route']; + $vars = $item['var']; + $option = $item['option']; + $pattern = $item['pattern']; + + // 检查参数有效性 + if (!self::checkOption($option, $url, $request)) { + continue; + } + + if (is_array($rule)) { + // 分组路由 + if (($pos = strpos($key, ':')) || ($pos = strpos($key, '<'))) { + $str = substr($key, 0, $pos); } else { - return self::parseRule('', $miss, $url, []); + $str = $key; + } + if (0 !== strpos($url, $str)) { + continue; + } + + $result = self::checkRoute($request, $rule, $url, $key); + if (false !== $result) { + return $result; + } + } else { + if ('__miss__' == $rule) { + // 指定MISS路由 + $miss = $item; + continue; + } + if ($group) { + $rule = $group . '/' . ltrim($rule, '/'); + } + $result = self::checkRule($rule, $route, $url, $pattern, $option); + if (false !== $result) { + return $result; } } } + if (isset($miss)) { + // 未匹配所有路由的路由规则处理 + return self::parseRule('', $miss, $url); + } return false; } + /** + * 检测路由别名 + * @access private + * @param Request $request + * @param string $url URL地址 + * @param string $depr URL分隔符 + * @return mixed + */ + private static function checkRouteAlias($request, $url, $depr) + { + $array = explode('/', $url, 2); + $item = self::$rules['alias'][$array[0]]; + + if (is_array($item)) { + list($rule, $option) = $item; + } else { + $rule = $item; + } + // 参数有效性检查 + if (isset($option) && !self::checkOption($option, $url, $request)) { + // 路由不匹配 + return false; + } elseif (0 === strpos($rule, '\\')) { + // 路由到类 + return self::bindToClass($array[1], substr($rule, 1), $depr); + } elseif (0 === strpos($url, '@')) { + // 路由到控制器类 + return self::bindToController($array[1], substr($rule, 1), $depr); + } else { + // 路由到模块/控制器 + return self::bindToModule($array[1], $rule, $depr); + } + } + /** * 检测URL绑定 * @access private * @param string $url URL地址 * @param array $rules 路由规则 * @param string $depr URL分隔符 - * @return false + * @return mixed */ private static function checkUrlBind(&$url, &$rules, $depr = '/') { @@ -847,27 +866,6 @@ class Route return ['type' => 'method', 'method' => [$namespace . '\\' . $class, $method], 'params' => []]; } - /** - * 绑定到应用 直接进行控制器类库访问 - * @access public - * @param string $url URL地址 - * @param string $depr URL分隔符 - * @return array - */ - public static function bindToApp($url, $depr = '/') - { - $array = explode($depr, $url, 4); - $module = !empty($array[0]) ? $array[0] : Config::get('default_module'); - $controller = !empty($array[1]) ? $array[1] : Config::get('default_controller'); - $method = !empty($array[2]) ? $array[2] : Config::get('default_action'); - $layer = Config::get('url_controller_layer'); - $class = App::$namespace . '\\' . $module . '\\' . $layer . '\\' . $controller; - if (!empty($array[3])) { - self::parseUrlParams($array[3]); - } - return ['type' => 'method', 'method' => [$class, $method], 'params' => []]; - } - /** * 绑定到控制器类 * @access public @@ -949,48 +947,22 @@ class Route $rule = str_replace($depr, '/', $rule); } - $rule = ltrim($rule, '/'); $len1 = substr_count($url, '/'); $len2 = substr_count($rule, '/'); // 多余参数是否合并 $merge = !empty($option['merge_extra_vars']) ? true : false; if ($len1 >= $len2 || strpos($rule, '[')) { - if ('$' == substr($rule, -1, 1)) { + if (!empty($option['complete_match'])) { // 完整匹配 if (!$merge && $len1 != $len2 && (false === strpos($rule, '[') || $len1 > $len2 || $len1 < $len2 - substr_count($rule, '['))) { return false; - } else { - $rule = substr($rule, 0, -1); } } - $pattern = array_merge(self::$pattern, $pattern); + $pattern = array_merge(self::$rules['pattern'], $pattern); if (false !== $match = self::match($url, $rule, $pattern, $merge)) { // 匹配到路由规则 - // 检测是否定义路由 - if (!empty($option['after_behavior'])) { - if ($option['after_behavior'] instanceof \Closure) { - $result = call_user_func_array($option['after_behavior'], [$route]); - } else { - foreach ((array) $option['after_behavior'] as $behavior) { - $result = Hook::exec($behavior, '', $route); - if (!is_null($result)) { - break; - } - } - } - // 路由规则重定向 - if ($result instanceof Response) { - return ['type' => 'response', 'response' => $result, 'params' => $match]; - } elseif (is_array($result)) { - return $result; - } - } - if ($route instanceof \Closure) { - // 执行闭包 - return ['type' => 'function', 'function' => $route, 'params' => $match]; - } - return self::parseRule($rule, $route, $url, $match, $merge); + return self::parseRule($rule, $route, $url, $option, $match, $merge); } } return false; @@ -1141,40 +1113,69 @@ class Route * @param string $rule 路由规则 * @param string $route 路由地址 * @param string $pathinfo URL地址 + * @param array $option 路由参数 * @param array $matches 匹配的变量 * @param bool $merge 合并额外变量 * @return array */ - private static function parseRule($rule, $route, $pathinfo, $matches, $merge = false) + private static function parseRule($rule, $route, $pathinfo, $option = [], $matches = [], $merge = false) { + // 检测是否定义路由 + if (!empty($option['after_behavior'])) { + if ($option['after_behavior'] instanceof \Closure) { + $result = call_user_func_array($option['after_behavior'], [$route]); + } else { + foreach ((array) $option['after_behavior'] as $behavior) { + $result = Hook::exec($behavior, '', $route); + if (!is_null($result)) { + break; + } + } + } + // 路由规则重定向 + if ($result instanceof Response) { + return ['type' => 'response', 'response' => $result, 'params' => $matches]; + } elseif (is_array($result)) { + return $result; + } + } + // 解析路由规则 - $rule = explode('/', $rule); - // 获取URL地址中的参数 - $paths = $merge ? explode('/', $pathinfo, count($rule)) : explode('/', $pathinfo); + if ($rule) { + $rule = explode('/', $rule); + // 获取URL地址中的参数 + $paths = $merge ? explode('/', $pathinfo, count($rule)) : explode('/', $pathinfo); + foreach ($rule as $item) { + $fun = ''; + if (0 === strpos($item, '[:')) { + $item = substr($item, 1, -1); + } + if (0 === strpos($item, ':')) { + $var = substr($item, 1); + $matches[$var] = array_shift($paths); + } else { + // 过滤URL中的静态变量 + array_shift($paths); + } + } + } else { + $paths = explode('/', $pathinfo); + } // 获取路由地址规则 $url = is_array($route) ? $route[0] : $route; - - foreach ($rule as $item) { - $fun = ''; - if (0 === strpos($item, '[:')) { - $item = substr($item, 1, -1); - } - if (0 === strpos($item, ':')) { - $var = substr($item, 1); - $matches[$var] = array_shift($paths); - } else { - // 过滤URL中的静态变量 - array_shift($paths); - } - } // 替换路由地址中的变量 - foreach ($matches as $key => $val) { - if (false !== strpos($url, ':' . $key)) { - $url = str_replace(':' . $key, $val, $url); - unset($matches[$key]); + if (is_string($url) && !empty($matches)) { + foreach ($matches as $key => $val) { + if (false !== strpos($url, ':' . $key)) { + $url = str_replace(':' . $key, $val, $url); + unset($matches[$key]); + } } } - if (0 === strpos($url, '/') || 0 === strpos($url, 'http')) { + if ($url instanceof \Closure) { + // 执行闭包 + $result = ['type' => 'function', 'function' => $url, 'params' => $matches]; + } elseif (0 === strpos($url, '/') || 0 === strpos($url, 'http')) { // 路由到重定向地址 $result = ['type' => 'redirect', 'url' => $url, 'status' => (is_array($route) && isset($route[1])) ? $route[1] : 301]; } elseif (0 === strpos($url, '\\')) { @@ -1190,6 +1191,8 @@ class Route } // 解析额外参数 self::parseUrlParams(empty($paths) ? '' : implode('/', $paths), $matches); + // 记录匹配的路由信息 + Request::instance()->routeInfo(['rule' => $rule, 'route' => $route, 'option' => $option]); return $result; } @@ -1235,7 +1238,39 @@ class Route } } // 设置当前请求的参数 - Request::instance()->param(array_merge($var, $_GET)); + Request::instance()->route($var); } + // 分析路由规则中的变量 + private static function parseVar($rule) + { + // 提取路由规则中的变量 + $var = []; + foreach (explode('/', $rule) as $val) { + $optional = false; + if (false !== strpos($val, '<') && preg_match_all('/<(\w+(\??))>/', $val, $matches)) { + foreach ($matches[1] as $name) { + if (strpos($name, '?')) { + $name = substr($name, 0, -1); + $optional = true; + } else { + $optional = false; + } + $var[$name] = $optional ? 2 : 1; + } + } + + if (0 === strpos($val, '[:')) { + // 可选参数 + $optional = true; + $val = substr($val, 1, -1); + } + if (0 === strpos($val, ':')) { + // URL变量 + $name = substr($val, 1); + $var[$name] = $optional ? 2 : 1; + } + } + return $var; + } } diff --git a/core/library/think/Url.php b/core/library/think/Url.php index 5f802011..cf570af0 100644 --- a/core/library/think/Url.php +++ b/core/library/think/Url.php @@ -19,6 +19,9 @@ use think\Route; class Url { + // 生成URL地址的root + protected static $root; + /** * URL生成 支持路由反射 * @param string $url URL表达式, @@ -113,7 +116,7 @@ class Url // 检测域名 $domain = self::parseDomain($url, $domain); // URL组装 - $url = $domain . Request::instance()->root() . '/' . ltrim($url, '/'); + $url = $domain . (self::$root ?: Request::instance()->root()) . '/' . ltrim($url, '/'); return $url; } @@ -140,7 +143,7 @@ class Url $url = $module . $controller . '/' . $request->action(); } else { $path = explode('/', $url); - $action = array_pop($path); + $action = Config::get('url_convert') ? strtolower(array_pop($path)) : array_pop($path); $controller = empty($path) ? $controller : (Config::get('url_convert') ? Loader::parseName(array_pop($path)) : array_pop($path)); $module = empty($path) ? $module : array_pop($path) . '/'; $url = $module . $controller . '/' . $action; @@ -152,45 +155,44 @@ class Url // 检测域名 protected static function parseDomain(&$url, $domain) { - if ($domain) { - $request = Request::instance(); - if (true === $domain) { - // 自动判断域名 - $domain = $request->host(); - if (Config::get('url_domain_deploy')) { - // 根域名 - $urlDomainRoot = Config::get('url_domain_root'); - $domains = Route::domain(); - $route_domain = array_keys($domains); - foreach ($route_domain as $domain_prefix) { - if (0 === strpos($domain_prefix, '*.') && strpos($domain, ltrim($domain_prefix, '*.')) !== false) { - foreach ($domains as $key => $rule) { - $rule = is_array($rule) ? $rule[0] : $rule; - if (false === strpos($key, '*') && 0 === strpos($url, $rule)) { - $url = ltrim($url, $rule); - $domain = $key; - // 生成对应子域名 - if (!empty($urlDomainRoot)) { - $domain .= $urlDomainRoot; - } - break; - } else if (false !== strpos($key, '*')) { - if (!empty($urlDomainRoot)) { - $domain .= $urlDomainRoot; - } - break; + if (!$domain) { + return ''; + } + $request = Request::instance(); + if (true === $domain) { + // 自动判断域名 + $domain = $request->host(); + if (Config::get('url_domain_deploy')) { + // 根域名 + $urlDomainRoot = Config::get('url_domain_root'); + $domains = Route::rules('domain'); + $route_domain = array_keys($domains); + foreach ($route_domain as $domain_prefix) { + if (0 === strpos($domain_prefix, '*.') && strpos($domain, ltrim($domain_prefix, '*.')) !== false) { + foreach ($domains as $key => $rule) { + $rule = is_array($rule) ? $rule[0] : $rule; + if (false === strpos($key, '*') && 0 === strpos($url, $rule)) { + $url = ltrim($url, $rule); + $domain = $key; + // 生成对应子域名 + if (!empty($urlDomainRoot)) { + $domain .= $urlDomainRoot; } + break; + } else if (false !== strpos($key, '*')) { + if (!empty($urlDomainRoot)) { + $domain .= $urlDomainRoot; + } + break; } } } } - } else { - $domain .= strpos($domain, '.') ? '' : strstr($request->host(), '.'); } - $domain = ($request->isSsl() ? 'https://' : 'http://') . $domain; } else { - $domain = ''; + $domain .= strpos($domain, '.') ? '' : strstr($request->host(), '.'); } + $domain = ($request->isSsl() ? 'https://' : 'http://') . $domain; return $domain; } @@ -258,24 +260,36 @@ class Url // 生成路由映射并缓存 private static function getRouteAlias() { - static $item = []; - if (!empty($item)) { - return $item; - } if ($item = Cache::get('think_route_map')) { return $item; } // 获取路由定义 - $rules = Route::getRules(); - foreach ($rules as $rule => $val) { - if (!empty($val['routes'])) { - foreach ($val['routes'] as $key => $route) { - if (is_numeric($key)) { - $key = array_shift($route); - } - if (is_array($route)) { - $route = $route[0]; + $array = Route::rules(); + foreach ($array as $type => $rules) { + foreach ($rules as $rule => $val) { + if (true === $val || empty($val['rule'])) { + continue; + } + $route = $val['route']; + $vars = $val['var']; + if (is_array($val['rule'])) { + foreach ($val['rule'] as $val) { + $key = $val['rule']; + $route = $val['route']; + $var = $val['var']; + $param = []; + if (is_array($route)) { + $route = implode('\\', $route); + } elseif ($route instanceof \Closure) { + continue; + } elseif (strpos($route, '?')) { + list($route, $str) = explode('?', $route, 2); + parse_str($str, $param); + } + $var = array_merge($vars, $var); + $item[$route][] = [$rule . '/' . $key, $var, $param]; } + } else { $param = []; if (is_array($route)) { $route = implode('\\', $route); @@ -285,38 +299,13 @@ class Url list($route, $str) = explode('?', $route, 2); parse_str($str, $param); } - $var = self::parseVar($rule . '/' . $key); - $item[$route][] = [$rule . '/' . $key, $var, $param]; + $item[$route][] = [$rule, $vars, $param]; } - } else { - $route = $val['route']; - $param = []; - if (is_array($route)) { - $route = implode('\\', $route); - } elseif ($route instanceof \Closure) { - continue; - } elseif (strpos($route, '?')) { - list($route, $str) = explode('?', $route, 2); - parse_str($str, $param); - } - $var = self::parseVar($rule); - $item[$route][] = [$rule, $var, $param]; } } - // 检测路由映射 - $maps = Route::map(); - foreach ($maps as $rule => $route) { - $param = []; - if (strpos($route, '?')) { - list($route, $str) = explode('?', $route, 2); - parse_str($str, $param); - } - $item[$route][] = [$rule, [], $param]; - } - // 检测路由别名 - $alias = Route::alias(); + $alias = Route::rules('alias'); foreach ($alias as $rule => $route) { $route = is_array($route) ? $route[0] : $route; $item[$route][] = [$rule, [], []]; @@ -325,45 +314,16 @@ class Url return $item; } - // 分析路由规则中的变量 - private static function parseVar($rule) - { - // 提取路由规则中的变量 - $var = []; - foreach (explode('/', $rule) as $val) { - $optional = false; - if (false !== strpos($val, '<') && preg_match_all('/<(\w+(\??))>/', $val, $matches)) { - foreach ($matches[1] as $name) { - if (strpos($name, '?')) { - $name = substr($name, 0, -1); - $optional = true; - } else { - $optional = false; - } - $var[$name] = $optional ? 2 : 1; - } - } - - if ('$' == substr($val, -1, 1)) { - $val = substr($val, 0, -1); - } - if (0 === strpos($val, '[:')) { - // 可选参数 - $optional = true; - $val = substr($val, 1, -1); - } - if (0 === strpos($val, ':')) { - // URL变量 - $name = substr($val, 1); - $var[$name] = $optional ? 2 : 1; - } - } - return $var; - } - // 清空路由别名缓存 public static function clearAliasCache() { Cache::rm('think_route_map'); } + + // 指定当前生成URL地址的root + public static function root($root) + { + self::$root = $root; + Request::instance()->root($root); + } } diff --git a/core/library/think/cache/driver/File.php b/core/library/think/cache/driver/File.php index 53a5ded6..29cd3773 100644 --- a/core/library/think/cache/driver/File.php +++ b/core/library/think/cache/driver/File.php @@ -38,8 +38,8 @@ class File if (!empty($options)) { $this->options = array_merge($this->options, $options); } - if (substr($this->options['path'], -1) != '/') { - $this->options['path'] .= '/'; + if (substr($this->options['path'], -1) != DS) { + $this->options['path'] .= DS; } $this->init(); } @@ -74,7 +74,7 @@ class File $dir = ''; $len = $this->options['path_level']; for ($i = 0; $i < $len; $i++) { - $dir .= $name{$i} . '/'; + $dir .= $name{$i} . DS; } if (!is_dir($this->options['path'] . $dir)) { mkdir($this->options['path'] . $dir, 0755, true); diff --git a/core/library/think/cache/driver/Lite.php b/core/library/think/cache/driver/Lite.php index 551359f7..0a3a838b 100644 --- a/core/library/think/cache/driver/Lite.php +++ b/core/library/think/cache/driver/Lite.php @@ -36,8 +36,8 @@ class Lite if (!empty($options)) { $this->options = array_merge($this->options, $options); } - if (substr($this->options['path'], -1) != '/') { - $this->options['path'] .= '/'; + if (substr($this->options['path'], -1) != DS) { + $this->options['path'] .= DS; } } diff --git a/core/library/think/cache/driver/Memcached.php b/core/library/think/cache/driver/Memcached.php index 93e58267..50082a1e 100644 --- a/core/library/think/cache/driver/Memcached.php +++ b/core/library/think/cache/driver/Memcached.php @@ -12,19 +12,18 @@ namespace think\cache\driver; use think\Cache; -use think\Exception; class Memcached { - protected $handler = null; + protected $handler; protected $options = [ - 'host' => '127.0.0.1', - 'port' => 11211, - 'expire' => 0, - 'timeout' => 0, // 超时时间(单位:毫秒) - 'prefix' => '', - 'username' => '', //账号 - 'password' => '', //密码 + 'host' => '127.0.0.1', + 'port' => 11211, + 'expire' => 0, + 'timeout' => 0, // 超时时间(单位:毫秒) + 'prefix' => '', + 'username' => '', //账号 + 'password' => '', //密码 ]; /** @@ -57,9 +56,9 @@ class Memcached $servers[] = [$host, (isset($ports[$i]) ? $ports[$i] : $ports[0]), 1]; } $this->handler->addServers($servers); - if('' != $this->options['username']){ + if ('' != $this->options['username']) { $this->handler->setOption(\Memcached::OPT_BINARY_PROTOCOL, true); - $this->handler->setSaslAuthData($this->options['username'], $this->options['password']); + $this->handler->setSaslAuthData($this->options['username'], $this->options['password']); } } diff --git a/core/library/think/cache/driver/Sae.php b/core/library/think/cache/driver/Sae.php deleted file mode 100644 index fbc20979..00000000 --- a/core/library/think/cache/driver/Sae.php +++ /dev/null @@ -1,122 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\cache\driver; - -use think\Cache; -use think\Exception; - -/** - * SAE Memcache缓存驱动 - * @author liu21st - */ -class Sae -{ - protected $handler = null; - protected $options = [ - 'host' => '127.0.0.1', - 'port' => 11211, - 'expire' => 0, - 'timeout' => false, - 'persistent' => false, - 'prefix' => '', - ]; - - /** - * 架构函数 - * @param array $options 缓存参数 - * @access public - */ - public function __construct($options = []) - { - if (!function_exists('memcache_init')) { - throw new \BadFunctionCallException('must run at sae'); - } - $this->handler = memcache_init(); - if (!$this->handler) { - throw new Exception('memcache init error'); - } - if (!empty($options)) { - $this->options = array_merge($this->options, $options); - } - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) - { - return $this->handler->get($_SERVER['HTTP_APPVERSION'] . '/' . $this->options['prefix'] . $name); - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param integer $expire 有效时间(秒) - * @return bool - */ - public function set($name, $value, $expire = null) - { - if (is_null($expire)) { - $expire = $this->options['expire']; - } - $name = $this->options['prefix'] . $name; - if ($this->handler->set($_SERVER['HTTP_APPVERSION'] . '/' . $name, $value, 0, $expire)) { - return true; - } - return false; - } - - /** - * 删除缓存 - * @param string $name 缓存变量名 - * @param bool|false $ttl - * @return bool - */ - public function rm($name, $ttl = false) - { - $name = $_SERVER['HTTP_APPVERSION'] . '/' . $this->options['prefix'] . $name; - return false === $ttl ? - $this->handler->delete($name) : - $this->handler->delete($name, $ttl); - } - - /** - * 清除缓存 - * @access public - * @return bool - */ - public function clear() - { - return $this->handler->flush(); - } - - /** - * 获得SaeKv对象 - */ - private function getKv() - { - static $kv; - if (!$kv) { - $kv = new \SaeKV(); - if (!$kv->init()) { - throw new Exception('KVDB init error'); - } - } - return $kv; - } - -} diff --git a/core/library/think/cache/driver/Sqlite.php b/core/library/think/cache/driver/Sqlite.php index 8a7c19aa..e4689d61 100644 --- a/core/library/think/cache/driver/Sqlite.php +++ b/core/library/think/cache/driver/Sqlite.php @@ -18,7 +18,7 @@ use think\Exception; * Sqlite缓存驱动 * @author liu21st */ -class Sqlite implements CacheInterface +class Sqlite { protected $options = [ diff --git a/core/library/think/db/Query.php b/core/library/think/db/Query.php index 8b7c5556..b589ff54 100644 --- a/core/library/think/db/Query.php +++ b/core/library/think/db/Query.php @@ -964,8 +964,7 @@ class Query * fragment:url锚点, * var_page:分页变量, * list_rows:每页数量 - * type:分页类名, - * namespace:分页类命名空间 + * type:分页类名 * @return \think\paginator\Collection * @throws DbException */ @@ -1717,8 +1716,8 @@ class Query * @param array|string|Query|\Closure $data * @return Collection|false|\PDOStatement|string * @throws DbException - * @throws Exception - * @throws PDOException + * @throws ModelNotFoundException + * @throws DataNotFoundException */ public function select($data = null) { @@ -1789,11 +1788,7 @@ class Query } } } elseif (!empty($options['fail'])) { - if (!empty($this->model)) { - throw new ModelNotFoundException('model data Not Found:' . $this->model, $this->model, $options); - } else { - throw new DataNotFoundException('table data not Found:' . $options['table'], $options['table'], $options); - } + $this->throwNotFound($options); } return $resultSet; } @@ -1804,8 +1799,8 @@ class Query * @param array|string|Query|\Closure $data * @return array|false|\PDOStatement|string|Model * @throws DbException - * @throws Exception - * @throws PDOException + * @throws ModelNotFoundException + * @throws DataNotFoundException */ public function find($data = null) { @@ -1874,25 +1869,37 @@ class Query } } } elseif (!empty($options['fail'])) { - if (!empty($this->model)) { - throw new ModelNotFoundException('model data Not Found:' . $this->model, $this->model, $options); - } else { - throw new DataNotFoundException('table data not Found:' . $options['table'], $options['table'], $options); - } + $this->throwNotFound($options); } else { $data = null; } return $data; } + /** + * 查询失败 抛出异常 + * @access public + * @param array $options 查询参数 + * @throws ModelNotFoundException + * @throws DataNotFoundException + */ + protected function throwNotFound($options = []) + { + if (!empty($this->model)) { + throw new ModelNotFoundException('model data Not Found:' . $this->model, $this->model, $options); + } else { + throw new DataNotFoundException('table data not Found:' . $options['table'], $options['table'], $options); + } + } + /** * 查找多条记录 如果不存在则抛出异常 * @access public * @param array|string|Query|\Closure $data * @return array|\PDOStatement|string|Model * @throws DbException - * @throws Exception - * @throws PDOException + * @throws ModelNotFoundException + * @throws DataNotFoundException */ public function selectOrFail($data = null) { @@ -1905,8 +1912,8 @@ class Query * @param array|string|Query|\Closure $data * @return array|\PDOStatement|string|Model * @throws DbException - * @throws Exception - * @throws PDOException + * @throws ModelNotFoundException + * @throws DataNotFoundException */ public function findOrFail($data = null) { diff --git a/core/library/think/db/builder/Mysql.php b/core/library/think/db/builder/Mysql.php index d7427af7..84853307 100644 --- a/core/library/think/db/builder/Mysql.php +++ b/core/library/think/db/builder/Mysql.php @@ -31,7 +31,7 @@ class Mysql extends Builder $key = trim($key); if (strpos($key, '$.') && false === strpos($key, '(')) { // JSON字段支持 - list($field, $name) = explode($key, '$.'); + list($field, $name) = explode('$.', $key); $key = 'jsn_extract(' . $field . ', \'$.\'.' . $name . ')'; } if (!preg_match('/[,\'\"\*\(\)`.\s]/', $key)) { diff --git a/core/library/think/db/builder/Sqlsrv.php b/core/library/think/db/builder/Sqlsrv.php index 8cc0f324..f54bd139 100644 --- a/core/library/think/db/builder/Sqlsrv.php +++ b/core/library/think/db/builder/Sqlsrv.php @@ -20,7 +20,7 @@ class Sqlsrv extends Builder { protected $selectSql = 'SELECT T1.* FROM (SELECT thinkphp.*, ROW_NUMBER() OVER (%ORDER%) AS ROW_NUMBER FROM (SELECT %DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%) AS thinkphp) AS T1 %LIMIT%%COMMENT%'; protected $selectInsertSql = 'SELECT %DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%'; - protected $updateSql = 'UPDATE %TABLE% SET %SET% %JOIN% %WHERE% %LIMIT% %LOCK%%COMMENT%'; + protected $updateSql = 'UPDATE %TABLE% SET %SET% FROM %TABLE% %JOIN% %WHERE% %LIMIT% %LOCK%%COMMENT%'; protected $deleteSql = 'DELETE FROM %TABLE% %USING% %JOIN% %WHERE% %LIMIT% %LOCK%%COMMENT%'; /** diff --git a/core/library/think/log/driver/File.php b/core/library/think/log/driver/File.php index a540aac0..bbc9b76e 100644 --- a/core/library/think/log/driver/File.php +++ b/core/library/think/log/driver/File.php @@ -54,12 +54,12 @@ class File } else { $current_uri = "cmd:" . implode(' ', $_SERVER['argv']); } - $runtime = number_format(microtime(true), 8, '.', '') - THINK_START_TIME; - $reqs = number_format(1 / $runtime, 2); - $time_str = " [运行时间:{$runtime}s] [吞吐率:{$reqs}req/s]"; + $runtime = (number_format(microtime(true), 8, '.', '') - THINK_START_TIME) ?: 0.00000001; + $reqs = number_format(1 / number_format($runtime, 8), 2); + $time_str = ' [运行时间:' . number_format($runtime, 6) . 's][吞吐率:' . $reqs . 'req/s]'; $memory_use = number_format((memory_get_usage() - THINK_START_MEM) / 1024, 2); - $memory_str = " [内存消耗:{$memory_use}kb]"; - $file_load = " [文件加载:" . count(get_included_files()) . "]"; + $memory_str = ' [内存消耗:' . $memory_use . 'kb]'; + $file_load = ' [文件加载:' . count(get_included_files()) . ']'; $info = '[ log ] ' . $current_uri . $time_str . $memory_str . $file_load . "\r\n"; foreach ($log as $type => $val) { diff --git a/core/library/think/log/driver/Sae.php b/core/library/think/log/driver/Sae.php deleted file mode 100644 index c593c09e..00000000 --- a/core/library/think/log/driver/Sae.php +++ /dev/null @@ -1,71 +0,0 @@ - ' c ', - ]; - - // 实例化并传入参数 - public function __construct(array $config = []) - { - $this->config = array_merge($this->config, $config); - } - - /** - * 日志写入接口 - * @access public - * @param array $log 日志信息 - * @return bool - */ - public function save(array $log = []) - { - static $is_debug = null; - $now = date($this->config['log_time_format']); - // 获取基本信息 - if (isset($_SERVER['HTTP_HOST'])) { - $current_uri = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; - } else { - $current_uri = "cmd:" . implode(' ', $_SERVER['argv']); - } - $runtime = number_format(microtime(true), 8, '.', '') - THINK_START_TIME; - $reqs = number_format(1 / $runtime, 2); - $time_str = " [运行时间:{$runtime}s] [吞吐率:{$reqs}req/s]"; - $memory_use = number_format((memory_get_usage() - THINK_START_MEM) / 1024, 2); - $memory_str = " [内存消耗:{$memory_use}kb]"; - $file_load = " [文件加载:" . count(get_included_files()) . "]"; - - $info = '[ log ] ' . $current_uri . $time_str . $memory_str . $file_load . "\r\n"; - foreach ($log as $type => $val) { - foreach ($val as $msg) { - if (!is_string($msg)) { - $msg = var_export($msg, true); - } - $info .= '[ ' . $type . ' ] ' . $msg . "\r\n"; - } - } - - $logstr = "[{$now}] {$_SERVER['SERVER_ADDR']} {$_SERVER['REMOTE_ADDR']} {$_SERVER['REQUEST_URI']}\r\n{$info}\r\n"; - if (is_null($is_debug)) { - $appSettings = []; - preg_replace_callback('@(\w+)\=([^;]*)@', function ($match) use (&$appSettings) { - $appSettings[$match['1']] = $match['2']; - }, $_SERVER['HTTP_APPCOOKIE']); - $is_debug = in_array($_SERVER['HTTP_APPVERSION'], explode(',', $appSettings['debug'])) ? true : false; - } - if ($is_debug) { - sae_set_display_errors(false); //记录日志不将日志打印出来 - } - sae_debug($logstr); - if ($is_debug) { - sae_set_display_errors(true); - } - return true; - } - -} diff --git a/core/library/think/debug/Socket.php b/core/library/think/log/driver/Socket.php similarity index 98% rename from core/library/think/debug/Socket.php rename to core/library/think/log/driver/Socket.php index 2f604ef9..facdf0e3 100644 --- a/core/library/think/debug/Socket.php +++ b/core/library/think/log/driver/Socket.php @@ -9,9 +9,7 @@ // | Author: luofei614 // +---------------------------------------------------------------------- -namespace think\debug; - -use think\Response; +namespace think\log\driver; /** * github: https://github.com/luofei614/SocketLog @@ -57,11 +55,10 @@ class Socket /** * 调试输出接口 * @access public - * @param Response $response Response对象 * @param array $log 日志信息 * @return bool */ - public function output(Response $response, array $log = []) + public function save(array $log = []) { if (!$this->check()) { return false; diff --git a/core/library/think/paginator/Collection.php b/core/library/think/paginator/Collection.php index 64fbb93b..ddea7d5a 100644 --- a/core/library/think/paginator/Collection.php +++ b/core/library/think/paginator/Collection.php @@ -51,7 +51,7 @@ class Collection extends \think\Collection return $this->paginator; } - public function toArray() + public function toArray($allow = []) { if ($this->paginator) { try { @@ -64,10 +64,10 @@ class Collection extends \think\Collection 'total' => $total, 'per_page' => $this->listRows(), 'current_page' => $this->currentPage(), - 'data' => parent::toArray() + 'data' => parent::toArray($allow) ]; } else { - return parent::toArray(); + return parent::toArray($allow); } } diff --git a/core/library/think/paginator/driver/Bootstrap.php b/core/library/think/paginator/driver/Bootstrap.php index be65ecfc..87e1fe48 100644 --- a/core/library/think/paginator/driver/Bootstrap.php +++ b/core/library/think/paginator/driver/Bootstrap.php @@ -66,23 +66,23 @@ class Bootstrap extends Paginator 'last' => null ]; - $length = 3; + $side = 3; + $window = $side * 2; - if ($this->lastPage < $length * 4) { + if ($this->lastPage < $window + 6) { $block['first'] = $this->getUrlRange(1, $this->lastPage); - } elseif ($this->currentPage <= $length * 2) { - $block['first'] = $this->getUrlRange(1, $length * 2 + 2); + } elseif ($this->currentPage <= $window) { + $block['first'] = $this->getUrlRange(1, $window + 2); $block['last'] = $this->getUrlRange($this->lastPage - 1, $this->lastPage); - } elseif ($this->currentPage > ($this->lastPage - $length * 2)) { + } elseif ($this->currentPage > ($this->lastPage - $window)) { $block['first'] = $this->getUrlRange(1, 2); - $block['last'] = $this->getUrlRange($this->lastPage - $length * 2 + 2, $this->lastPage); + $block['last'] = $this->getUrlRange($this->lastPage - ($window + 2), $this->lastPage); } else { $block['first'] = $this->getUrlRange(1, 2); - $block['slider'] = $this->getUrlRange($this->currentPage - $length, $this->currentPage + $length); + $block['slider'] = $this->getUrlRange($this->currentPage - $side, $this->currentPage + $side); $block['last'] = $this->getUrlRange($this->lastPage - 1, $this->lastPage); } - $html = ''; if (is_array($block['first'])) { @@ -132,7 +132,7 @@ class Bootstrap extends Paginator * 生成一个可点击的按钮 * * @param string $url - * @param int $page + * @param int $page * @return string */ protected function getAvailablePageWrapper($url, $page) @@ -193,7 +193,7 @@ class Bootstrap extends Paginator * 生成普通页码按钮 * * @param string $url - * @param int $page + * @param int $page * @return string */ protected function getPageLinkWrapper($url, $page) diff --git a/core/library/think/template/driver/Sae.php b/core/library/think/template/driver/Sae.php deleted file mode 100644 index 9e5230a5..00000000 --- a/core/library/think/template/driver/Sae.php +++ /dev/null @@ -1,109 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\template\driver; - -use think\Exception; - -class Sae -{ - // mc 对象 - private $mc; - // 编译缓存内容 - private $contents = []; - - /** - * 架构函数 - * @access public - */ - public function __construct() - { - if (!function_exists('memcache_init')) { - throw new Exception('请在SAE平台上运行代码。'); - } - $this->mc = @memcache_init(); - if (!$this->mc) { - throw new Exception('您未开通Memcache服务,请在SAE管理平台初始化Memcache服务'); - } - } - - /** - * 写入编译缓存 - * @param string $cacheFile 缓存的文件名 - * @param string $content 缓存的内容 - * @return void|array - */ - public function write($cacheFile, $content) - { - // 添加写入时间 - $content = $_SERVER['REQUEST_TIME'] . $content; - if (!$this->mc->set($cacheFile, $content, MEMCACHE_COMPRESSED, 0)) { - throw new Exception('sae mc write error:' . $cacheFile); - } else { - $this->contents[$cacheFile] = $content; - return true; - } - } - - /** - * 读取编译编译 - * @param string $cacheFile 缓存的文件名 - * @param array $vars 变量数组 - * @return void - */ - public function read($cacheFile, $vars = []) - { - if (!empty($vars) && is_array($vars)) { - extract($vars, EXTR_OVERWRITE); - } - eval('?>' . $this->get($cacheFile, 'content')); - } - - /** - * 检查编译缓存是否有效 - * @param string $cacheFile 缓存的文件名 - * @param int $cacheTime 缓存时间 - * @return boolean - */ - public function check($cacheFile, $cacheTime) - { - $mtime = $this->get($cacheFile, 'mtime'); - if (0 != $cacheTime && $_SERVER['REQUEST_TIME'] > $mtime + $cacheTime) { - // 缓存是否在有效期 - return false; - } - return true; - } - - /** - * 读取文件信息 - * @access private - * @param string $filename 文件名 - * @param string $name 信息名 mtime或者content - * @return boolean - */ - private function get($filename, $name) - { - if (!isset($this->contents[$filename])) { - $this->contents[$filename] = $this->mc->get($filename); - } - $content = $this->contents[$filename]; - - if (false === $content) { - return false; - } - $info = array( - 'mtime' => substr($content, 0, 10), - 'content' => substr($content, 10), - ); - return $info[$name]; - } -} diff --git a/core/library/traits/controller/Jump.php b/core/library/traits/controller/Jump.php index 23c9bc0b..10f2c765 100644 --- a/core/library/traits/controller/Jump.php +++ b/core/library/traits/controller/Jump.php @@ -19,6 +19,7 @@ use think\exception\HttpResponseException; use think\Request; use think\Response; use think\response\Redirect; +use think\Url; use think\View as ViewTemplate; trait Jump @@ -39,11 +40,16 @@ trait Jump $code = $msg; $msg = ''; } + if (is_null($url) && isset($_SERVER["HTTP_REFERER"])) { + $url = $_SERVER["HTTP_REFERER"]; + } else { + $url = preg_match('/^(https?:|\/)/', $url) ? $url : Url::build($url); + } $result = [ 'code' => $code, 'msg' => $msg, 'data' => $data, - 'url' => is_null($url) && isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : $url, + 'url' => $url, 'wait' => $wait, ]; @@ -71,11 +77,16 @@ trait Jump $code = $msg; $msg = ''; } + if (is_null($url)) { + $url = 'javascript:history.back(-1);'; + } else { + $url = preg_match('/^(https?:|\/)/', $url) ? $url : Url::build($url); + } $result = [ 'code' => $code, 'msg' => $msg, 'data' => $data, - 'url' => is_null($url) ? 'javascript:history.back(-1);' : $url, + 'url' => $url, 'wait' => $wait, ]; @@ -104,7 +115,7 @@ trait Jump 'msg' => $msg, 'time' => $_SERVER['REQUEST_TIME'], 'data' => $data, - ]; + ]; $type = $type ?: $this->getResponseType(); return Response::create($result, $type); }
- - 备份名称 卷数 压缩
{$data.time|date='Ymd-His',###} {$data.part} {$data.compress}