parent
a03736399f
commit
fc631f51a8
@ -0,0 +1,6 @@
|
|||||||
|
<code_scheme name="Default" version="173">
|
||||||
|
<PHPCodeStyleSettings>
|
||||||
|
<option name="ALIGN_KEY_VALUE_PAIRS" value="true" />
|
||||||
|
<option name="ALIGN_ASSIGNMENTS" value="true" />
|
||||||
|
</PHPCodeStyleSettings>
|
||||||
|
</code_scheme>
|
||||||
@ -0,0 +1 @@
|
|||||||
|
deny from all
|
||||||
@ -0,0 +1,256 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\admin\controller\Base;
|
||||||
|
use \think\Db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员管理
|
||||||
|
* @author hardphp@163.com
|
||||||
|
*/
|
||||||
|
class Admin extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 列表
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
//搜索参数
|
||||||
|
$isEnabled = input('isEnabled', -1, 'intval');
|
||||||
|
$userName = input('userName', '', 'trim');
|
||||||
|
$phone = input('phone', '', 'trim');
|
||||||
|
$realName = input('realName', '', 'trim');
|
||||||
|
$startTime = input('startTime', '', 'strtotime');
|
||||||
|
$endTime = input('endTime', '', 'strtotime');
|
||||||
|
$order = input('order/a', 'a.id desc');
|
||||||
|
$page = input('page', 1, 'intval');
|
||||||
|
$psize = input('psize', 10, 'intval');
|
||||||
|
|
||||||
|
$lists = model('Admin', 'logic')->getLists($userName, $phone, $realName, $startTime, $endTime, $isEnabled, $order, $page, $psize);
|
||||||
|
$result['total'] = model('Admin', 'logic')->getTotal($userName, $phone, $realName, $startTime, $endTime, $isEnabled);
|
||||||
|
$result['data'] = $lists;
|
||||||
|
ajax_return_ok($result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取登录用户信息
|
||||||
|
public function getuser()
|
||||||
|
{
|
||||||
|
$user = $this->user;
|
||||||
|
$access = my_model('AuthRule', 'logic', 'admin')->getAuthByGroupIdToTree($user['groupId']);
|
||||||
|
$routers = [];
|
||||||
|
|
||||||
|
foreach ($access as $v) {
|
||||||
|
$temp = $this->getdata($v);
|
||||||
|
foreach ($v['children'] as $vo) {
|
||||||
|
$temp['children'][] = $this->getdata($vo);
|
||||||
|
}
|
||||||
|
$routers[] = $temp;
|
||||||
|
}
|
||||||
|
$user['access'] = $routers;
|
||||||
|
$group = my_model('AuthGroup', 'logic', 'admin')->getGroupById($user['groupId']);
|
||||||
|
$user['group'] = $group['title'];
|
||||||
|
ajax_return_ok($user);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getdata($data)
|
||||||
|
{
|
||||||
|
$temp = [];
|
||||||
|
$temp['path'] = $data['path'];
|
||||||
|
$temp['component'] = $data['component'];
|
||||||
|
$temp['name'] = $data['name'];
|
||||||
|
if ($data['hidden'] > -1) {
|
||||||
|
$temp['hidden'] = (boolean)$data['hidden'];
|
||||||
|
}
|
||||||
|
if ($data['alwaysShow'] > -1) {
|
||||||
|
$temp['alwaysShow'] = (boolean)$data['alwaysShow'];
|
||||||
|
}
|
||||||
|
if ($data['redirect']) {
|
||||||
|
$temp['redirect'] = $data['redirect'];
|
||||||
|
}
|
||||||
|
$temp['meta']['title'] = $data['title'];
|
||||||
|
$temp['meta']['icon'] = $data['icon'];
|
||||||
|
if ($data['noCache'] > -1) {
|
||||||
|
$temp['meta']['noCache'] = (boolean)$data['noCache'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** 详情
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getinfo()
|
||||||
|
{
|
||||||
|
$uid = input('id', '0', 'int');
|
||||||
|
if ($uid == 0) {
|
||||||
|
ajax_return_error('参数有误!');
|
||||||
|
}
|
||||||
|
$info = model('Admin', 'logic')->getAdminById($uid);
|
||||||
|
ajax_return_ok($info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存
|
||||||
|
*/
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
$id = input('id', '0', 'int');
|
||||||
|
//接收数据
|
||||||
|
$data = [
|
||||||
|
'groupId' => input('groupId', '', 'trim'),
|
||||||
|
'userName' => input('userName', '', 'trim'),
|
||||||
|
'realName' => input('realName', '', 'trim'),
|
||||||
|
'img' => input('img', '', 'trim'),
|
||||||
|
'phone' => input('phone', '', 'trim'),
|
||||||
|
'email' => input('email', '', 'trim'),
|
||||||
|
'password' => input('password', '', 'trim'),
|
||||||
|
'regTime' => input('regTime', 0, 'int'),
|
||||||
|
'isEnabled' => input('isEnabled', 0, 'int'),
|
||||||
|
];
|
||||||
|
$validate = validate('Admin');
|
||||||
|
$result = $validate->scene('save')->check($data);
|
||||||
|
if (!$result) {
|
||||||
|
$error = $validate->getError();
|
||||||
|
ajax_return_error($error);
|
||||||
|
}
|
||||||
|
$res = model('Admin', 'logic')->modify($id, $data);
|
||||||
|
if ($res == false) {
|
||||||
|
ajax_return_error('保存失败!');
|
||||||
|
} else {
|
||||||
|
ajax_return_ok(['id' => $res], '保存成功!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
*/
|
||||||
|
public function del()
|
||||||
|
{
|
||||||
|
$id = input('id', '0', 'int');
|
||||||
|
if ($id == 0) {
|
||||||
|
ajax_return_error('参数有误!');
|
||||||
|
} else {
|
||||||
|
if ($id == 1) {
|
||||||
|
ajax_return_error('该记录不能删除!');
|
||||||
|
}
|
||||||
|
if (model('Admin', 'logic')->del($id)) {
|
||||||
|
ajax_return_ok([], '删除成功!');
|
||||||
|
} else {
|
||||||
|
ajax_return_error('删除失败!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除
|
||||||
|
*/
|
||||||
|
public function delall()
|
||||||
|
{
|
||||||
|
$ids = input('ids', '', 'trim');
|
||||||
|
if (empty($ids)) {
|
||||||
|
ajax_return_error('参数有误!');
|
||||||
|
} else {
|
||||||
|
$ids = explode(',', $ids);
|
||||||
|
model('Admin', 'logic')->delall($ids);
|
||||||
|
ajax_return_ok([], '删除成功!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function change()
|
||||||
|
{
|
||||||
|
|
||||||
|
$val = input('val', '', 'int');
|
||||||
|
$field = input('field', '', 'trim');
|
||||||
|
$value = input('value', '', 'int');
|
||||||
|
if (empty($field)) {
|
||||||
|
ajax_return_error('参数有误!');
|
||||||
|
}
|
||||||
|
$res = model('Admin', 'logic')->change($val, $field, $value);
|
||||||
|
if ($res) {
|
||||||
|
ajax_return_ok([], '修改成功!');
|
||||||
|
} else {
|
||||||
|
ajax_return_error('修改失败!');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function changeall()
|
||||||
|
{
|
||||||
|
$val = input('val', '', 'trim');
|
||||||
|
$field = input('field', '', 'trim');
|
||||||
|
$value = input('value', '', 'int');
|
||||||
|
if (empty($val)) {
|
||||||
|
ajax_return_error('参数有误!');
|
||||||
|
}
|
||||||
|
if (empty($field)) {
|
||||||
|
ajax_return_error('参数有误!');
|
||||||
|
}
|
||||||
|
|
||||||
|
$ids = explode(',', $val);
|
||||||
|
foreach ($ids as $v) {
|
||||||
|
$res = model('Admin', 'logic')->change($v, $field, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
ajax_return_ok([], '修改成功!');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改密码
|
||||||
|
*/
|
||||||
|
public function setpwd()
|
||||||
|
{
|
||||||
|
//接收数据
|
||||||
|
$data = [
|
||||||
|
'oldPwd' => input('oldPwd', '', 'trim'),
|
||||||
|
'newPwd' => input('newPwd', '', 'trim'),
|
||||||
|
'newPwd2' => input('newPwd2', '', 'trim')
|
||||||
|
];
|
||||||
|
//验证输入数据合法性
|
||||||
|
$validate = validate('Password');
|
||||||
|
$result = $validate->check($data);
|
||||||
|
if (!$result) {
|
||||||
|
$error = $validate->getError();
|
||||||
|
ajax_return_error($error);
|
||||||
|
}
|
||||||
|
$res = model('Admin', 'logic')->setPwd($this->uid, $data['newPwd'], $data['oldPwd']);
|
||||||
|
if ($res) {
|
||||||
|
ajax_return_ok([], '修改成功!');
|
||||||
|
} else {
|
||||||
|
ajax_return_error('修改失败!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改个人资料
|
||||||
|
*/
|
||||||
|
public function modify()
|
||||||
|
{
|
||||||
|
$id = $this->uid;
|
||||||
|
//接收数据
|
||||||
|
$data = [
|
||||||
|
'realName' => input('realName', '', 'trim'),
|
||||||
|
'img' => input('img', '', 'trim'),
|
||||||
|
'phone' => input('phone', '', 'trim'),
|
||||||
|
'email' => input('email', '', 'trim'),
|
||||||
|
'password' => input('password', '', 'trim'),
|
||||||
|
];
|
||||||
|
$validate = validate('Admin');
|
||||||
|
$result = $validate->scene('modify')->check($data);
|
||||||
|
if (!$result) {
|
||||||
|
$error = $validate->getError();
|
||||||
|
ajax_return_error($error);
|
||||||
|
}
|
||||||
|
$res = model('Admin', 'logic')->modify($id, $data);
|
||||||
|
if ($res == false) {
|
||||||
|
ajax_return_error('保存失败!');
|
||||||
|
} else {
|
||||||
|
ajax_return_ok(['id' => $res], '保存成功!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\common\controller\Admin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统基类
|
||||||
|
* @author hardphp@163.com
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class Base extends Admin
|
||||||
|
{
|
||||||
|
public function _initialize()
|
||||||
|
{
|
||||||
|
parent::_initialize();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\admin\controller\Base;
|
||||||
|
use \think\Request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员管理
|
||||||
|
* @author hardphp@163.com
|
||||||
|
*/
|
||||||
|
class Error extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 列表
|
||||||
|
*/
|
||||||
|
public function _empty()
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\admin\controller\Base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统首页
|
||||||
|
* @author hardphp@163.com
|
||||||
|
*/
|
||||||
|
class Index extends Base
|
||||||
|
{
|
||||||
|
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\admin\controller\Base;
|
||||||
|
use \think\Db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员登录日志管理
|
||||||
|
* @author hardphp@163.com
|
||||||
|
*/
|
||||||
|
class Log extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 列表
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
//搜索参数
|
||||||
|
$userName = input('userName', '', 'trim');
|
||||||
|
$uid = input('uid', '', 'trim');
|
||||||
|
$loginIp = input('loginIp', '', 'trim');
|
||||||
|
$startTime = input('startTime', '', 'strtotime');
|
||||||
|
$endTime = input('endTime', '', 'strtotime');
|
||||||
|
$order = input('order/a', 'a.id desc');
|
||||||
|
$page = input('page', 1, 'intval');
|
||||||
|
$psize = input('psize', 10, 'intval');
|
||||||
|
|
||||||
|
$lists = model('LoginLog', 'logic')->getLists($uid, $userName, $loginIp, $startTime, $endTime, $order, $page, $psize);
|
||||||
|
$result['total'] = model('LoginLog', 'logic')->getTotal($uid, $userName, $loginIp, $startTime, $endTime);
|
||||||
|
$result['data'] = $lists;
|
||||||
|
ajax_return_ok($result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\common\controller\Api;
|
||||||
|
use app\common\util\AuthUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 后台登陆
|
||||||
|
* @author hardphp@163.com
|
||||||
|
*/
|
||||||
|
class Login extends Api
|
||||||
|
{
|
||||||
|
public function _initialize()
|
||||||
|
{
|
||||||
|
parent::_initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
//接收数据
|
||||||
|
$data = [
|
||||||
|
'userName' => input('userName', '', 'trim'),
|
||||||
|
'password' => input('password', '', 'trim'),
|
||||||
|
//'verify' => input('verify', '', 'trim')
|
||||||
|
];
|
||||||
|
$validate = validate('Admin');
|
||||||
|
$result = $validate->scene('login')->check($data);
|
||||||
|
if (!$result) {
|
||||||
|
$error = $validate->getError();
|
||||||
|
ajax_return_error($error);
|
||||||
|
}
|
||||||
|
// 登录验证并获取包含访问令牌的用户
|
||||||
|
$result = model('Admin', 'logic')->login($data['userName'], $data['password']);
|
||||||
|
ajax_return_ok($result, '登录成功');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,163 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\admin\controller\System;
|
||||||
|
use \think\Db;
|
||||||
|
use app\common\util\TreeUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色管理
|
||||||
|
* @author hardphp@163.com
|
||||||
|
*/
|
||||||
|
class Roles extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 列表
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
//搜索参数
|
||||||
|
$title = input('title', '', 'trim');
|
||||||
|
$status = input('status', -1, 'int');
|
||||||
|
$order = input('order/a', '');
|
||||||
|
$page = input('page', 1, 'intval');
|
||||||
|
$psize = input('psize', 10, 'intval');
|
||||||
|
|
||||||
|
$lists = model('AuthGroup', 'logic')->getLists($title, $status, $order, $page, $psize);
|
||||||
|
$result['total'] = model('AuthGroup', 'logic')->getTotal($title, $status);
|
||||||
|
$result['data'] = $lists;
|
||||||
|
ajax_return_ok($result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 列表,不分页
|
||||||
|
*/
|
||||||
|
public function getLists()
|
||||||
|
{
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
$lists = model('AuthGroup', 'logic')->getListsAll(1);
|
||||||
|
ajax_return_ok($lists);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** 详情
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getinfo()
|
||||||
|
{
|
||||||
|
$id = input('id', '0', 'int');
|
||||||
|
if ($id == 0) {
|
||||||
|
ajax_return_error('参数有误!');
|
||||||
|
}
|
||||||
|
$info = model('AuthGroup', 'logic')->getGroupById($id);
|
||||||
|
ajax_return_ok($info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存
|
||||||
|
*/
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
$id = input('id', '0', 'int');
|
||||||
|
//接收数据
|
||||||
|
$data = [
|
||||||
|
'title' => input('title', '', 'trim'),
|
||||||
|
'status' => input('status', 0, 'int'),
|
||||||
|
'rules' => input('rules/a', '')
|
||||||
|
];
|
||||||
|
$validate = validate('AuthGroup');
|
||||||
|
$result = $validate->check($data);
|
||||||
|
if (!$result) {
|
||||||
|
$error = $validate->getError();
|
||||||
|
ajax_return_error($error);
|
||||||
|
}
|
||||||
|
$data['rules'] = implode(',', $data['rules']);
|
||||||
|
$res = model('AuthGroup', 'logic')->modify($id, $data);
|
||||||
|
if ($res == false) {
|
||||||
|
ajax_return_error('保存失败!');
|
||||||
|
} else {
|
||||||
|
ajax_return_ok(['id' => $res], '保存成功!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
*/
|
||||||
|
public function del()
|
||||||
|
{
|
||||||
|
$id = input('id', '0', 'int');
|
||||||
|
if ($id == 0) {
|
||||||
|
ajax_return_error('参数有误!');
|
||||||
|
} else {
|
||||||
|
if ($id == 1) {
|
||||||
|
ajax_return_error('该记录不能删除!');
|
||||||
|
}
|
||||||
|
if (model('AuthGroup', 'logic')->del($id)) {
|
||||||
|
ajax_return_ok([], '删除成功!');
|
||||||
|
} else {
|
||||||
|
ajax_return_error('删除失败!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除
|
||||||
|
*/
|
||||||
|
public function delall()
|
||||||
|
{
|
||||||
|
$ids = input('ids', '', 'trim');
|
||||||
|
if (empty($ids)) {
|
||||||
|
ajax_return_error('参数有误!');
|
||||||
|
} else {
|
||||||
|
$ids = explode(',', $ids);
|
||||||
|
$ids = array_diff($ids, [1]);
|
||||||
|
model('AuthGroup', 'logic')->delall($ids);
|
||||||
|
ajax_return_ok([], '删除成功!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function change()
|
||||||
|
{
|
||||||
|
|
||||||
|
$val = input('val', '', 'int');
|
||||||
|
$field = input('field', '', 'trim');
|
||||||
|
$value = input('value', '', 'int');
|
||||||
|
if (empty($field)) {
|
||||||
|
ajax_return_error('参数有误!');
|
||||||
|
}
|
||||||
|
$res = model('AuthGroup', 'logic')->change($val, $field, $value);
|
||||||
|
if ($res) {
|
||||||
|
ajax_return_ok([], '修改成功!');
|
||||||
|
} else {
|
||||||
|
ajax_return_error('修改失败!');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function changeall()
|
||||||
|
{
|
||||||
|
$val = input('val', '', 'trim');
|
||||||
|
$field = input('field', '', 'trim');
|
||||||
|
$value = input('value', '', 'int');
|
||||||
|
if (empty($val)) {
|
||||||
|
ajax_return_error('参数有误!');
|
||||||
|
}
|
||||||
|
if (empty($field)) {
|
||||||
|
ajax_return_error('参数有误!');
|
||||||
|
}
|
||||||
|
|
||||||
|
$ids = explode(',', $val);
|
||||||
|
foreach ($ids as $v) {
|
||||||
|
$res = model('AuthGroup', 'logic')->change($v, $field, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
ajax_return_ok([], '修改成功!');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,178 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\admin\controller\Base;
|
||||||
|
use \think\Db;
|
||||||
|
use app\common\util\TreeUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 规则管理
|
||||||
|
* @author hardphp@163.com
|
||||||
|
*/
|
||||||
|
class Rules extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 列表
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
//搜索参数
|
||||||
|
$title = input('title', '', 'trim');
|
||||||
|
$status = input('status', -1, 'int');
|
||||||
|
$order = input('order/a', '');
|
||||||
|
$lists = model('AuthRule', 'logic')->getLists($title, $status, $order);
|
||||||
|
$result['data'] = $lists;
|
||||||
|
ajax_return_ok($result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 列表,不分页
|
||||||
|
*/
|
||||||
|
public function getLists()
|
||||||
|
{
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
$lists = model('AuthRule', 'logic')->getListsAll(1);
|
||||||
|
ajax_return_ok($lists);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** 详情
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getinfo()
|
||||||
|
{
|
||||||
|
$id = input('id', '0', 'int');
|
||||||
|
if ($id == 0) {
|
||||||
|
ajax_return_error('参数有误!');
|
||||||
|
}
|
||||||
|
$info = model('AuthRule', 'logic')->getRuleById($id);
|
||||||
|
ajax_return_ok($info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存
|
||||||
|
*/
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
$id = input('id', '0', 'int');
|
||||||
|
//接收数据
|
||||||
|
$data = [
|
||||||
|
'pid' => input('pid', 0, 'int'),
|
||||||
|
'title' => input('title', '', 'trim'),
|
||||||
|
'name' => input('name', '', 'trim'),
|
||||||
|
'icon' => input('icon', '', 'trim'),
|
||||||
|
'status' => input('status', 0, 'int'),
|
||||||
|
'path' => input('path', '', 'trim'),
|
||||||
|
'component' => input('component', '', 'trim'),
|
||||||
|
'redirect' => input('redirect', '', 'trim'),
|
||||||
|
'hidden' => input('hidden', 0, 'int'),
|
||||||
|
'noCache' => input('noCache', 1, 'int'),
|
||||||
|
'alwaysShow' => input('alwaysShow', 1, 'int')
|
||||||
|
];
|
||||||
|
$validate = validate('AuthRule');
|
||||||
|
$result = $validate->check($data);
|
||||||
|
if (!$result) {
|
||||||
|
$error = $validate->getError();
|
||||||
|
ajax_return_error($error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($id && $id == $data['pid']) {
|
||||||
|
ajax_return_error('上级不能选择自己!');
|
||||||
|
}
|
||||||
|
|
||||||
|
$res = model('AuthRule', 'logic')->modify($id, $data);
|
||||||
|
if ($res == false) {
|
||||||
|
ajax_return_error('保存失败!');
|
||||||
|
} else {
|
||||||
|
ajax_return_ok(['id'=>$res], '保存成功!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
*/
|
||||||
|
public function del()
|
||||||
|
{
|
||||||
|
$id = input('id', '0', 'int');
|
||||||
|
if ($id == 0) {
|
||||||
|
ajax_return_error('参数有误!');
|
||||||
|
} else {
|
||||||
|
if (model('AuthRule', 'logic')->del($id)) {
|
||||||
|
ajax_return_ok([], '删除成功!');
|
||||||
|
} else {
|
||||||
|
ajax_return_error('删除失败!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function change()
|
||||||
|
{
|
||||||
|
$val = input('val', '', 'int');
|
||||||
|
$field = input('field', '', 'trim');
|
||||||
|
$value = input('value', '', 'int');
|
||||||
|
if (empty($field)) {
|
||||||
|
ajax_return_error('参数有误!');
|
||||||
|
}
|
||||||
|
$res = model('AuthRule', 'logic')->change($val, $field, $value);
|
||||||
|
if ($res) {
|
||||||
|
ajax_return_ok([], '修改成功!');
|
||||||
|
} else {
|
||||||
|
ajax_return_error('修改失败!');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [sortColum 栏目排序]
|
||||||
|
* @return [type] [description]
|
||||||
|
*/
|
||||||
|
public function sort()
|
||||||
|
{
|
||||||
|
$listOrder = input('listOrder/a');
|
||||||
|
$res = model('AuthRule', 'logic')->sort($listOrder);
|
||||||
|
ajax_return_ok([], '排序成功!');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除
|
||||||
|
*/
|
||||||
|
public function delall()
|
||||||
|
{
|
||||||
|
$ids = input('ids', '', 'trim');
|
||||||
|
if (empty($ids)) {
|
||||||
|
ajax_return_error('参数有误!');
|
||||||
|
} else {
|
||||||
|
$ids = explode(',', $ids);
|
||||||
|
foreach ($ids as $v) {
|
||||||
|
$res = model('AuthRule', 'logic')->del($v);
|
||||||
|
}
|
||||||
|
ajax_return_ok([], '删除成功!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function changeall()
|
||||||
|
{
|
||||||
|
$val = input('val', '', 'trim');
|
||||||
|
$field = input('field', '', 'trim');
|
||||||
|
$value = input('value', '', 'int');
|
||||||
|
if (empty($val)) {
|
||||||
|
ajax_return_error('参数有误!');
|
||||||
|
}
|
||||||
|
if (empty($field)) {
|
||||||
|
ajax_return_error('参数有误!');
|
||||||
|
}
|
||||||
|
|
||||||
|
$ids = explode(',', $val);
|
||||||
|
foreach ($ids as $v) {
|
||||||
|
$res = model('AuthRule', 'logic')->change($v, $field, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
ajax_return_ok([], '修改成功!');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\common\util\UploadUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传
|
||||||
|
* @author hardphp@163.com
|
||||||
|
*/
|
||||||
|
class Upload extends \think\Controller
|
||||||
|
{
|
||||||
|
public function _initialize()
|
||||||
|
{
|
||||||
|
//跨域访问
|
||||||
|
if (config('app_debug') == true) {
|
||||||
|
header("Access-Control-Allow-Origin:*");
|
||||||
|
// 响应类型
|
||||||
|
header("Access-Control-Allow-Methods:GET,POST");
|
||||||
|
// 响应头设置
|
||||||
|
header("Access-Control-Allow-Headers:x-requested-with,content-type,x-access-token,x-access-appid");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//上传图片
|
||||||
|
public function upimage()
|
||||||
|
{
|
||||||
|
$filename = input('filename', '', 'trim');
|
||||||
|
if (empty($filename)) {
|
||||||
|
ajax_return_error('参数错误');
|
||||||
|
}
|
||||||
|
$url = uploadUtil::upimage($filename);
|
||||||
|
$url = request()->domain().$url;
|
||||||
|
ajax_return_ok(['url' => $url]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//上传文件
|
||||||
|
public function upfile()
|
||||||
|
{
|
||||||
|
$filename = input('filename', '', 'trim');
|
||||||
|
if (empty($filename)) {
|
||||||
|
ajax_return_error('参数错误');
|
||||||
|
}
|
||||||
|
$url = uploadUtil::upfile($filename);
|
||||||
|
$url = request()->domain().$url;
|
||||||
|
ajax_return_ok(['url' => $url]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,96 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\logic;
|
||||||
|
|
||||||
|
use \think\Model;
|
||||||
|
use app\common\CommonConstant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分组操作
|
||||||
|
*/
|
||||||
|
class AuthGroup extends Model
|
||||||
|
{
|
||||||
|
|
||||||
|
/** 获取分组列表
|
||||||
|
* @param $title
|
||||||
|
* @param $status
|
||||||
|
*/
|
||||||
|
public function getLists($title = '', $status = -1, $myorder = 'id desc', $page, $psize)
|
||||||
|
{
|
||||||
|
return my_model('AuthGroup', 'model', 'admin')->getLists($title, $status, $myorder, $page, $psize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有的列表,不分页
|
||||||
|
*/
|
||||||
|
public function getListsAll($status = -1, $myorder = 'a.id asc')
|
||||||
|
{
|
||||||
|
return my_model('AuthGroup', 'model', 'admin')->getListsAll($status, $myorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 通过ID获取信息
|
||||||
|
* @param $id
|
||||||
|
*/
|
||||||
|
public function getGroupById($id)
|
||||||
|
{
|
||||||
|
return my_model('AuthGroup', 'model', 'admin')->getGroupById($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取数量
|
||||||
|
*/
|
||||||
|
public function getTotal($title = '', $status = -1)
|
||||||
|
{
|
||||||
|
return my_model('AuthGroup', 'model', 'admin')->getTotal($title, $status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 保存
|
||||||
|
* @param $id
|
||||||
|
* @param $data
|
||||||
|
*/
|
||||||
|
public function modify($id, $data)
|
||||||
|
{
|
||||||
|
$data['updateTime'] = time();
|
||||||
|
if ($id) {
|
||||||
|
if (my_model('AuthGroup', 'model', 'admin')->check($data['title']) && $id != my_model('AuthGroup', 'model', 'admin')->check($data['title'])) {
|
||||||
|
ajax_return_error('该名称已存在!');
|
||||||
|
}
|
||||||
|
return my_model('AuthGroup', 'model', 'admin')->modify($id, $data);
|
||||||
|
} else {
|
||||||
|
if (my_model('AuthGroup', 'model', 'admin')->check($data['title'])) {
|
||||||
|
ajax_return_error('该名称已存在!');
|
||||||
|
}
|
||||||
|
return my_model('AuthGroup', 'model', 'admin')->add($data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除
|
||||||
|
* @param $id
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function del($id)
|
||||||
|
{
|
||||||
|
return my_model('AuthGroup', 'model', 'admin')->del($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 批量删除
|
||||||
|
* @param $ids
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function delall($ids)
|
||||||
|
{
|
||||||
|
return my_model('AuthGroup', 'model', 'admin')->delall($ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $val id 值
|
||||||
|
* @param $field 修改字段
|
||||||
|
* @param $value 字段值
|
||||||
|
*/
|
||||||
|
public function change($val, $field, $value)
|
||||||
|
{
|
||||||
|
$table = 'auth_group';
|
||||||
|
$id = 'id';
|
||||||
|
return my_model('Admin', 'model', 'admin')->change($table, $id, $val, $field, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,172 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\logic;
|
||||||
|
|
||||||
|
use \think\Model;
|
||||||
|
use app\common\CommonConstant;
|
||||||
|
use app\common\util\TreeUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 权限操作
|
||||||
|
*/
|
||||||
|
class AuthRule extends Model
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取权限组权限
|
||||||
|
* @param $groupId 分组id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAuthByGroupId($groupId)
|
||||||
|
{
|
||||||
|
$group = my_model('AuthGroup', 'model', 'admin')->getGroupById($groupId);
|
||||||
|
if ($group['status'] != 1 || empty($group['rules'])) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$ruleIds = explode(',', $group['rules']);
|
||||||
|
return my_model('AuthRule', 'model', 'admin')->getRuleByIds($ruleIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取权限组权限 格式化成树状
|
||||||
|
* @param $groupId 分组id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAuthByGroupIdToTree($groupId)
|
||||||
|
{
|
||||||
|
$group = my_model('AuthGroup', 'model', 'admin')->getGroupById($groupId);
|
||||||
|
if ($group['status'] != 1 || empty($group['rules'])) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$ruleIds = explode(',', $group['rules']);
|
||||||
|
$rules = my_model('AuthRule', 'model', 'admin')->getRuleByIds($ruleIds);
|
||||||
|
$rules = TreeUtil::listToTreeMulti($rules, 0, 'id', 'pid', 'children');
|
||||||
|
return $rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 根据名称获取权限
|
||||||
|
* @param $name 权限标识
|
||||||
|
* @param $groupId 分组id
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasAccessByName($name, $groupId)
|
||||||
|
{
|
||||||
|
$rule = my_model('AuthRule', 'model', 'admin')->getRuleByName($name);
|
||||||
|
if (empty($rule)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ($rule['status'] === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$group = my_model('AuthGroup', 'model', 'admin')->getGroupById($groupId);
|
||||||
|
if ($group['status'] != 1 || empty($group['rules'])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$myRuleIds = explode(',', $group['rules']);
|
||||||
|
if (in_array($rule['id'], $myRuleIds)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 通过ID获取信息
|
||||||
|
* @param $id
|
||||||
|
*/
|
||||||
|
public function getRuleById($id)
|
||||||
|
{
|
||||||
|
return my_model('AuthRule', 'model', 'admin')->getRuleById($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 通过标识获取信息
|
||||||
|
* @param $name
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getRuleByName($name)
|
||||||
|
{
|
||||||
|
return my_model('AuthRule', 'model', 'admin')->getRuleByName($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取列表
|
||||||
|
*/
|
||||||
|
public function getLists($title = '', $status = -1, $myorder = 'a.id desc')
|
||||||
|
{
|
||||||
|
return my_model('AuthRule', 'model', 'admin')->getLists($title, $status, $myorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有的列表,不分页
|
||||||
|
*/
|
||||||
|
public function getListsAll($status = -1, $myorder = 'a.id desc')
|
||||||
|
{
|
||||||
|
return my_model('AuthRule', 'model', 'admin')->getListsAll($status, $myorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取数量
|
||||||
|
*/
|
||||||
|
public function getTotal($title = '', $status = -1)
|
||||||
|
{
|
||||||
|
return my_model('AuthRule', 'model', 'admin')->getTotal($title, $status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 保存
|
||||||
|
* @param $id
|
||||||
|
* @param $data
|
||||||
|
*/
|
||||||
|
public function modify($id, $data)
|
||||||
|
{
|
||||||
|
$data['updateTime'] = time();
|
||||||
|
if ($id) {
|
||||||
|
if (my_model('AuthRule', 'model', 'admin')->check($data['name']) && $id != my_model('AuthRule', 'model', 'admin')->check($data['name'])) {
|
||||||
|
ajax_return_error('该标识已存在!');
|
||||||
|
}
|
||||||
|
return my_model('AuthRule', 'model', 'admin')->modify($id, $data);
|
||||||
|
} else {
|
||||||
|
if (my_model('AuthRule', 'model', 'admin')->check($data['name'])) {
|
||||||
|
ajax_return_error('该标识已存在!');
|
||||||
|
}
|
||||||
|
return my_model('AuthRule', 'model', 'admin')->add($data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除
|
||||||
|
* @param $id
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function del($id)
|
||||||
|
{
|
||||||
|
$info = my_model('AuthRule', 'model', 'admin')->getRuleByPid($id);
|
||||||
|
if ($info) {
|
||||||
|
ajax_return_error('请先删除下级!');
|
||||||
|
}
|
||||||
|
return my_model('AuthRule', 'model', 'admin')->del($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $val id 值
|
||||||
|
* @param $field 修改字段
|
||||||
|
* @param $value 字段值
|
||||||
|
*/
|
||||||
|
public function change($val, $field, $value)
|
||||||
|
{
|
||||||
|
$table = 'auth_rule';
|
||||||
|
$id = 'id';
|
||||||
|
return model('Admin')->change($table, $id, $val, $field, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sort($listOrder)
|
||||||
|
{
|
||||||
|
if (empty($listOrder)) {
|
||||||
|
ajax_return_error('没有数据!');
|
||||||
|
} else {
|
||||||
|
|
||||||
|
foreach ($listOrder as $id => $sorts) {
|
||||||
|
my_model('AuthRule', 'model', 'admin')->sort($id, $sorts);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\logic;
|
||||||
|
|
||||||
|
use \think\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员登陸日志操作
|
||||||
|
*/
|
||||||
|
class LoginLog extends Model
|
||||||
|
{
|
||||||
|
/**获取管理员登陸日志列表
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getLists($uid = '', $userName = '', $loginIp = '', $startTime = '', $endTime = '', $myorder = 'a.id desc', $page = 1, $psize = 10)
|
||||||
|
{
|
||||||
|
return my_model('LoginLog', 'model', 'admin')->getLists($uid, $userName, $loginIp, $startTime, $endTime, $myorder, $page, $psize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**获取管理员登陸日志数量
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getTotal($uid = '', $userName = '', $loginIp = '', $startTime = '', $endTime = '')
|
||||||
|
{
|
||||||
|
return my_model('LoginLog', 'model', 'admin')->getTotal($uid, $userName, $loginIp, $startTime, $endTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,165 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\model;
|
||||||
|
|
||||||
|
use \think\Model;
|
||||||
|
use \think\Db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员相关操作
|
||||||
|
*/
|
||||||
|
class Admin extends Model
|
||||||
|
{
|
||||||
|
/** 通过ID获取用户信息
|
||||||
|
* @param $uid 用户id
|
||||||
|
*/
|
||||||
|
public function getAdminById($uid)
|
||||||
|
{
|
||||||
|
$where = " a.id = " . $uid;
|
||||||
|
$user = Db::name('admin')->alias('a')->field('a.*,b.title')->join('auth_group b', 'a.groupId = b.id', 'left')->where($where)->find();
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 通过用户名获取用户信息
|
||||||
|
* @param $userName 用户名
|
||||||
|
*/
|
||||||
|
public function getAdminByName($userName)
|
||||||
|
{
|
||||||
|
$where = ['userName' => $userName];
|
||||||
|
$user = Db::name('admin')->alias('a')->field('a.*,b.title')->join('auth_group b', 'a.groupId = b.id', 'left')->where($where)->find();
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取管理员列表
|
||||||
|
*/
|
||||||
|
public function getLists($userName, $phone, $realName, $startTime, $endTime, $isEnabled, $myorder, $page, $psize)
|
||||||
|
{
|
||||||
|
$where = true;
|
||||||
|
if ($userName) {
|
||||||
|
$where .= " and a.userName like '%" . $userName . "%' ";
|
||||||
|
}
|
||||||
|
if ($phone) {
|
||||||
|
$where .= " and a.phone like '%" . $phone . "%' ";
|
||||||
|
}
|
||||||
|
if ($realName) {
|
||||||
|
$where .= " and a.realName like '%" . $realName . "%' ";
|
||||||
|
}
|
||||||
|
if ($startTime) {
|
||||||
|
$where .= " and a.loginTime >= " . $startTime . " ";
|
||||||
|
}
|
||||||
|
if ($endTime) {
|
||||||
|
$where .= " and a.loginTime <= " . $endTime . " ";
|
||||||
|
}
|
||||||
|
if ($isEnabled != -1) {
|
||||||
|
$where .= " and a.isEnabled = " . $isEnabled;
|
||||||
|
}
|
||||||
|
return Db::name('admin')->alias('a')->field('a.*,b.title')->join('auth_group b', 'a.groupId = b.id', 'left')->where($where)->order($myorder)->page($page, $psize)->select();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询管理员得数量
|
||||||
|
* @param $keyword
|
||||||
|
* @param $isEnabled
|
||||||
|
*/
|
||||||
|
public function getTotal($userName, $phone, $realName, $startTime, $endTime, $isEnabled)
|
||||||
|
{
|
||||||
|
$where = true;
|
||||||
|
if ($userName) {
|
||||||
|
$where .= " and a.userName like '%" . $userName . "%' ";
|
||||||
|
}
|
||||||
|
if ($phone) {
|
||||||
|
$where .= " and a.phone like '%" . $phone . "%' ";
|
||||||
|
}
|
||||||
|
if ($realName) {
|
||||||
|
$where .= " and a.realName like '%" . $realName . "%' ";
|
||||||
|
}
|
||||||
|
if ($startTime) {
|
||||||
|
$where .= " and a.loginTime >= " . $startTime . " ";
|
||||||
|
}
|
||||||
|
if ($endTime) {
|
||||||
|
$where .= " and a.loginTime <= " . $endTime . " ";
|
||||||
|
}
|
||||||
|
if ($isEnabled != -1) {
|
||||||
|
$where .= " and a.isEnabled = " . $isEnabled;
|
||||||
|
}
|
||||||
|
return Db::name('admin')->alias('a')->join('auth_group b', 'a.groupId = b.id', 'left')->where($where)->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新
|
||||||
|
* @param array $uid
|
||||||
|
* @param array $data
|
||||||
|
* @return $this|void
|
||||||
|
*/
|
||||||
|
public function modify($uid, $data)
|
||||||
|
{
|
||||||
|
return Db::name('admin')->where(['id' => $uid])->update($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**新增
|
||||||
|
* @param $data
|
||||||
|
*/
|
||||||
|
public function add($data)
|
||||||
|
{
|
||||||
|
return Db::name('admin')->insertGetId($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除
|
||||||
|
* @param $uid
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function del($uid)
|
||||||
|
{
|
||||||
|
return Db::name('admin')->where('id', $uid)->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 批量删除
|
||||||
|
* @param $uids
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function delall($uids)
|
||||||
|
{
|
||||||
|
return Db::name('admin')->where('id', 'in',$uids)->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [checkAdmin 检测用户名是否存在]
|
||||||
|
* @param [type] $name [description]
|
||||||
|
* @return [type] [description]
|
||||||
|
*/
|
||||||
|
public function checkAdmin($name)
|
||||||
|
{
|
||||||
|
$id = Db::name('admin')->where('userName', $name)->value('id');
|
||||||
|
if (empty($id)) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return $id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**获取密码
|
||||||
|
* @param $uid
|
||||||
|
*/
|
||||||
|
public function getPwd($uid)
|
||||||
|
{
|
||||||
|
return Db::name('admin')->where('id', $uid)->value('password');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**设置密码
|
||||||
|
* @param $uid
|
||||||
|
*/
|
||||||
|
public function setPwd($uid, $newPwd)
|
||||||
|
{
|
||||||
|
return Db::name('admin')->where('id', $uid)->setField('password', $newPwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $val id 值
|
||||||
|
* @param $field 修改字段
|
||||||
|
* @param $value 字段值
|
||||||
|
*/
|
||||||
|
public function change($table, $id, $val, $field, $value)
|
||||||
|
{
|
||||||
|
return Db::name($table)->where($id, $val)->update([$field => $value,'updateTime'=>time()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,117 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\model;
|
||||||
|
|
||||||
|
use \think\Model;
|
||||||
|
use \think\Db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户组相关操作
|
||||||
|
*/
|
||||||
|
class AuthGroup extends Model
|
||||||
|
{
|
||||||
|
/** 通过ID获取分组信息
|
||||||
|
* @param $groupId 用户组id
|
||||||
|
*/
|
||||||
|
public function getGroupById($groupId)
|
||||||
|
{
|
||||||
|
$where = ['id' => $groupId];
|
||||||
|
return Db::name('auth_group')->where($where)->find();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取分组列表
|
||||||
|
* @param $title
|
||||||
|
* @param $status
|
||||||
|
*/
|
||||||
|
public function getLists($title, $status, $myorder, $page, $psize)
|
||||||
|
{
|
||||||
|
$where = true;
|
||||||
|
if ($title) {
|
||||||
|
$where .= " and title like '%" . $title . "%' ";
|
||||||
|
}
|
||||||
|
if ($status != -1) {
|
||||||
|
$where .= " and status = " . $status;
|
||||||
|
}
|
||||||
|
return Db::name('auth_group')->where($where)->order($myorder)->page($page, $psize)->select();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有的列表,不分页
|
||||||
|
*/
|
||||||
|
public function getListsAll($status, $myorder)
|
||||||
|
{
|
||||||
|
$where = true;
|
||||||
|
if ($status != -1) {
|
||||||
|
$where .= " and a.status = " . $status;
|
||||||
|
}
|
||||||
|
return Db::name('auth_group')->alias('a')->field('a.*')->where($where)->order($myorder)->select();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取分组数量
|
||||||
|
* @param $title
|
||||||
|
* @param $status
|
||||||
|
*/
|
||||||
|
public function getTotal($title, $status)
|
||||||
|
{
|
||||||
|
$where = true;
|
||||||
|
if ($title) {
|
||||||
|
$where .= " and title like '%" . $title . "%' ";
|
||||||
|
}
|
||||||
|
if ($status != -1) {
|
||||||
|
$where .= " and status = " . $status;
|
||||||
|
}
|
||||||
|
return Db::name('auth_group')->where($where)->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新
|
||||||
|
* @param array $id
|
||||||
|
* @param array $data
|
||||||
|
* @return $this|void
|
||||||
|
*/
|
||||||
|
public function modify($id, $data)
|
||||||
|
{
|
||||||
|
return Db::name('auth_group')->where(['id' => $id])->update($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**新增
|
||||||
|
* @param $data
|
||||||
|
*/
|
||||||
|
public function add($data)
|
||||||
|
{
|
||||||
|
return Db::name('auth_group')->insertGetId($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除
|
||||||
|
* @param $id
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function del($id)
|
||||||
|
{
|
||||||
|
return Db::name('auth_group')->where('id', $id)->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 批量删除
|
||||||
|
* @param $ids
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function delall($ids)
|
||||||
|
{
|
||||||
|
return Db::name('auth_group')->where('id', 'in',$ids)->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [check 检测是否存在]
|
||||||
|
* @param [type] $name [description]
|
||||||
|
* @return [type] [description]
|
||||||
|
*/
|
||||||
|
public function check($name)
|
||||||
|
{
|
||||||
|
$id = Db::name('auth_group')->where('title', $name)->value('id');
|
||||||
|
if (empty($id)) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return $id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,142 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\model;
|
||||||
|
|
||||||
|
use \think\Model;
|
||||||
|
use \think\Db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户组权限相关操作
|
||||||
|
*/
|
||||||
|
class AuthRule extends Model
|
||||||
|
{
|
||||||
|
/** 通过ID获取权限信息
|
||||||
|
* @param $ruleId 权限id
|
||||||
|
*/
|
||||||
|
public function getRuleById($ruleId)
|
||||||
|
{
|
||||||
|
$where = ['id' => $ruleId];
|
||||||
|
return Db::name('auth_rule')->where($where)->find();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 通过PID获取权限信息
|
||||||
|
* @param $pid 权限pid
|
||||||
|
*/
|
||||||
|
public function getRuleByPid($pid)
|
||||||
|
{
|
||||||
|
$where = ['pid' => $pid];
|
||||||
|
return Db::name('auth_rule')->where($where)->find();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 权限id 数组
|
||||||
|
* @param $ruleIds
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public function getRuleByIds($ruleIds)
|
||||||
|
{
|
||||||
|
$where = ['id' => ['in', $ruleIds], 'status' => 1];
|
||||||
|
return Db::name('auth_rule')->where($where)->order('sorts', ' asc')->select();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 根据名称获取权限
|
||||||
|
* @param $name
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public function getRuleByName($name)
|
||||||
|
{
|
||||||
|
return Db::name('auth_rule')->where(['name' => $name])->find();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取列表
|
||||||
|
*/
|
||||||
|
public function getLists($title, $status, $myorder)
|
||||||
|
{
|
||||||
|
$where = true;
|
||||||
|
if ($title) {
|
||||||
|
$where .= " and a.title like '%" . $title . "%' ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($status != -1) {
|
||||||
|
$where .= " and a.status = " . $status;
|
||||||
|
}
|
||||||
|
return Db::name('auth_rule')->alias('a')->field('a.*')->where($where)->order($myorder)->select();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有的列表,不分页
|
||||||
|
*/
|
||||||
|
public function getListsAll($status, $myorder)
|
||||||
|
{
|
||||||
|
$where = true;
|
||||||
|
if ($status != -1) {
|
||||||
|
$where .= " and a.status = " . $status;
|
||||||
|
}
|
||||||
|
return Db::name('auth_rule')->alias('a')->field('a.*')->where($where)->order($myorder)->select();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取数量
|
||||||
|
*/
|
||||||
|
public function getTotal($title, $status)
|
||||||
|
{
|
||||||
|
$where = true;
|
||||||
|
if ($title) {
|
||||||
|
$where .= " and a.title like '%" . $title . "%' ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($status != -1) {
|
||||||
|
$where .= " and a.status = " . $status;
|
||||||
|
}
|
||||||
|
return Db::name('auth_rule')->alias('a')->where($where)->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新
|
||||||
|
* @param array $id
|
||||||
|
* @param array $data
|
||||||
|
* @return $this|void
|
||||||
|
*/
|
||||||
|
public function modify($id, $data)
|
||||||
|
{
|
||||||
|
return Db::name('auth_rule')->where(['id' => $id])->update($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**新增
|
||||||
|
* @param $data
|
||||||
|
*/
|
||||||
|
public function add($data)
|
||||||
|
{
|
||||||
|
return Db::name('auth_rule')->insertGetId($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除
|
||||||
|
* @param $id
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function del($id)
|
||||||
|
{
|
||||||
|
return Db::name('auth_rule')->where('id', $id)->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [check 检测是否存在]
|
||||||
|
* @param [type] $name [description]
|
||||||
|
* @return [type] [description]
|
||||||
|
*/
|
||||||
|
public function check($name)
|
||||||
|
{
|
||||||
|
$id = Db::name('auth_rule')->where('name', $name)->value('id');
|
||||||
|
if (empty($id)) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return $id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//排序
|
||||||
|
public function sort($id, $sorts)
|
||||||
|
{
|
||||||
|
return Db::name('auth_rule')->where('id', $id)->update(['sorts' => $sorts,'updateTime'=>time()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\model;
|
||||||
|
|
||||||
|
use \think\Model;
|
||||||
|
use \think\Db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员登陆日志
|
||||||
|
*/
|
||||||
|
class LoginLog extends Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取管理员登陸日志列表
|
||||||
|
*/
|
||||||
|
public function getLists($uid, $userName, $loginIp, $startTime, $endTime, $myorder, $page, $psize)
|
||||||
|
{
|
||||||
|
$where = true;
|
||||||
|
if ($uid) {
|
||||||
|
$where .= " and a.uid = " . $uid . " ";
|
||||||
|
}
|
||||||
|
if ($userName) {
|
||||||
|
$where .= " and a.userName like '%" . $userName . "%' ";
|
||||||
|
}
|
||||||
|
if ($loginIp) {
|
||||||
|
$where .= " and a.loginIp = '" . $loginIp . "' ";
|
||||||
|
}
|
||||||
|
if ($startTime) {
|
||||||
|
$where .= " and a.loginTime >= " . $startTime . " ";
|
||||||
|
}
|
||||||
|
if ($endTime) {
|
||||||
|
$where .= " and a.loginTime <= " . $endTime . " ";
|
||||||
|
}
|
||||||
|
return Db::name('login_log')->alias('a')->field('a.*')->where($where)->order($myorder)->page($page, $psize)->select();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询管理员登陸日志数量
|
||||||
|
* @param $keyword
|
||||||
|
* @param $isEnabled
|
||||||
|
*/
|
||||||
|
public function getTotal($uid, $userName, $loginIp, $startTime, $endTime)
|
||||||
|
{
|
||||||
|
$where = true;
|
||||||
|
if ($uid) {
|
||||||
|
$where .= " and a.uid = " . $uid . " ";
|
||||||
|
}
|
||||||
|
if ($userName) {
|
||||||
|
$where .= " and a.userName like '%" . $userName . "%' ";
|
||||||
|
}
|
||||||
|
if ($loginIp) {
|
||||||
|
$where .= " and a.loginIp = '" . $loginIp . "' ";
|
||||||
|
}
|
||||||
|
if ($startTime) {
|
||||||
|
$where .= " and a.loginTime >= " . $startTime . " ";
|
||||||
|
}
|
||||||
|
if ($endTime) {
|
||||||
|
$where .= " and a.loginTime <= " . $endTime . " ";
|
||||||
|
}
|
||||||
|
return Db::name('login_log')->alias('a')->where($where)->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 添加日志
|
||||||
|
* @param $data
|
||||||
|
*/
|
||||||
|
public function add($data)
|
||||||
|
{
|
||||||
|
return Db::name('login_log')->insertGetId($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\validate;
|
||||||
|
|
||||||
|
use \think\Validate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员
|
||||||
|
*/
|
||||||
|
class Admin extends Validate
|
||||||
|
{
|
||||||
|
//验证规则
|
||||||
|
protected $rule = [
|
||||||
|
'userName' => ['require', 'max' => '25', 'alpha'],
|
||||||
|
'password' => ['require'],
|
||||||
|
'groupId' => ['require', 'gt' => '0'],
|
||||||
|
'phone' => ['regex' => '/1[3458]{1}\d{9}$/'],
|
||||||
|
'email' => ['email'],
|
||||||
|
'verify' => ['require', 'captcha']
|
||||||
|
];
|
||||||
|
|
||||||
|
//提示信息
|
||||||
|
protected $message = [
|
||||||
|
'userName.require' => '账号必须',
|
||||||
|
'userName.max' => '账号最多不能超过25个字符',
|
||||||
|
'userName.alpha' => '账号必须是字母',
|
||||||
|
'password' => '密码必须',
|
||||||
|
'groupId' => '请选择角色',
|
||||||
|
'phone.regex' => '手机格式错误',
|
||||||
|
'email' => '邮箱格式错误',
|
||||||
|
'verify.require' => '验证码必须',
|
||||||
|
'verify.captcha' => '验证码错误'
|
||||||
|
];
|
||||||
|
|
||||||
|
//验证场景
|
||||||
|
protected $scene = [
|
||||||
|
'login' => ['userName', 'password'],
|
||||||
|
'save' => ['userName', 'groupId', 'phone', 'email'],
|
||||||
|
'modify' => ['phone', 'email'],
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\validate;
|
||||||
|
|
||||||
|
use \think\Validate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 规则
|
||||||
|
*/
|
||||||
|
class AuthGroup extends Validate
|
||||||
|
{
|
||||||
|
//验证规则
|
||||||
|
protected $rule = [
|
||||||
|
'title' => ['require'],
|
||||||
|
'rules' => ['require'],
|
||||||
|
];
|
||||||
|
|
||||||
|
//提示信息
|
||||||
|
protected $message = [
|
||||||
|
'title' => '名称必填',
|
||||||
|
'rules' => '选择权限',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\validate;
|
||||||
|
|
||||||
|
use \think\Validate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 规则
|
||||||
|
*/
|
||||||
|
class AuthRule extends Validate
|
||||||
|
{
|
||||||
|
//验证规则
|
||||||
|
protected $rule = [
|
||||||
|
'title' => ['require'],
|
||||||
|
'name' => ['require'],
|
||||||
|
'icon' => ['require'],
|
||||||
|
'path' => ['require'],
|
||||||
|
'component' => ['require'],
|
||||||
|
];
|
||||||
|
|
||||||
|
//提示信息
|
||||||
|
protected $message = [
|
||||||
|
'title' => '名称必填',
|
||||||
|
'name' => '标识必填',
|
||||||
|
'icon' => '图标必填',
|
||||||
|
'path' => '路径必填',
|
||||||
|
'component' => '组件必填',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\validate;
|
||||||
|
|
||||||
|
use \think\Validate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码修改
|
||||||
|
*/
|
||||||
|
class Password extends Validate
|
||||||
|
{
|
||||||
|
//验证规则
|
||||||
|
protected $rule = [
|
||||||
|
'oldPwd' => 'require',
|
||||||
|
'newPwd' => 'require',
|
||||||
|
'newPwd' => 'length:6,10',
|
||||||
|
'newPwd2' => 'require|confirm:newPwd',
|
||||||
|
];
|
||||||
|
|
||||||
|
//提示信息
|
||||||
|
protected $message = [
|
||||||
|
'oldPwd' => '原始密码必填',
|
||||||
|
'newPwd' => '新密码必填',
|
||||||
|
'newPwd.length' => '密码长度为6到10位',
|
||||||
|
'newPwd2' => '确认密码必填',
|
||||||
|
'newPwd2.confirm' => '新密码不相等',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\api\controller;
|
||||||
|
|
||||||
|
use app\common\controller\Api;
|
||||||
|
use app\common\util\AuthUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* api基类 -- 不验证用户登录
|
||||||
|
* @author hardphp@163.com
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class Base extends Api
|
||||||
|
{
|
||||||
|
public function _initialize()
|
||||||
|
{
|
||||||
|
parent::_initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\api\controller;
|
||||||
|
|
||||||
|
use app\common\util\AuthUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员基类 --验证登录
|
||||||
|
* @author hardphp@163.com
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class Center extends Base
|
||||||
|
{
|
||||||
|
//用户信息
|
||||||
|
protected $user = [];
|
||||||
|
protected $uid = 0;
|
||||||
|
|
||||||
|
public function _initialize()
|
||||||
|
{
|
||||||
|
parent::_initialize();
|
||||||
|
//身份验证
|
||||||
|
$result = AuthUtil::checkUser('user');
|
||||||
|
if ($result['status']) {
|
||||||
|
$this->user = $result['msg'];
|
||||||
|
$this->uid = $result['msg']['id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\api\controller;
|
||||||
|
/**
|
||||||
|
* 登陆
|
||||||
|
* @author hardphp@163.com
|
||||||
|
*/
|
||||||
|
class Login extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 手机号登录
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
//接收数据
|
||||||
|
$data = [
|
||||||
|
'phone' => input('phone', '', 'trim'),
|
||||||
|
'password' => input('password', '', 'trim')
|
||||||
|
];
|
||||||
|
$validate = my_validate('User', 'user');
|
||||||
|
$result = $validate->scene('login')->check($data);
|
||||||
|
if (!$result) {
|
||||||
|
$error = $validate->getError();
|
||||||
|
ajax_return_error($error);
|
||||||
|
}
|
||||||
|
// 登录验证并获取包含访问令牌的用户
|
||||||
|
$result = my_model('User', 'logic', 'user')->login($data['userName'], $data['password'], 1);
|
||||||
|
ajax_return_ok($result, '登录成功');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 账号登录
|
||||||
|
*/
|
||||||
|
public function index2()
|
||||||
|
{
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
//接收数据
|
||||||
|
$data = [
|
||||||
|
'userName' => input('userName', '', 'trim'),
|
||||||
|
'password' => input('password', '', 'trim'),
|
||||||
|
];
|
||||||
|
$validate = my_validate('User', 'user');
|
||||||
|
$result = $validate->scene('login2')->check($data);
|
||||||
|
if (!$result) {
|
||||||
|
$error = $validate->getError();
|
||||||
|
ajax_return_error($error);
|
||||||
|
}
|
||||||
|
// 登录验证并获取包含访问令牌的用户
|
||||||
|
$result = my_model('User', 'logic', 'user')->login($data['userName'], $data['password'], 2);
|
||||||
|
ajax_return_ok($result, '登录成功');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\api\controller;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册
|
||||||
|
* @author hardphp@163.com
|
||||||
|
* 2018-06-21
|
||||||
|
*/
|
||||||
|
class Register extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 手机号注册
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
//接收数据
|
||||||
|
$data = [
|
||||||
|
'phone' => input('phone', '', 'trim'),
|
||||||
|
'password' => input('password', '', 'trim'),
|
||||||
|
'code' => input('code', '', 'int'),
|
||||||
|
];
|
||||||
|
$validate = my_validate('User', 'user');
|
||||||
|
$result = $validate->scene('reg')->check($data);
|
||||||
|
if (!$result) {
|
||||||
|
$error = $validate->getError();
|
||||||
|
ajax_return_error($error);
|
||||||
|
}
|
||||||
|
//验证码
|
||||||
|
model('PhoneCode')->checkCode($data['phone'], $data['code'], 1);
|
||||||
|
//注册
|
||||||
|
$result = my_model('User', 'logic', 'user')->reg($data['phone'], $data['password'], 1);
|
||||||
|
ajax_return_ok([], '注册成功');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 账号注册
|
||||||
|
*/
|
||||||
|
public function index2()
|
||||||
|
{
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
//接收数据
|
||||||
|
$data = [
|
||||||
|
'userName' => input('userName', '', 'trim'),
|
||||||
|
'password' => input('password', '', 'trim'),
|
||||||
|
];
|
||||||
|
$validate = my_validate('User', 'user');
|
||||||
|
$result = $validate->scene('reg2')->check($data);
|
||||||
|
if (!$result) {
|
||||||
|
$error = $validate->getError();
|
||||||
|
ajax_return_error($error);
|
||||||
|
}
|
||||||
|
//验证码
|
||||||
|
model('PhoneCode')->checkCode($data['phone'], $data['code'], 1);
|
||||||
|
//注册
|
||||||
|
$result = my_model('User', 'logic', 'user')->reg($data['phone'], $data['password'], 2);
|
||||||
|
ajax_return_ok([], '注册成功');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: yunwuxin <448901948@qq.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
return [];
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\common\controller;
|
||||||
|
use app\common\controller\Api;
|
||||||
|
use app\common\util\AuthUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 后台接口基类
|
||||||
|
* @author hardphp@163.com
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class Admin extends Api
|
||||||
|
{
|
||||||
|
//用户信息
|
||||||
|
protected $user = [];
|
||||||
|
protected $uid = 0;
|
||||||
|
public function _initialize()
|
||||||
|
{
|
||||||
|
parent::_initialize();
|
||||||
|
//身份验证
|
||||||
|
$result = AuthUtil::checkUser('admin');
|
||||||
|
if ($result['status']) {
|
||||||
|
$this->user = $result['msg'];
|
||||||
|
$this->uid = $result['msg']['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
//权限验证
|
||||||
|
$module = strtolower(request()->module());
|
||||||
|
$controller = strtolower(request()->controller());
|
||||||
|
$action = strtolower(request()->action());
|
||||||
|
$nowUrl = $module . '/' . $controller . '/' . $action;
|
||||||
|
$access = my_model('AuthRule', 'logic', 'admin')->hasAccessByName($nowUrl, $result['msg']['groupId']);
|
||||||
|
if (!$access) {
|
||||||
|
ajax_return_error('无权访问!');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\common\controller;
|
||||||
|
|
||||||
|
use app\common\util\AuthUtil;
|
||||||
|
use Think\Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接口基类
|
||||||
|
* @author hardphp@163.com
|
||||||
|
*/
|
||||||
|
class Api extends \think\Controller
|
||||||
|
{
|
||||||
|
public function _initialize()
|
||||||
|
{
|
||||||
|
//跨域访问
|
||||||
|
if (config('app_debug') == true) {
|
||||||
|
header("Access-Control-Allow-Origin:*");
|
||||||
|
// 响应类型
|
||||||
|
header("Access-Control-Allow-Methods:GET,POST");
|
||||||
|
// 响应头设置
|
||||||
|
header("Access-Control-Allow-Headers:x-requested-with,content-type,x-access-token,x-access-appid");
|
||||||
|
}
|
||||||
|
//签名验证
|
||||||
|
AuthUtil::checkSign();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\common\model;
|
||||||
|
|
||||||
|
use \think\Model;
|
||||||
|
use \think\Db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用相关操作
|
||||||
|
*/
|
||||||
|
class App extends Model
|
||||||
|
{
|
||||||
|
/** 通过appID获取信息
|
||||||
|
* @param $appId
|
||||||
|
*/
|
||||||
|
public function getAppByAppId($appId)
|
||||||
|
{
|
||||||
|
$where = ['appId' => $appId];
|
||||||
|
$app = Db::name('app')->where($where)->find();
|
||||||
|
return $app;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新
|
||||||
|
* @param array $id
|
||||||
|
* @param array $data
|
||||||
|
* @return $this|void
|
||||||
|
*/
|
||||||
|
public function modify($id, $data)
|
||||||
|
{
|
||||||
|
return Db::name('app')->where(['id' => $id])->update($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,88 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\common\util;
|
||||||
|
|
||||||
|
use app\common\CommonConstant;
|
||||||
|
use think\File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传
|
||||||
|
* @author hardphp@163.com
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class UploadUtil
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传图片
|
||||||
|
*/
|
||||||
|
public static function upimage($name = '', $path = '')
|
||||||
|
{
|
||||||
|
|
||||||
|
if (empty($path)) {
|
||||||
|
// 框架应用根目录/uploads/ 目录下
|
||||||
|
$path = ROOT_PATH . 'public' . DS . 'uploads' . DS . 'images';
|
||||||
|
}
|
||||||
|
$files = request()->file($name);
|
||||||
|
$info = $files->validate(['size' => 1024 * 1024 * 5, 'ext' => ['gif', 'jpg', 'jpeg', 'png']])->move($path);
|
||||||
|
if ($info) {
|
||||||
|
// 成功上传后 获取上传信息
|
||||||
|
$url = '/uploads/images/' . $info->getSaveName();
|
||||||
|
$url = str_replace('\\', '/', $url);
|
||||||
|
return $url;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// 上传失败获取错误信息
|
||||||
|
my_exception($files->getError(), CommonConstant::e_system_upload_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传视频
|
||||||
|
*/
|
||||||
|
public static function upvideo($name = '', $path = '')
|
||||||
|
{
|
||||||
|
|
||||||
|
if (empty($path)) {
|
||||||
|
// 框架应用根目录/uploads/ 目录下
|
||||||
|
$path = ROOT_PATH . 'public' . DS . 'uploads' . DS . 'video';
|
||||||
|
}
|
||||||
|
$files = request()->file($name);
|
||||||
|
$info = $files->validate(['size' => 1024 * 1024 * 5, 'ext' => ['mp4']])->move($path);
|
||||||
|
if ($info) {
|
||||||
|
// 成功上传后 获取上传信息
|
||||||
|
$url = '/uploads/video/' . $info->getSaveName();
|
||||||
|
$url = str_replace('\\', '/', $url);
|
||||||
|
return $url;
|
||||||
|
} else {
|
||||||
|
// 上传失败获取错误信息
|
||||||
|
my_exception($files->getError(), CommonConstant::e_system_upload_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传文件
|
||||||
|
*/
|
||||||
|
public static function upfile($name = '', $path = '')
|
||||||
|
{
|
||||||
|
|
||||||
|
if (empty($path)) {
|
||||||
|
// 框架应用根目录/uploads/ 目录下
|
||||||
|
$path = ROOT_PATH . 'public' . DS . 'uploads' . DS . 'file';
|
||||||
|
}
|
||||||
|
$files = request()->file($name);
|
||||||
|
$info = $files->validate(['size' => 1024 * 1024 * 5, 'ext' => ['xls', 'xlsx']])->move($path);
|
||||||
|
if ($info) {
|
||||||
|
// 成功上传后 获取上传信息
|
||||||
|
$url = '/uploads/file/' . $info->getSaveName();
|
||||||
|
$url = str_replace('\\', '/', $url);
|
||||||
|
return $url;
|
||||||
|
} else {
|
||||||
|
// 上传失败获取错误信息
|
||||||
|
my_exception($files->getError(), CommonConstant::e_system_upload_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\common\validate;
|
||||||
|
|
||||||
|
use \think\Validate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用
|
||||||
|
*/
|
||||||
|
class App extends Validate
|
||||||
|
{
|
||||||
|
//验证规则
|
||||||
|
protected $rule = [
|
||||||
|
'appId' => ['require', 'length' => '18', 'alphaNum'],
|
||||||
|
'appSecret' => ['require', 'length' => '32', 'alphaNum'],
|
||||||
|
];
|
||||||
|
|
||||||
|
//提示信息
|
||||||
|
protected $message = [
|
||||||
|
'appId.require' => 'appId必须',
|
||||||
|
'appId.length' => 'appId不正确',
|
||||||
|
'appId.alphaNum' => 'appId不正确',
|
||||||
|
'appSecret.require' => 'appSecret必须',
|
||||||
|
'appSecret.length' => 'appSecret不正确',
|
||||||
|
'appSecret.alphaNum' => 'appSecret不正确',
|
||||||
|
];
|
||||||
|
|
||||||
|
//验证场景
|
||||||
|
protected $scene = [
|
||||||
|
'login' => ['appId', 'appSecret'],
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\index\controller;
|
||||||
|
|
||||||
|
class Index
|
||||||
|
{
|
||||||
|
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,89 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\index\controller;
|
||||||
|
use \think\Db;
|
||||||
|
/**
|
||||||
|
* 接口基类
|
||||||
|
* @author xiegaolei
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class Test
|
||||||
|
{
|
||||||
|
//生成签名
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$param = input("param.");
|
||||||
|
$appid = $param['appid'];
|
||||||
|
if(empty($appid)){
|
||||||
|
ajax_return_error('请填写appid');
|
||||||
|
}
|
||||||
|
unset($param['appid']);
|
||||||
|
unset($param['token']);
|
||||||
|
$signature = $this->getSgin($appid,$param);
|
||||||
|
ajax_return_ok(['sign' => $signature]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//请求数据
|
||||||
|
public function getdata()
|
||||||
|
{
|
||||||
|
$data = array();
|
||||||
|
$param = input("param.");
|
||||||
|
$url = $param['url'];
|
||||||
|
$api = $param['api'];
|
||||||
|
if (empty($url) || empty($api)) {
|
||||||
|
ajax_return_error('请填写接口地址');
|
||||||
|
} else {
|
||||||
|
$url = $url . $api;
|
||||||
|
}
|
||||||
|
|
||||||
|
$head = ["x-access-appid:".$param['appid'],"x-access-token:".$param['token']];
|
||||||
|
$data['signature'] = $param['signature'];
|
||||||
|
if (isset($param['data'])) {
|
||||||
|
foreach ($param['data']['key'] as $k => $v) {
|
||||||
|
if ($v) {
|
||||||
|
$data[$v] = $param['data']['value'][$k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($param['method']) {
|
||||||
|
case 'POST' :
|
||||||
|
$result = curl_post($url, $data,$head);
|
||||||
|
break;
|
||||||
|
case 'GET' :
|
||||||
|
$result = curl_get($url, $data,$head);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$result = '';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo $result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//生成签名
|
||||||
|
protected function getSgin($appid,$param)
|
||||||
|
{
|
||||||
|
$app = Db::name('app')->where(['appId' => $appid])->find();
|
||||||
|
if(empty($app)){
|
||||||
|
ajax_return_error('appid无效');
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = array();
|
||||||
|
if (isset($param['data'])) {
|
||||||
|
foreach ($param['data']['key'] as $k => $v) {
|
||||||
|
if ($v) {
|
||||||
|
$data[$v] = $param['data']['value'][$k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ksort($data);
|
||||||
|
$str = http_build_query($data);
|
||||||
|
$signature = md5(sha1($str) . $app['appSecret']);
|
||||||
|
return $signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,166 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\user\model;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
use think\Db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class user 会员管理
|
||||||
|
* xiegaolei
|
||||||
|
* @package app\user\model
|
||||||
|
*/
|
||||||
|
class User extends Model
|
||||||
|
{
|
||||||
|
|
||||||
|
/** 通过ID获取信息
|
||||||
|
* @param $id
|
||||||
|
*/
|
||||||
|
public function getUserById($id)
|
||||||
|
{
|
||||||
|
$where = " a.isDel = 0 and a.id = " . $id;
|
||||||
|
return Db::name('user')->alias('a')->field('a.*')->where($where)->find();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 通过手机号获取信息
|
||||||
|
* @param $phone
|
||||||
|
*/
|
||||||
|
public function getUserByPhone($phone)
|
||||||
|
{
|
||||||
|
$where = " a.isDel = 0 and a.phone = " . $phone;
|
||||||
|
return Db::name('user')->alias('a')->field('a.*')->where($where)->find();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 通过用户名获取信息
|
||||||
|
* @param $name
|
||||||
|
*/
|
||||||
|
public function getUserByName($name)
|
||||||
|
{
|
||||||
|
$where = " a.isDel = 0 and a.userName = " . $name;
|
||||||
|
return Db::name('user')->alias('a')->field('a.*')->where($where)->find();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取列表
|
||||||
|
*/
|
||||||
|
public function getLists($userName, $nickName, $phone, $adzoneId, $realName, $openId, $startTime, $endTime, $isEnabled, $pid, $myorder, $page, $psize)
|
||||||
|
{
|
||||||
|
$where = 'a.isDel = 0';
|
||||||
|
if ($userName) {
|
||||||
|
$where .= " and a.userName = '" . $userName . "' ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($nickName != '') {
|
||||||
|
$where .= " and a.nickName = '" . $nickName . "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($adzoneId != '') {
|
||||||
|
$where .= " and a.adzoneId = '" . $adzoneId . "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($realName != '') {
|
||||||
|
$where .= " and a.realName = '" . $realName . "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($phone != '') {
|
||||||
|
$where .= " and a.phone = '" . $phone . "'";
|
||||||
|
}
|
||||||
|
if ($openId != '') {
|
||||||
|
$where .= " and a.openId = '" . $openId . "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($startTime) {
|
||||||
|
$where .= " and a.loginTime >= " . $startTime . " ";
|
||||||
|
}
|
||||||
|
if ($endTime) {
|
||||||
|
$where .= " and a.loginTime <= " . $endTime . " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($isEnabled != -1) {
|
||||||
|
$where .= " and a.isEnabled = " . $isEnabled;
|
||||||
|
}
|
||||||
|
if ($pid != '') {
|
||||||
|
$where .= " and (a.pid = " . $pid . " or a.pid2 = " . $pid . ")";
|
||||||
|
}
|
||||||
|
return Db::name('user')->alias('a')->field('a.*')->where($where)->order($myorder)->page($page, $psize)->select();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取数量
|
||||||
|
*/
|
||||||
|
public function getTotal($userName, $nickName, $phone, $adzoneId, $realName, $openId, $startTime, $endTime, $isEnabled, $pid)
|
||||||
|
{
|
||||||
|
$where = 'a.isDel = 0';
|
||||||
|
if ($userName) {
|
||||||
|
$where .= " and a.userName = '" . $userName . "' ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($nickName != '') {
|
||||||
|
$where .= " and a.nickName = '" . $nickName . "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($adzoneId != '') {
|
||||||
|
$where .= " and a.adzoneId = '" . $adzoneId . "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($realName != '') {
|
||||||
|
$where .= " and a.realName = '" . $realName . "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($phone != '') {
|
||||||
|
$where .= " and a.phone = '" . $phone . "'";
|
||||||
|
}
|
||||||
|
if ($openId != '') {
|
||||||
|
$where .= " and a.openId = '" . $openId . "'";
|
||||||
|
}
|
||||||
|
if ($startTime) {
|
||||||
|
$where .= " and a.loginTime >= " . $startTime . " ";
|
||||||
|
}
|
||||||
|
if ($endTime) {
|
||||||
|
$where .= " and a.loginTime <= " . $endTime . " ";
|
||||||
|
}
|
||||||
|
if ($isEnabled != -1) {
|
||||||
|
$where .= " and a.isEnabled = " . $isEnabled;
|
||||||
|
}
|
||||||
|
if ($pid != '') {
|
||||||
|
$where .= " and (a.pid = " . $pid . " or a.pid2 = " . $pid . ")";
|
||||||
|
}
|
||||||
|
return Db::name('user')->alias('a')->field('a.*')->where($where)->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [check 检测是否存在]
|
||||||
|
* @param [type] $orderNum
|
||||||
|
* @return [type]
|
||||||
|
*/
|
||||||
|
public function check($phone)
|
||||||
|
{
|
||||||
|
$id = Db::name('user')->where(['phone' => $phone, 'isDel' => 0])->value('id');
|
||||||
|
if (empty($id)) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return $id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**新增
|
||||||
|
* @param $data
|
||||||
|
*/
|
||||||
|
public function add($data)
|
||||||
|
{
|
||||||
|
return Db::name('user')->insertGetId($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新
|
||||||
|
* @param array $id
|
||||||
|
* @param array $data
|
||||||
|
* @return $this|void
|
||||||
|
*/
|
||||||
|
public function modify($id, $data)
|
||||||
|
{
|
||||||
|
return Db::name('user')->where(['id' => $id])->update($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\user\validate;
|
||||||
|
|
||||||
|
use \think\Validate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户校验
|
||||||
|
*/
|
||||||
|
class User extends Validate
|
||||||
|
{
|
||||||
|
//验证规则
|
||||||
|
protected $rule = [
|
||||||
|
'userName' => ['require', 'length' => '6,20', 'alphaNum'],
|
||||||
|
'realName' => ['require'],
|
||||||
|
'phone' => ['regex' => '/1[3458]{1}\d{9}$/'],
|
||||||
|
'password' => ['require', 'length' => '6,20', 'alphaNum'],
|
||||||
|
'code' => ['require', 'integer'],
|
||||||
|
];
|
||||||
|
|
||||||
|
//提示信息
|
||||||
|
protected $message = [
|
||||||
|
'userName.require' => '账号必须',
|
||||||
|
'userName.length' => '账号长度6-20位',
|
||||||
|
'userName.alphaNum' => '账号只能包含字母和数字',
|
||||||
|
'realName.require' => '姓名必须',
|
||||||
|
'phone.regex' => '手机格式错误',
|
||||||
|
'password.require' => '密码必须',
|
||||||
|
'password.length' => '密码长度6-20位',
|
||||||
|
'password.alphaNum' => '密码不正确',
|
||||||
|
'code.require' => '验证码必须',
|
||||||
|
'code.integer' => '验证码类型不正确'
|
||||||
|
];
|
||||||
|
|
||||||
|
//验证场景
|
||||||
|
protected $scene = [
|
||||||
|
'login' => ['phone', 'password'],
|
||||||
|
'login2' => ['userName', 'password'],
|
||||||
|
'reg' => ['phone', 'password', 'code'],
|
||||||
|
'reg2' => ['userName', 'password'],
|
||||||
|
'save' => ['phone']
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"name": "tp5-api",
|
||||||
|
"description": "前后端完全分离--服务端基于thinkphp5+mysql 接口解决方案",
|
||||||
|
"keywords": [
|
||||||
|
"thinkphp5",
|
||||||
|
"mysql"
|
||||||
|
],
|
||||||
|
"homepage": "http://www.hardphp.com",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "hardphp",
|
||||||
|
"email": "hardphp@163.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"repositories": {
|
||||||
|
"packagist": {
|
||||||
|
"type": "composer",
|
||||||
|
"url": "https://packagist.phpcomposer.com"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.4.0",
|
||||||
|
"topthink/framework": "5.0.24",
|
||||||
|
"topthink/think-image": "^1.0",
|
||||||
|
"topthink/think-captcha": "^1.0",
|
||||||
|
"topthink/think-mongo": "^1.0",
|
||||||
|
"topthink/think-migration": "^1.0",
|
||||||
|
"topthink/think-angular": "^1.0",
|
||||||
|
"topthink/think-sae": "^1.0",
|
||||||
|
"topthink/think-worker": "^1.0",
|
||||||
|
"topthink/think-queue": "^1.0",
|
||||||
|
"topthink/think-testing": "^1.0",
|
||||||
|
"firebase/php-jwt": "^4.0",
|
||||||
|
"phpmailer/phpmailer": "~5.2",
|
||||||
|
"phpoffice/phpexcel": "~1.8.1",
|
||||||
|
"jpush/jpush": "v3.5.*",
|
||||||
|
"jaeger/querylist": "^3.1",
|
||||||
|
"jaeger/querylist-ext-request":"^1.0",
|
||||||
|
"jaeger/querylist-ext-multi":"^1.0",
|
||||||
|
"jaeger/querylist-ext-login":"^1.0",
|
||||||
|
"jaeger/querylist-ext-dimage": "^1.1",
|
||||||
|
"overtrue/wechat": "~3.1"
|
||||||
|
},
|
||||||
|
"extra": {
|
||||||
|
"think-path": "thinkphp"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"preferred-install": "dist"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
return [
|
||||||
|
// 数据库类型
|
||||||
|
'type' => 'mysql',
|
||||||
|
// 服务器地址
|
||||||
|
'hostname' => '127.0.0.1',
|
||||||
|
// 数据库名
|
||||||
|
'database' => '',
|
||||||
|
// 用户名
|
||||||
|
'username' => 'root',
|
||||||
|
// 密码
|
||||||
|
'password' => '',
|
||||||
|
// 端口
|
||||||
|
'hostport' => '',
|
||||||
|
// 连接dsn
|
||||||
|
'dsn' => '',
|
||||||
|
// 数据库连接参数
|
||||||
|
'params' => [],
|
||||||
|
// 数据库编码默认采用utf8
|
||||||
|
'charset' => 'utf8',
|
||||||
|
// 数据库表前缀
|
||||||
|
'prefix' => 'tp_',
|
||||||
|
// 数据库调试模式
|
||||||
|
'debug' => true,
|
||||||
|
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
|
||||||
|
'deploy' => 0,
|
||||||
|
// 数据库读写是否分离 主从式有效
|
||||||
|
'rw_separate' => false,
|
||||||
|
// 读写分离后 主服务器数量
|
||||||
|
'master_num' => 1,
|
||||||
|
// 指定从服务器序号
|
||||||
|
'slave_no' => '',
|
||||||
|
// 是否严格检查字段是否存在
|
||||||
|
'fields_strict' => true,
|
||||||
|
// 数据集返回类型
|
||||||
|
'resultset_type' => 'array',
|
||||||
|
// 自动写入时间戳字段
|
||||||
|
'auto_timestamp' => false,
|
||||||
|
// 时间字段取出后的默认时间格式
|
||||||
|
'datetime_format' => 'Y-m-d H:i:s',
|
||||||
|
// 是否需要进行SQL性能分析
|
||||||
|
'sql_explain' => false,
|
||||||
|
// Builder类
|
||||||
|
'builder' => '',
|
||||||
|
// Query类
|
||||||
|
'query' => '\\think\\db\\Query',
|
||||||
|
];
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: yunwuxin <448901948@qq.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
return [
|
||||||
|
'connector' => 'Sync'
|
||||||
|
];
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
return [
|
||||||
|
'__pattern__' => [
|
||||||
|
'name' => '\w+',
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
// 应用行为扩展定义文件
|
||||||
|
return [
|
||||||
|
// 应用初始化
|
||||||
|
'app_init' => [],
|
||||||
|
// 应用开始
|
||||||
|
'app_begin' => [],
|
||||||
|
// 模块初始化
|
||||||
|
'module_init' => [],
|
||||||
|
// 操作开始执行
|
||||||
|
'action_begin' => [],
|
||||||
|
// 视图内容过滤
|
||||||
|
'view_filter' => [],
|
||||||
|
// 日志写入
|
||||||
|
'log_write' => [],
|
||||||
|
// 应用结束
|
||||||
|
'app_end' => [],
|
||||||
|
//api鉴权
|
||||||
|
'api_auth' => [],
|
||||||
|
];
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
<IfModule mod_rewrite.c>
|
||||||
|
Options +FollowSymlinks -Multiviews
|
||||||
|
RewriteEngine On
|
||||||
|
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
|
||||||
|
</IfModule>
|
||||||
@ -0,0 +1,237 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
|
<title>api调试</title>
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css">
|
||||||
|
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
|
||||||
|
<style>
|
||||||
|
.row{
|
||||||
|
margin:0px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="container" style="margin:10px;width:95%">
|
||||||
|
|
||||||
|
<div class="pull-left" style="width:70%;border-right:2px green solid">
|
||||||
|
<form role="form" action="" id="form">
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-2">
|
||||||
|
<div class="form-group">
|
||||||
|
<select class="form-control" name="method" id="method">
|
||||||
|
<option value="POST">POST</option>
|
||||||
|
<option value="GET">GET</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" id="url" name="url" value="http://api.hardphp.com/index.php" autocomplete="off" placeholder="根地址">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" id="api" name="api" autocomplete="off" placeholder="接口地址">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="col-md-2">
|
||||||
|
<div class="form-group">
|
||||||
|
<button class="btn btn-success" id ="submit" type="submit" >提交数据</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 style="color:red">===========header参数==============</h3>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-2">
|
||||||
|
<h4>appid:</h4>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" name="appid" value="" autocomplete="off" placeholder="x-access-appid">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-2">
|
||||||
|
<h4>token:</h4>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" name="token" value="" autocomplete="off" placeholder="x-access-token">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 style="color:red">===========系统参数==============</h3>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-2">
|
||||||
|
<h4>签名signature:</h4>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" name="signature" autocomplete="off" placeholder="签名">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-2">
|
||||||
|
<button class="btn btn-primary addsign" type="button">生成签名</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 style="color:red">===========应用参数==============</h3>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-1">
|
||||||
|
<div class="form-group">
|
||||||
|
<button class="btn btn-danger add" type="button">添加参数</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-5">
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" name="data[key][]" autocomplete="off" placeholder="参数名">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-5">
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" name="data[value][]" autocomplete="off" placeholder="参数值">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-2">
|
||||||
|
<button class="btn btn-info delete" type="button">删除参数</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="pull-right" style="width:25%">
|
||||||
|
<div class="row">
|
||||||
|
<h3 style="color:red">===请求结果===</h3>
|
||||||
|
<pre id="result"></pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(function () {
|
||||||
|
|
||||||
|
$("#submit").click(function(){
|
||||||
|
|
||||||
|
$('#result').html('');
|
||||||
|
|
||||||
|
var url = $('#url').val();
|
||||||
|
var api = $('#api').val();
|
||||||
|
|
||||||
|
var method = $('#method').val();
|
||||||
|
if(url == '' || api == ''){
|
||||||
|
alert('请填写接口地址');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
type:method,
|
||||||
|
url:'http://api.hardphp.com/index.php/index/test/getdata',
|
||||||
|
data:$('#form').serialize(),
|
||||||
|
dataType:'json',
|
||||||
|
success:success
|
||||||
|
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
|
||||||
|
function success(data){
|
||||||
|
|
||||||
|
$('#result').html(JSON.stringify(data, null, 4));
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$('.addsign').click(function(){
|
||||||
|
|
||||||
|
$.post(
|
||||||
|
"http://api.hardphp.com/index.php/index/test/index",
|
||||||
|
$('#form').serialize(),
|
||||||
|
function(data){
|
||||||
|
if(data.status){
|
||||||
|
$('input[name="signature"]').val(data.data.sign);
|
||||||
|
}else{
|
||||||
|
alert(data.msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
} ,"json");
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$('.add').click(function(){
|
||||||
|
|
||||||
|
var html ='<div class="row">';
|
||||||
|
html +='<div class="col-md-5">';
|
||||||
|
html +='<div class="form-group">';
|
||||||
|
html +='<input type="text" class="form-control" name="data[key][]" autocomplete="off" placeholder="参数名">';
|
||||||
|
html +='</div>';
|
||||||
|
html +='</div>';
|
||||||
|
html +='<div class="col-md-5">';
|
||||||
|
html +='<div class="form-group">';
|
||||||
|
html +='<input type="text" class="form-control" name="data[value][]" autocomplete="off" placeholder="参数值">';
|
||||||
|
html +='</div>';
|
||||||
|
html +='</div>';
|
||||||
|
html +='<div class="col-md-2">';
|
||||||
|
html +='<button class="btn btn-info delete" type="button">删除参数</button>';
|
||||||
|
html +='</div>';
|
||||||
|
html +='</div>';
|
||||||
|
|
||||||
|
|
||||||
|
$('#form').append(html);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#form').on('click','.delete',function(){
|
||||||
|
|
||||||
|
$(this).closest('.row').remove();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
//表单提交
|
||||||
|
$(document)
|
||||||
|
.ajaxStart(function(){
|
||||||
|
$("button:submit").addClass("btn-success").removeClass('btn-success').attr("disabled", true);
|
||||||
|
})
|
||||||
|
.ajaxStop(function(){
|
||||||
|
$("button:submit").removeClass("btn-success").addClass("btn-success").attr("disabled", false);
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
header('Content-Type:application/json; charset=utf-8');
|
||||||
|
$result['msg'] = $message;
|
||||||
|
$result['status'] = 0;
|
||||||
|
$result['code'] = $code;
|
||||||
|
exit(json_encode($result));
|
||||||
|
?>
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
// [ 应用入口文件 ]
|
||||||
|
// 定义应用目录
|
||||||
|
define('APP_PATH', __DIR__ . '/../application/');
|
||||||
|
|
||||||
|
//配置目录
|
||||||
|
define('CONF_PATH', __DIR__.'/../config/');
|
||||||
|
|
||||||
|
// 加载框架引导文件
|
||||||
|
require __DIR__ . '/../thinkphp/start.php';
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
User-agent: *
|
||||||
|
Disallow:
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
/composer.lock
|
||||||
|
/vendor
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
@ -0,0 +1 @@
|
|||||||
|
deny from all
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
sudo: false
|
||||||
|
|
||||||
|
language: php
|
||||||
|
|
||||||
|
services:
|
||||||
|
- memcached
|
||||||
|
- mongodb
|
||||||
|
- mysql
|
||||||
|
- postgresql
|
||||||
|
- redis-server
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
fast_finish: true
|
||||||
|
include:
|
||||||
|
- php: 5.4
|
||||||
|
- php: 5.5
|
||||||
|
- php: 5.6
|
||||||
|
- php: 7.0
|
||||||
|
- php: hhvm
|
||||||
|
allow_failures:
|
||||||
|
- php: hhvm
|
||||||
|
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $HOME/.composer/cache
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- composer self-update
|
||||||
|
- mysql -e "create database IF NOT EXISTS test;" -uroot
|
||||||
|
- psql -c 'DROP DATABASE IF EXISTS test;' -U postgres
|
||||||
|
- psql -c 'create database test;' -U postgres
|
||||||
|
|
||||||
|
install:
|
||||||
|
- ./tests/script/install.sh
|
||||||
|
|
||||||
|
script:
|
||||||
|
## LINT
|
||||||
|
- find . -path ./vendor -prune -o -type f -name \*.php -exec php -l {} \;
|
||||||
|
## PHP Copy/Paste Detector
|
||||||
|
- vendor/bin/phpcpd --verbose --exclude vendor ./ || true
|
||||||
|
## PHPLOC
|
||||||
|
- vendor/bin/phploc --exclude vendor ./
|
||||||
|
## PHPUNIT
|
||||||
|
- vendor/bin/phpunit --coverage-clover=coverage.xml --configuration=phpunit.xml
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
- bash <(curl -s https://codecov.io/bash)
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
define('THINK_VERSION', '5.0.24');
|
||||||
|
define('THINK_START_TIME', microtime(true));
|
||||||
|
define('THINK_START_MEM', memory_get_usage());
|
||||||
|
define('EXT', '.php');
|
||||||
|
define('DS', DIRECTORY_SEPARATOR);
|
||||||
|
defined('THINK_PATH') or define('THINK_PATH', __DIR__ . DS);
|
||||||
|
define('LIB_PATH', THINK_PATH . 'library' . DS);
|
||||||
|
define('CORE_PATH', LIB_PATH . 'think' . DS);
|
||||||
|
define('TRAIT_PATH', LIB_PATH . 'traits' . DS);
|
||||||
|
defined('APP_PATH') or define('APP_PATH', dirname($_SERVER['SCRIPT_FILENAME']) . DS);
|
||||||
|
defined('ROOT_PATH') or define('ROOT_PATH', dirname(realpath(APP_PATH)) . DS);
|
||||||
|
defined('EXTEND_PATH') or define('EXTEND_PATH', ROOT_PATH . 'extend' . DS);
|
||||||
|
defined('VENDOR_PATH') or define('VENDOR_PATH', ROOT_PATH . 'vendor' . DS);
|
||||||
|
defined('RUNTIME_PATH') or define('RUNTIME_PATH', ROOT_PATH . 'runtime' . DS);
|
||||||
|
defined('LOG_PATH') or define('LOG_PATH', RUNTIME_PATH . 'log' . DS);
|
||||||
|
defined('CACHE_PATH') or define('CACHE_PATH', RUNTIME_PATH . 'cache' . DS);
|
||||||
|
defined('TEMP_PATH') or define('TEMP_PATH', RUNTIME_PATH . 'temp' . DS);
|
||||||
|
defined('CONF_PATH') or define('CONF_PATH', APP_PATH); // 配置文件目录
|
||||||
|
defined('CONF_EXT') or define('CONF_EXT', EXT); // 配置文件后缀
|
||||||
|
defined('ENV_PREFIX') or define('ENV_PREFIX', 'PHP_'); // 环境变量的配置前缀
|
||||||
|
|
||||||
|
// 环境常量
|
||||||
|
define('IS_CLI', PHP_SAPI == 'cli' ? true : false);
|
||||||
|
define('IS_WIN', strpos(PHP_OS, 'WIN') !== false);
|
||||||
|
|
||||||
|
// 载入Loader类
|
||||||
|
require CORE_PATH . 'Loader.php';
|
||||||
|
|
||||||
|
// 加载环境变量配置文件
|
||||||
|
if (is_file(ROOT_PATH . '.env')) {
|
||||||
|
$env = parse_ini_file(ROOT_PATH . '.env', true);
|
||||||
|
|
||||||
|
foreach ($env as $key => $val) {
|
||||||
|
$name = ENV_PREFIX . strtoupper($key);
|
||||||
|
|
||||||
|
if (is_array($val)) {
|
||||||
|
foreach ($val as $k => $v) {
|
||||||
|
$item = $name . '_' . strtoupper($k);
|
||||||
|
putenv("$item=$v");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
putenv("$name=$val");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册自动加载
|
||||||
|
\think\Loader::register();
|
||||||
|
|
||||||
|
// 注册错误和异常处理机制
|
||||||
|
\think\Error::register();
|
||||||
|
|
||||||
|
// 加载惯例配置文件
|
||||||
|
\think\Config::set(include THINK_PATH . 'convention' . EXT);
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
comment:
|
||||||
|
layout: header, changes, diff
|
||||||
|
coverage:
|
||||||
|
ignore:
|
||||||
|
- base.php
|
||||||
|
- helper.php
|
||||||
|
- convention.php
|
||||||
|
- lang/zh-cn.php
|
||||||
|
- start.php
|
||||||
|
- console.php
|
||||||
|
status:
|
||||||
|
patch: false
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "topthink/framework",
|
||||||
|
"description": "the new thinkphp framework",
|
||||||
|
"type": "think-framework",
|
||||||
|
"keywords": [
|
||||||
|
"framework",
|
||||||
|
"thinkphp",
|
||||||
|
"ORM"
|
||||||
|
],
|
||||||
|
"homepage": "http://thinkphp.cn/",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "liu21st",
|
||||||
|
"email": "liu21st@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.4.0",
|
||||||
|
"topthink/think-installer": "~1.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "4.8.*",
|
||||||
|
"johnkary/phpunit-speedtrap": "^1.0",
|
||||||
|
"mikey179/vfsStream": "~1.6",
|
||||||
|
"phploc/phploc": "2.*",
|
||||||
|
"sebastian/phpcpd": "2.*",
|
||||||
|
"phpdocumentor/reflection-docblock": "^2.0"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"think\\": "library/think"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006-2017 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: yunwuxin <448901948@qq.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace think;
|
||||||
|
|
||||||
|
// ThinkPHP 引导文件
|
||||||
|
// 加载基础文件
|
||||||
|
require __DIR__ . '/base.php';
|
||||||
|
|
||||||
|
// 执行应用
|
||||||
|
App::initCommon();
|
||||||
|
Console::init();
|
||||||
@ -0,0 +1,235 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace think;
|
||||||
|
|
||||||
|
class Build
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 根据传入的 build 资料创建目录和文件
|
||||||
|
* @access public
|
||||||
|
* @param array $build build 列表
|
||||||
|
* @param string $namespace 应用类库命名空间
|
||||||
|
* @param bool $suffix 类库后缀
|
||||||
|
* @return void
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function run(array $build = [], $namespace = 'app', $suffix = false)
|
||||||
|
{
|
||||||
|
// 锁定
|
||||||
|
$lock = APP_PATH . 'build.lock';
|
||||||
|
|
||||||
|
// 如果锁定文件不可写(不存在)则进行处理,否则表示已经有程序在处理了
|
||||||
|
if (!is_writable($lock)) {
|
||||||
|
if (!touch($lock)) {
|
||||||
|
throw new Exception(
|
||||||
|
'应用目录[' . APP_PATH . ']不可写,目录无法自动生成!<BR>请手动生成项目目录~',
|
||||||
|
10006
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($build as $module => $list) {
|
||||||
|
if ('__dir__' == $module) {
|
||||||
|
// 创建目录列表
|
||||||
|
self::buildDir($list);
|
||||||
|
} elseif ('__file__' == $module) {
|
||||||
|
// 创建文件列表
|
||||||
|
self::buildFile($list);
|
||||||
|
} else {
|
||||||
|
// 创建模块
|
||||||
|
self::module($module, $list, $namespace, $suffix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解除锁定
|
||||||
|
unlink($lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建目录
|
||||||
|
* @access protected
|
||||||
|
* @param array $list 目录列表
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected static function buildDir($list)
|
||||||
|
{
|
||||||
|
foreach ($list as $dir) {
|
||||||
|
// 目录不存在则创建目录
|
||||||
|
!is_dir(APP_PATH . $dir) && mkdir(APP_PATH . $dir, 0755, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建文件
|
||||||
|
* @access protected
|
||||||
|
* @param array $list 文件列表
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected static function buildFile($list)
|
||||||
|
{
|
||||||
|
foreach ($list as $file) {
|
||||||
|
// 先创建目录
|
||||||
|
if (!is_dir(APP_PATH . dirname($file))) {
|
||||||
|
mkdir(APP_PATH . dirname($file), 0755, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 再创建文件
|
||||||
|
if (!is_file(APP_PATH . $file)) {
|
||||||
|
file_put_contents(
|
||||||
|
APP_PATH . $file,
|
||||||
|
'php' == pathinfo($file, PATHINFO_EXTENSION) ? "<?php\n" : ''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建模块
|
||||||
|
* @access public
|
||||||
|
* @param string $module 模块名
|
||||||
|
* @param array $list build 列表
|
||||||
|
* @param string $namespace 应用类库命名空间
|
||||||
|
* @param bool $suffix 类库后缀
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function module($module = '', $list = [], $namespace = 'app', $suffix = false)
|
||||||
|
{
|
||||||
|
$module = $module ?: '';
|
||||||
|
|
||||||
|
// 创建模块目录
|
||||||
|
!is_dir(APP_PATH . $module) && mkdir(APP_PATH . $module);
|
||||||
|
|
||||||
|
// 如果不是 runtime 目录则需要创建配置文件和公共文件、创建模块的默认页面
|
||||||
|
if (basename(RUNTIME_PATH) != $module) {
|
||||||
|
self::buildCommon($module);
|
||||||
|
self::buildHello($module, $namespace, $suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 未指定文件和目录,则创建默认的模块目录和文件
|
||||||
|
if (empty($list)) {
|
||||||
|
$list = [
|
||||||
|
'__file__' => ['config.php', 'common.php'],
|
||||||
|
'__dir__' => ['controller', 'model', 'view'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建子目录和文件
|
||||||
|
foreach ($list as $path => $file) {
|
||||||
|
$modulePath = APP_PATH . $module . DS;
|
||||||
|
|
||||||
|
if ('__dir__' == $path) {
|
||||||
|
// 生成子目录
|
||||||
|
foreach ($file as $dir) {
|
||||||
|
self::checkDirBuild($modulePath . $dir);
|
||||||
|
}
|
||||||
|
} elseif ('__file__' == $path) {
|
||||||
|
// 生成(空白)文件
|
||||||
|
foreach ($file as $name) {
|
||||||
|
if (!is_file($modulePath . $name)) {
|
||||||
|
file_put_contents(
|
||||||
|
$modulePath . $name,
|
||||||
|
'php' == pathinfo($name, PATHINFO_EXTENSION) ? "<?php\n" : ''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 生成相关 MVC 文件
|
||||||
|
foreach ($file as $val) {
|
||||||
|
$val = trim($val);
|
||||||
|
$filename = $modulePath . $path . DS . $val . ($suffix ? ucfirst($path) : '') . EXT;
|
||||||
|
$space = $namespace . '\\' . ($module ? $module . '\\' : '') . $path;
|
||||||
|
$class = $val . ($suffix ? ucfirst($path) : '');
|
||||||
|
|
||||||
|
switch ($path) {
|
||||||
|
case 'controller': // 控制器
|
||||||
|
$content = "<?php\nnamespace {$space};\n\nclass {$class}\n{\n\n}";
|
||||||
|
break;
|
||||||
|
case 'model': // 模型
|
||||||
|
$content = "<?php\nnamespace {$space};\n\nuse think\Model;\n\nclass {$class} extends Model\n{\n\n}";
|
||||||
|
break;
|
||||||
|
case 'view': // 视图
|
||||||
|
$filename = $modulePath . $path . DS . $val . '.html';
|
||||||
|
self::checkDirBuild(dirname($filename));
|
||||||
|
$content = '';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// 其他文件
|
||||||
|
$content = "<?php\nnamespace {$space};\n\nclass {$class}\n{\n\n}";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_file($filename)) {
|
||||||
|
file_put_contents($filename, $content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建模块的欢迎页面
|
||||||
|
* @access protected
|
||||||
|
* @param string $module 模块名
|
||||||
|
* @param string $namespace 应用类库命名空间
|
||||||
|
* @param bool $suffix 类库后缀
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected static function buildHello($module, $namespace, $suffix = false)
|
||||||
|
{
|
||||||
|
$filename = APP_PATH . ($module ? $module . DS : '') .
|
||||||
|
'controller' . DS . 'Index' .
|
||||||
|
($suffix ? 'Controller' : '') . EXT;
|
||||||
|
|
||||||
|
if (!is_file($filename)) {
|
||||||
|
$module = $module ? $module . '\\' : '';
|
||||||
|
$suffix = $suffix ? 'Controller' : '';
|
||||||
|
$content = str_replace(
|
||||||
|
['{$app}', '{$module}', '{layer}', '{$suffix}'],
|
||||||
|
[$namespace, $module, 'controller', $suffix],
|
||||||
|
file_get_contents(THINK_PATH . 'tpl' . DS . 'default_index.tpl')
|
||||||
|
);
|
||||||
|
|
||||||
|
self::checkDirBuild(dirname($filename));
|
||||||
|
file_put_contents($filename, $content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建模块的公共文件
|
||||||
|
* @access protected
|
||||||
|
* @param string $module 模块名
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected static function buildCommon($module)
|
||||||
|
{
|
||||||
|
$config = CONF_PATH . ($module ? $module . DS : '') . 'config.php';
|
||||||
|
|
||||||
|
self::checkDirBuild(dirname($config));
|
||||||
|
|
||||||
|
if (!is_file($config)) {
|
||||||
|
file_put_contents($config, "<?php\n//配置文件\nreturn [\n\n];");
|
||||||
|
}
|
||||||
|
|
||||||
|
$common = APP_PATH . ($module ? $module . DS : '') . 'common.php';
|
||||||
|
if (!is_file($common)) file_put_contents($common, "<?php\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建目录
|
||||||
|
* @access protected
|
||||||
|
* @param string $dirname 目录名称
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected static function checkDirBuild($dirname)
|
||||||
|
{
|
||||||
|
!is_dir($dirname) && mkdir($dirname, 0755, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,247 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace think;
|
||||||
|
|
||||||
|
use think\cache\Driver;
|
||||||
|
|
||||||
|
class Cache
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array 缓存的实例
|
||||||
|
*/
|
||||||
|
public static $instance = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int 缓存读取次数
|
||||||
|
*/
|
||||||
|
public static $readTimes = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int 缓存写入次数
|
||||||
|
*/
|
||||||
|
public static $writeTimes = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var object 操作句柄
|
||||||
|
*/
|
||||||
|
public static $handler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接缓存驱动
|
||||||
|
* @access public
|
||||||
|
* @param array $options 配置数组
|
||||||
|
* @param bool|string $name 缓存连接标识 true 强制重新连接
|
||||||
|
* @return Driver
|
||||||
|
*/
|
||||||
|
public static function connect(array $options = [], $name = false)
|
||||||
|
{
|
||||||
|
$type = !empty($options['type']) ? $options['type'] : 'File';
|
||||||
|
|
||||||
|
if (false === $name) {
|
||||||
|
$name = md5(serialize($options));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (true === $name || !isset(self::$instance[$name])) {
|
||||||
|
$class = false === strpos($type, '\\') ?
|
||||||
|
'\\think\\cache\\driver\\' . ucwords($type) :
|
||||||
|
$type;
|
||||||
|
|
||||||
|
// 记录初始化信息
|
||||||
|
App::$debug && Log::record('[ CACHE ] INIT ' . $type, 'info');
|
||||||
|
|
||||||
|
if (true === $name) {
|
||||||
|
return new $class($options);
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$instance[$name] = new $class($options);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$instance[$name];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动初始化缓存
|
||||||
|
* @access public
|
||||||
|
* @param array $options 配置数组
|
||||||
|
* @return Driver
|
||||||
|
*/
|
||||||
|
public static function init(array $options = [])
|
||||||
|
{
|
||||||
|
if (is_null(self::$handler)) {
|
||||||
|
if (empty($options) && 'complex' == Config::get('cache.type')) {
|
||||||
|
$default = Config::get('cache.default');
|
||||||
|
// 获取默认缓存配置,并连接
|
||||||
|
$options = Config::get('cache.' . $default['type']) ?: $default;
|
||||||
|
} elseif (empty($options)) {
|
||||||
|
$options = Config::get('cache');
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$handler = self::connect($options);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换缓存类型 需要配置 cache.type 为 complex
|
||||||
|
* @access public
|
||||||
|
* @param string $name 缓存标识
|
||||||
|
* @return Driver
|
||||||
|
*/
|
||||||
|
public static function store($name = '')
|
||||||
|
{
|
||||||
|
if ('' !== $name && 'complex' == Config::get('cache.type')) {
|
||||||
|
return self::connect(Config::get('cache.' . $name), strtolower($name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断缓存是否存在
|
||||||
|
* @access public
|
||||||
|
* @param string $name 缓存变量名
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function has($name)
|
||||||
|
{
|
||||||
|
self::$readTimes++;
|
||||||
|
|
||||||
|
return self::init()->has($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取缓存
|
||||||
|
* @access public
|
||||||
|
* @param string $name 缓存标识
|
||||||
|
* @param mixed $default 默认值
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public static function get($name, $default = false)
|
||||||
|
{
|
||||||
|
self::$readTimes++;
|
||||||
|
|
||||||
|
return self::init()->get($name, $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入缓存
|
||||||
|
* @access public
|
||||||
|
* @param string $name 缓存标识
|
||||||
|
* @param mixed $value 存储数据
|
||||||
|
* @param int|null $expire 有效时间 0为永久
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public static function set($name, $value, $expire = null)
|
||||||
|
{
|
||||||
|
self::$writeTimes++;
|
||||||
|
|
||||||
|
return self::init()->set($name, $value, $expire);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自增缓存(针对数值缓存)
|
||||||
|
* @access public
|
||||||
|
* @param string $name 缓存变量名
|
||||||
|
* @param int $step 步长
|
||||||
|
* @return false|int
|
||||||
|
*/
|
||||||
|
public static function inc($name, $step = 1)
|
||||||
|
{
|
||||||
|
self::$writeTimes++;
|
||||||
|
|
||||||
|
return self::init()->inc($name, $step);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自减缓存(针对数值缓存)
|
||||||
|
* @access public
|
||||||
|
* @param string $name 缓存变量名
|
||||||
|
* @param int $step 步长
|
||||||
|
* @return false|int
|
||||||
|
*/
|
||||||
|
public static function dec($name, $step = 1)
|
||||||
|
{
|
||||||
|
self::$writeTimes++;
|
||||||
|
|
||||||
|
return self::init()->dec($name, $step);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除缓存
|
||||||
|
* @access public
|
||||||
|
* @param string $name 缓存标识
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public static function rm($name)
|
||||||
|
{
|
||||||
|
self::$writeTimes++;
|
||||||
|
|
||||||
|
return self::init()->rm($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除缓存
|
||||||
|
* @access public
|
||||||
|
* @param string $tag 标签名
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public static function clear($tag = null)
|
||||||
|
{
|
||||||
|
self::$writeTimes++;
|
||||||
|
|
||||||
|
return self::init()->clear($tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取缓存并删除
|
||||||
|
* @access public
|
||||||
|
* @param string $name 缓存变量名
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public static function pull($name)
|
||||||
|
{
|
||||||
|
self::$readTimes++;
|
||||||
|
self::$writeTimes++;
|
||||||
|
|
||||||
|
return self::init()->pull($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 如果不存在则写入缓存
|
||||||
|
* @access public
|
||||||
|
* @param string $name 缓存变量名
|
||||||
|
* @param mixed $value 存储数据
|
||||||
|
* @param int $expire 有效时间 0为永久
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public static function remember($name, $value, $expire = null)
|
||||||
|
{
|
||||||
|
self::$readTimes++;
|
||||||
|
|
||||||
|
return self::init()->remember($name, $value, $expire);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存标签
|
||||||
|
* @access public
|
||||||
|
* @param string $name 标签名
|
||||||
|
* @param string|array $keys 缓存标识
|
||||||
|
* @param bool $overlay 是否覆盖
|
||||||
|
* @return Driver
|
||||||
|
*/
|
||||||
|
public static function tag($name, $keys = null, $overlay = false)
|
||||||
|
{
|
||||||
|
return self::init()->tag($name, $keys, $overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,467 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: zhangyajun <448901948@qq.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace think;
|
||||||
|
|
||||||
|
use ArrayAccess;
|
||||||
|
use ArrayIterator;
|
||||||
|
use Countable;
|
||||||
|
use IteratorAggregate;
|
||||||
|
use JsonSerializable;
|
||||||
|
|
||||||
|
class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array 数据
|
||||||
|
*/
|
||||||
|
protected $items = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collection constructor.
|
||||||
|
* @access public
|
||||||
|
* @param array $items 数据
|
||||||
|
*/
|
||||||
|
public function __construct($items = [])
|
||||||
|
{
|
||||||
|
$this->items = $this->convertToArray($items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建 Collection 实例
|
||||||
|
* @access public
|
||||||
|
* @param array $items 数据
|
||||||
|
* @return static
|
||||||
|
*/
|
||||||
|
public static function make($items = [])
|
||||||
|
{
|
||||||
|
return new static($items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断数据是否为空
|
||||||
|
* @access public
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isEmpty()
|
||||||
|
{
|
||||||
|
return empty($this->items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将数据转成数组
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function toArray()
|
||||||
|
{
|
||||||
|
return array_map(function ($value) {
|
||||||
|
return ($value instanceof Model || $value instanceof self) ?
|
||||||
|
$value->toArray() :
|
||||||
|
$value;
|
||||||
|
}, $this->items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取全部的数据
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function all()
|
||||||
|
{
|
||||||
|
return $this->items;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 交换数组中的键和值
|
||||||
|
* @access public
|
||||||
|
* @return static
|
||||||
|
*/
|
||||||
|
public function flip()
|
||||||
|
{
|
||||||
|
return new static(array_flip($this->items));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回数组中所有的键名组成的新 Collection 实例
|
||||||
|
* @access public
|
||||||
|
* @return static
|
||||||
|
*/
|
||||||
|
public function keys()
|
||||||
|
{
|
||||||
|
return new static(array_keys($this->items));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回数组中所有的值组成的新 Collection 实例
|
||||||
|
* @access public
|
||||||
|
* @return static
|
||||||
|
*/
|
||||||
|
public function values()
|
||||||
|
{
|
||||||
|
return new static(array_values($this->items));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 合并数组并返回一个新的 Collection 实例
|
||||||
|
* @access public
|
||||||
|
* @param mixed $items 新的数据
|
||||||
|
* @return static
|
||||||
|
*/
|
||||||
|
public function merge($items)
|
||||||
|
{
|
||||||
|
return new static(array_merge($this->items, $this->convertToArray($items)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 比较数组,返回差集生成的新 Collection 实例
|
||||||
|
* @access public
|
||||||
|
* @param mixed $items 做比较的数据
|
||||||
|
* @return static
|
||||||
|
*/
|
||||||
|
public function diff($items)
|
||||||
|
{
|
||||||
|
return new static(array_diff($this->items, $this->convertToArray($items)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 比较数组,返回交集组成的 Collection 新实例
|
||||||
|
* @access public
|
||||||
|
* @param mixed $items 比较数据
|
||||||
|
* @return static
|
||||||
|
*/
|
||||||
|
public function intersect($items)
|
||||||
|
{
|
||||||
|
return new static(array_intersect($this->items, $this->convertToArray($items)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回并删除数据中的的最后一个元素(出栈)
|
||||||
|
* @access public
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function pop()
|
||||||
|
{
|
||||||
|
return array_pop($this->items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回并删除数据中首个元素
|
||||||
|
* @access public
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function shift()
|
||||||
|
{
|
||||||
|
return array_shift($this->items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在数组开头插入一个元素
|
||||||
|
* @access public
|
||||||
|
* @param mixed $value 值
|
||||||
|
* @param mixed $key 键名
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function unshift($value, $key = null)
|
||||||
|
{
|
||||||
|
if (is_null($key)) {
|
||||||
|
array_unshift($this->items, $value);
|
||||||
|
} else {
|
||||||
|
$this->items = [$key => $value] + $this->items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在数组结尾插入一个元素
|
||||||
|
* @access public
|
||||||
|
* @param mixed $value 值
|
||||||
|
* @param mixed $key 键名
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function push($value, $key = null)
|
||||||
|
{
|
||||||
|
if (is_null($key)) {
|
||||||
|
$this->items[] = $value;
|
||||||
|
} else {
|
||||||
|
$this->items[$key] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过使用用户自定义函数,以字符串返回数组
|
||||||
|
* @access public
|
||||||
|
* @param callable $callback 回调函数
|
||||||
|
* @param mixed $initial 初始值
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function reduce(callable $callback, $initial = null)
|
||||||
|
{
|
||||||
|
return array_reduce($this->items, $callback, $initial);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 以相反的顺序创建一个新的 Collection 实例
|
||||||
|
* @access public
|
||||||
|
* @return static
|
||||||
|
*/
|
||||||
|
public function reverse()
|
||||||
|
{
|
||||||
|
return new static(array_reverse($this->items));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 把数据分割为新的数组块
|
||||||
|
* @access public
|
||||||
|
* @param int $size 分隔长度
|
||||||
|
* @param bool $preserveKeys 是否保持原数据索引
|
||||||
|
* @return static
|
||||||
|
*/
|
||||||
|
public function chunk($size, $preserveKeys = false)
|
||||||
|
{
|
||||||
|
$chunks = [];
|
||||||
|
|
||||||
|
foreach (array_chunk($this->items, $size, $preserveKeys) as $chunk) {
|
||||||
|
$chunks[] = new static($chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new static($chunks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 给数据中的每个元素执行回调
|
||||||
|
* @access public
|
||||||
|
* @param callable $callback 回调函数
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function each(callable $callback)
|
||||||
|
{
|
||||||
|
foreach ($this->items as $key => $item) {
|
||||||
|
$result = $callback($item, $key);
|
||||||
|
|
||||||
|
if (false === $result) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_object($item)) {
|
||||||
|
$this->items[$key] = $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用回调函数过滤数据中的元素
|
||||||
|
* @access public
|
||||||
|
* @param callable|null $callback 回调函数
|
||||||
|
* @return static
|
||||||
|
*/
|
||||||
|
public function filter(callable $callback = null)
|
||||||
|
{
|
||||||
|
return new static(array_filter($this->items, $callback ?: null));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回数据中指定的一列
|
||||||
|
* @access public
|
||||||
|
* @param mixed $columnKey 键名
|
||||||
|
* @param null $indexKey 作为索引值的列
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function column($columnKey, $indexKey = null)
|
||||||
|
{
|
||||||
|
if (function_exists('array_column')) {
|
||||||
|
return array_column($this->items, $columnKey, $indexKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = [];
|
||||||
|
foreach ($this->items as $row) {
|
||||||
|
$key = $value = null;
|
||||||
|
$keySet = $valueSet = false;
|
||||||
|
|
||||||
|
if (null !== $indexKey && array_key_exists($indexKey, $row)) {
|
||||||
|
$key = (string) $row[$indexKey];
|
||||||
|
$keySet = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $columnKey) {
|
||||||
|
$valueSet = true;
|
||||||
|
$value = $row;
|
||||||
|
} elseif (is_array($row) && array_key_exists($columnKey, $row)) {
|
||||||
|
$valueSet = true;
|
||||||
|
$value = $row[$columnKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($valueSet) {
|
||||||
|
if ($keySet) {
|
||||||
|
$result[$key] = $value;
|
||||||
|
} else {
|
||||||
|
$result[] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对数据排序,并返回排序后的数据组成的新 Collection 实例
|
||||||
|
* @access public
|
||||||
|
* @param callable|null $callback 回调函数
|
||||||
|
* @return static
|
||||||
|
*/
|
||||||
|
public function sort(callable $callback = null)
|
||||||
|
{
|
||||||
|
$items = $this->items;
|
||||||
|
$callback = $callback ?: function ($a, $b) {
|
||||||
|
return $a == $b ? 0 : (($a < $b) ? -1 : 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
uasort($items, $callback);
|
||||||
|
return new static($items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将数据打乱后组成新的 Collection 实例
|
||||||
|
* @access public
|
||||||
|
* @return static
|
||||||
|
*/
|
||||||
|
public function shuffle()
|
||||||
|
{
|
||||||
|
$items = $this->items;
|
||||||
|
|
||||||
|
shuffle($items);
|
||||||
|
return new static($items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 截取数据并返回新的 Collection 实例
|
||||||
|
* @access public
|
||||||
|
* @param int $offset 起始位置
|
||||||
|
* @param int $length 截取长度
|
||||||
|
* @param bool $preserveKeys 是否保持原先的键名
|
||||||
|
* @return static
|
||||||
|
*/
|
||||||
|
public function slice($offset, $length = null, $preserveKeys = false)
|
||||||
|
{
|
||||||
|
return new static(array_slice($this->items, $offset, $length, $preserveKeys));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指定的键是否存在
|
||||||
|
* @access public
|
||||||
|
* @param mixed $offset 键名
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function offsetExists($offset)
|
||||||
|
{
|
||||||
|
return array_key_exists($offset, $this->items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定键对应的值
|
||||||
|
* @access public
|
||||||
|
* @param mixed $offset 键名
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function offsetGet($offset)
|
||||||
|
{
|
||||||
|
return $this->items[$offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置键值
|
||||||
|
* @access public
|
||||||
|
* @param mixed $offset 键名
|
||||||
|
* @param mixed $value 值
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function offsetSet($offset, $value)
|
||||||
|
{
|
||||||
|
if (is_null($offset)) {
|
||||||
|
$this->items[] = $value;
|
||||||
|
} else {
|
||||||
|
$this->items[$offset] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除指定键值
|
||||||
|
* @access public
|
||||||
|
* @param mixed $offset 键名
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function offsetUnset($offset)
|
||||||
|
{
|
||||||
|
unset($this->items[$offset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统计数据的个数
|
||||||
|
* @access public
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function count()
|
||||||
|
{
|
||||||
|
return count($this->items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取数据的迭代器
|
||||||
|
* @access public
|
||||||
|
* @return ArrayIterator
|
||||||
|
*/
|
||||||
|
public function getIterator()
|
||||||
|
{
|
||||||
|
return new ArrayIterator($this->items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将数据反序列化成数组
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function jsonSerialize()
|
||||||
|
{
|
||||||
|
return $this->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换当前数据集为 JSON 字符串
|
||||||
|
* @access public
|
||||||
|
* @param integer $options json 参数
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function toJson($options = JSON_UNESCAPED_UNICODE)
|
||||||
|
{
|
||||||
|
return json_encode($this->toArray(), $options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将数据转换成字符串
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return $this->toJson();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将数据转换成数组
|
||||||
|
* @access protected
|
||||||
|
* @param mixed $items 数据
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function convertToArray($items)
|
||||||
|
{
|
||||||
|
return $items instanceof self ? $items->all() : (array) $items;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,863 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | TopThink [ WE CAN DO IT JUST THINK IT ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2015 http://www.topthink.com All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: zhangyajun <448901948@qq.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace think;
|
||||||
|
|
||||||
|
use think\console\Command;
|
||||||
|
use think\console\command\Help as HelpCommand;
|
||||||
|
use think\console\Input;
|
||||||
|
use think\console\input\Argument as InputArgument;
|
||||||
|
use think\console\input\Definition as InputDefinition;
|
||||||
|
use think\console\input\Option as InputOption;
|
||||||
|
use think\console\Output;
|
||||||
|
use think\console\output\driver\Buffer;
|
||||||
|
|
||||||
|
class Console
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string 命令名称
|
||||||
|
*/
|
||||||
|
private $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string 命令版本
|
||||||
|
*/
|
||||||
|
private $version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Command[] 命令
|
||||||
|
*/
|
||||||
|
private $commands = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool 是否需要帮助信息
|
||||||
|
*/
|
||||||
|
private $wantHelps = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool 是否捕获异常
|
||||||
|
*/
|
||||||
|
private $catchExceptions = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool 是否自动退出执行
|
||||||
|
*/
|
||||||
|
private $autoExit = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var InputDefinition 输入定义
|
||||||
|
*/
|
||||||
|
private $definition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string 默认执行的命令
|
||||||
|
*/
|
||||||
|
private $defaultCommand;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array 默认提供的命令
|
||||||
|
*/
|
||||||
|
private static $defaultCommands = [
|
||||||
|
"think\\console\\command\\Help",
|
||||||
|
"think\\console\\command\\Lists",
|
||||||
|
"think\\console\\command\\Build",
|
||||||
|
"think\\console\\command\\Clear",
|
||||||
|
"think\\console\\command\\make\\Controller",
|
||||||
|
"think\\console\\command\\make\\Model",
|
||||||
|
"think\\console\\command\\optimize\\Autoload",
|
||||||
|
"think\\console\\command\\optimize\\Config",
|
||||||
|
"think\\console\\command\\optimize\\Route",
|
||||||
|
"think\\console\\command\\optimize\\Schema",
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Console constructor.
|
||||||
|
* @access public
|
||||||
|
* @param string $name 名称
|
||||||
|
* @param string $version 版本
|
||||||
|
* @param null|string $user 执行用户
|
||||||
|
*/
|
||||||
|
public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN', $user = null)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
$this->version = $version;
|
||||||
|
|
||||||
|
if ($user) {
|
||||||
|
$this->setUser($user);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->defaultCommand = 'list';
|
||||||
|
$this->definition = $this->getDefaultInputDefinition();
|
||||||
|
|
||||||
|
foreach ($this->getDefaultCommands() as $command) {
|
||||||
|
$this->add($command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置执行用户
|
||||||
|
* @param $user
|
||||||
|
*/
|
||||||
|
public function setUser($user)
|
||||||
|
{
|
||||||
|
$user = posix_getpwnam($user);
|
||||||
|
if ($user) {
|
||||||
|
posix_setuid($user['uid']);
|
||||||
|
posix_setgid($user['gid']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化 Console
|
||||||
|
* @access public
|
||||||
|
* @param bool $run 是否运行 Console
|
||||||
|
* @return int|Console
|
||||||
|
*/
|
||||||
|
public static function init($run = true)
|
||||||
|
{
|
||||||
|
static $console;
|
||||||
|
|
||||||
|
if (!$console) {
|
||||||
|
$config = Config::get('console');
|
||||||
|
// 实例化 console
|
||||||
|
$console = new self($config['name'], $config['version'], $config['user']);
|
||||||
|
|
||||||
|
// 读取指令集
|
||||||
|
if (is_file(CONF_PATH . 'command' . EXT)) {
|
||||||
|
$commands = include CONF_PATH . 'command' . EXT;
|
||||||
|
|
||||||
|
if (is_array($commands)) {
|
||||||
|
foreach ($commands as $command) {
|
||||||
|
class_exists($command) &&
|
||||||
|
is_subclass_of($command, "\\think\\console\\Command") &&
|
||||||
|
$console->add(new $command()); // 注册指令
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $run ? $console->run() : $console;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调用命令
|
||||||
|
* @access public
|
||||||
|
* @param string $command
|
||||||
|
* @param array $parameters
|
||||||
|
* @param string $driver
|
||||||
|
* @return Output
|
||||||
|
*/
|
||||||
|
public static function call($command, array $parameters = [], $driver = 'buffer')
|
||||||
|
{
|
||||||
|
$console = self::init(false);
|
||||||
|
|
||||||
|
array_unshift($parameters, $command);
|
||||||
|
|
||||||
|
$input = new Input($parameters);
|
||||||
|
$output = new Output($driver);
|
||||||
|
|
||||||
|
$console->setCatchExceptions(false);
|
||||||
|
$console->find($command)->run($input, $output);
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行当前的指令
|
||||||
|
* @access public
|
||||||
|
* @return int
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
$input = new Input();
|
||||||
|
$output = new Output();
|
||||||
|
|
||||||
|
$this->configureIO($input, $output);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$exitCode = $this->doRun($input, $output);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
if (!$this->catchExceptions) throw $e;
|
||||||
|
|
||||||
|
$output->renderException($e);
|
||||||
|
|
||||||
|
$exitCode = $e->getCode();
|
||||||
|
|
||||||
|
if (is_numeric($exitCode)) {
|
||||||
|
$exitCode = ((int) $exitCode) ?: 1;
|
||||||
|
} else {
|
||||||
|
$exitCode = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->autoExit) {
|
||||||
|
if ($exitCode > 255) $exitCode = 255;
|
||||||
|
|
||||||
|
exit($exitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $exitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行指令
|
||||||
|
* @access public
|
||||||
|
* @param Input $input 输入
|
||||||
|
* @param Output $output 输出
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function doRun(Input $input, Output $output)
|
||||||
|
{
|
||||||
|
// 获取版本信息
|
||||||
|
if (true === $input->hasParameterOption(['--version', '-V'])) {
|
||||||
|
$output->writeln($this->getLongVersion());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$name = $this->getCommandName($input);
|
||||||
|
|
||||||
|
// 获取帮助信息
|
||||||
|
if (true === $input->hasParameterOption(['--help', '-h'])) {
|
||||||
|
if (!$name) {
|
||||||
|
$name = 'help';
|
||||||
|
$input = new Input(['help']);
|
||||||
|
} else {
|
||||||
|
$this->wantHelps = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$name) {
|
||||||
|
$name = $this->defaultCommand;
|
||||||
|
$input = new Input([$this->defaultCommand]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->doRunCommand($this->find($name), $input, $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置输入参数定义
|
||||||
|
* @access public
|
||||||
|
* @param InputDefinition $definition 输入定义
|
||||||
|
* @return $this;
|
||||||
|
*/
|
||||||
|
public function setDefinition(InputDefinition $definition)
|
||||||
|
{
|
||||||
|
$this->definition = $definition;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取输入参数定义
|
||||||
|
* @access public
|
||||||
|
* @return InputDefinition
|
||||||
|
*/
|
||||||
|
public function getDefinition()
|
||||||
|
{
|
||||||
|
return $this->definition;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取帮助信息
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getHelp()
|
||||||
|
{
|
||||||
|
return $this->getLongVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置是否捕获异常
|
||||||
|
* @access public
|
||||||
|
* @param bool $boolean 是否捕获
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setCatchExceptions($boolean)
|
||||||
|
{
|
||||||
|
$this->catchExceptions = (bool) $boolean;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置是否自动退出
|
||||||
|
* @access public
|
||||||
|
* @param bool $boolean 是否自动退出
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setAutoExit($boolean)
|
||||||
|
{
|
||||||
|
$this->autoExit = (bool) $boolean;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取名称
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置名称
|
||||||
|
* @access public
|
||||||
|
* @param string $name 名称
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setName($name)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取版本
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getVersion()
|
||||||
|
{
|
||||||
|
return $this->version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置版本
|
||||||
|
* @access public
|
||||||
|
* @param string $version 版本信息
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setVersion($version)
|
||||||
|
{
|
||||||
|
$this->version = $version;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取完整的版本号
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLongVersion()
|
||||||
|
{
|
||||||
|
if ('UNKNOWN' !== $this->getName() && 'UNKNOWN' !== $this->getVersion()) {
|
||||||
|
return sprintf(
|
||||||
|
'<info>%s</info> version <comment>%s</comment>',
|
||||||
|
$this->getName(),
|
||||||
|
$this->getVersion()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return '<info>Console Tool</info>';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册一个指令
|
||||||
|
* @access public
|
||||||
|
* @param string $name 指令名称
|
||||||
|
* @return Command
|
||||||
|
*/
|
||||||
|
public function register($name)
|
||||||
|
{
|
||||||
|
return $this->add(new Command($name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量添加指令
|
||||||
|
* @access public
|
||||||
|
* @param Command[] $commands 指令实例
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function addCommands(array $commands)
|
||||||
|
{
|
||||||
|
foreach ($commands as $command) $this->add($command);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加一个指令
|
||||||
|
* @access public
|
||||||
|
* @param Command $command 命令实例
|
||||||
|
* @return Command|bool
|
||||||
|
*/
|
||||||
|
public function add(Command $command)
|
||||||
|
{
|
||||||
|
if (!$command->isEnabled()) {
|
||||||
|
$command->setConsole(null);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$command->setConsole($this);
|
||||||
|
|
||||||
|
if (null === $command->getDefinition()) {
|
||||||
|
throw new \LogicException(
|
||||||
|
sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->commands[$command->getName()] = $command;
|
||||||
|
|
||||||
|
foreach ($command->getAliases() as $alias) {
|
||||||
|
$this->commands[$alias] = $command;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $command;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指令
|
||||||
|
* @access public
|
||||||
|
* @param string $name 指令名称
|
||||||
|
* @return Command
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function get($name)
|
||||||
|
{
|
||||||
|
if (!isset($this->commands[$name])) {
|
||||||
|
throw new \InvalidArgumentException(
|
||||||
|
sprintf('The command "%s" does not exist.', $name)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$command = $this->commands[$name];
|
||||||
|
|
||||||
|
if ($this->wantHelps) {
|
||||||
|
$this->wantHelps = false;
|
||||||
|
|
||||||
|
/** @var HelpCommand $helpCommand */
|
||||||
|
$helpCommand = $this->get('help');
|
||||||
|
$helpCommand->setCommand($command);
|
||||||
|
|
||||||
|
return $helpCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $command;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 某个指令是否存在
|
||||||
|
* @access public
|
||||||
|
* @param string $name 指令名称
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function has($name)
|
||||||
|
{
|
||||||
|
return isset($this->commands[$name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有的命名空间
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getNamespaces()
|
||||||
|
{
|
||||||
|
$namespaces = [];
|
||||||
|
|
||||||
|
foreach ($this->commands as $command) {
|
||||||
|
$namespaces = array_merge(
|
||||||
|
$namespaces, $this->extractAllNamespaces($command->getName())
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($command->getAliases() as $alias) {
|
||||||
|
$namespaces = array_merge(
|
||||||
|
$namespaces, $this->extractAllNamespaces($alias)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_values(array_unique(array_filter($namespaces)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找注册命名空间中的名称或缩写
|
||||||
|
* @access public
|
||||||
|
* @param string $namespace
|
||||||
|
* @return string
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function findNamespace($namespace)
|
||||||
|
{
|
||||||
|
$expr = preg_replace_callback('{([^:]+|)}', function ($matches) {
|
||||||
|
return preg_quote($matches[1]) . '[^:]*';
|
||||||
|
}, $namespace);
|
||||||
|
|
||||||
|
$allNamespaces = $this->getNamespaces();
|
||||||
|
$namespaces = preg_grep('{^' . $expr . '}', $allNamespaces);
|
||||||
|
|
||||||
|
if (empty($namespaces)) {
|
||||||
|
$message = sprintf(
|
||||||
|
'There are no commands defined in the "%s" namespace.', $namespace
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
|
||||||
|
if (1 == count($alternatives)) {
|
||||||
|
$message .= "\n\nDid you mean this?\n ";
|
||||||
|
} else {
|
||||||
|
$message .= "\n\nDid you mean one of these?\n ";
|
||||||
|
}
|
||||||
|
|
||||||
|
$message .= implode("\n ", $alternatives);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \InvalidArgumentException($message);
|
||||||
|
}
|
||||||
|
|
||||||
|
$exact = in_array($namespace, $namespaces, true);
|
||||||
|
|
||||||
|
if (count($namespaces) > 1 && !$exact) {
|
||||||
|
throw new \InvalidArgumentException(
|
||||||
|
sprintf(
|
||||||
|
'The namespace "%s" is ambiguous (%s).',
|
||||||
|
$namespace,
|
||||||
|
$this->getAbbreviationSuggestions(array_values($namespaces)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $exact ? $namespace : reset($namespaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找指令
|
||||||
|
* @access public
|
||||||
|
* @param string $name 名称或者别名
|
||||||
|
* @return Command
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function find($name)
|
||||||
|
{
|
||||||
|
$expr = preg_replace_callback('{([^:]+|)}', function ($matches) {
|
||||||
|
return preg_quote($matches[1]) . '[^:]*';
|
||||||
|
}, $name);
|
||||||
|
|
||||||
|
$allCommands = array_keys($this->commands);
|
||||||
|
$commands = preg_grep('{^' . $expr . '}', $allCommands);
|
||||||
|
|
||||||
|
if (empty($commands) || count(preg_grep('{^' . $expr . '$}', $commands)) < 1) {
|
||||||
|
if (false !== ($pos = strrpos($name, ':'))) {
|
||||||
|
$this->findNamespace(substr($name, 0, $pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
$message = sprintf('Command "%s" is not defined.', $name);
|
||||||
|
|
||||||
|
if ($alternatives = $this->findAlternatives($name, $allCommands)) {
|
||||||
|
if (1 == count($alternatives)) {
|
||||||
|
$message .= "\n\nDid you mean this?\n ";
|
||||||
|
} else {
|
||||||
|
$message .= "\n\nDid you mean one of these?\n ";
|
||||||
|
}
|
||||||
|
$message .= implode("\n ", $alternatives);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \InvalidArgumentException($message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($commands) > 1) {
|
||||||
|
$commandList = $this->commands;
|
||||||
|
$commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) {
|
||||||
|
$commandName = $commandList[$nameOrAlias]->getName();
|
||||||
|
|
||||||
|
return $commandName === $nameOrAlias || !in_array($commandName, $commands);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$exact = in_array($name, $commands, true);
|
||||||
|
if (count($commands) > 1 && !$exact) {
|
||||||
|
$suggestions = $this->getAbbreviationSuggestions(array_values($commands));
|
||||||
|
|
||||||
|
throw new \InvalidArgumentException(
|
||||||
|
sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->get($exact ? $name : reset($commands));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有的指令
|
||||||
|
* @access public
|
||||||
|
* @param string $namespace 命名空间
|
||||||
|
* @return Command[]
|
||||||
|
*/
|
||||||
|
public function all($namespace = null)
|
||||||
|
{
|
||||||
|
if (null === $namespace) return $this->commands;
|
||||||
|
|
||||||
|
$commands = [];
|
||||||
|
|
||||||
|
foreach ($this->commands as $name => $command) {
|
||||||
|
$ext = $this->extractNamespace($name, substr_count($namespace, ':') + 1);
|
||||||
|
|
||||||
|
if ($ext === $namespace) $commands[$name] = $command;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $commands;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取可能的指令名
|
||||||
|
* @access public
|
||||||
|
* @param array $names 指令名
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function getAbbreviations($names)
|
||||||
|
{
|
||||||
|
$abbrevs = [];
|
||||||
|
foreach ($names as $name) {
|
||||||
|
for ($len = strlen($name); $len > 0; --$len) {
|
||||||
|
$abbrev = substr($name, 0, $len);
|
||||||
|
$abbrevs[$abbrev][] = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $abbrevs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置基于用户的参数和选项的输入和输出实例
|
||||||
|
* @access protected
|
||||||
|
* @param Input $input 输入实例
|
||||||
|
* @param Output $output 输出实例
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function configureIO(Input $input, Output $output)
|
||||||
|
{
|
||||||
|
if (true === $input->hasParameterOption(['--ansi'])) {
|
||||||
|
$output->setDecorated(true);
|
||||||
|
} elseif (true === $input->hasParameterOption(['--no-ansi'])) {
|
||||||
|
$output->setDecorated(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (true === $input->hasParameterOption(['--no-interaction', '-n'])) {
|
||||||
|
$input->setInteractive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (true === $input->hasParameterOption(['--quiet', '-q'])) {
|
||||||
|
$output->setVerbosity(Output::VERBOSITY_QUIET);
|
||||||
|
} else {
|
||||||
|
if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) {
|
||||||
|
$output->setVerbosity(Output::VERBOSITY_DEBUG);
|
||||||
|
} elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || $input->getParameterOption('--verbose') === 2) {
|
||||||
|
$output->setVerbosity(Output::VERBOSITY_VERY_VERBOSE);
|
||||||
|
} elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) {
|
||||||
|
$output->setVerbosity(Output::VERBOSITY_VERBOSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行指令
|
||||||
|
* @access protected
|
||||||
|
* @param Command $command 指令实例
|
||||||
|
* @param Input $input 输入实例
|
||||||
|
* @param Output $output 输出实例
|
||||||
|
* @return int
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
protected function doRunCommand(Command $command, Input $input, Output $output)
|
||||||
|
{
|
||||||
|
return $command->run($input, $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指令的名称
|
||||||
|
* @access protected
|
||||||
|
* @param Input $input 输入实例
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function getCommandName(Input $input)
|
||||||
|
{
|
||||||
|
return $input->getFirstArgument();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取默认输入定义
|
||||||
|
* @access protected
|
||||||
|
* @return InputDefinition
|
||||||
|
*/
|
||||||
|
protected function getDefaultInputDefinition()
|
||||||
|
{
|
||||||
|
return new InputDefinition([
|
||||||
|
new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
|
||||||
|
new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'),
|
||||||
|
new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this console version'),
|
||||||
|
new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
|
||||||
|
new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'),
|
||||||
|
new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'),
|
||||||
|
new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'),
|
||||||
|
new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取默认命令
|
||||||
|
* @access protected
|
||||||
|
* @return Command[]
|
||||||
|
*/
|
||||||
|
protected function getDefaultCommands()
|
||||||
|
{
|
||||||
|
$defaultCommands = [];
|
||||||
|
|
||||||
|
foreach (self::$defaultCommands as $class) {
|
||||||
|
if (class_exists($class) && is_subclass_of($class, "think\\console\\Command")) {
|
||||||
|
$defaultCommands[] = new $class();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $defaultCommands;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加默认指令
|
||||||
|
* @access public
|
||||||
|
* @param array $classes 指令
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function addDefaultCommands(array $classes)
|
||||||
|
{
|
||||||
|
self::$defaultCommands = array_merge(self::$defaultCommands, $classes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取可能的建议
|
||||||
|
* @access private
|
||||||
|
* @param array $abbrevs
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function getAbbreviationSuggestions($abbrevs)
|
||||||
|
{
|
||||||
|
return sprintf(
|
||||||
|
'%s, %s%s',
|
||||||
|
$abbrevs[0],
|
||||||
|
$abbrevs[1],
|
||||||
|
count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : ''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回指令的命名空间部分
|
||||||
|
* @access public
|
||||||
|
* @param string $name 指令名称
|
||||||
|
* @param string $limit 部分的命名空间的最大数量
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function extractNamespace($name, $limit = null)
|
||||||
|
{
|
||||||
|
$parts = explode(':', $name);
|
||||||
|
array_pop($parts);
|
||||||
|
|
||||||
|
return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找可替代的建议
|
||||||
|
* @access private
|
||||||
|
* @param string $name 指令名称
|
||||||
|
* @param array|\Traversable $collection 建议集合
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function findAlternatives($name, $collection)
|
||||||
|
{
|
||||||
|
$threshold = 1e3;
|
||||||
|
$alternatives = [];
|
||||||
|
$collectionParts = [];
|
||||||
|
|
||||||
|
foreach ($collection as $item) {
|
||||||
|
$collectionParts[$item] = explode(':', $item);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (explode(':', $name) as $i => $subname) {
|
||||||
|
foreach ($collectionParts as $collectionName => $parts) {
|
||||||
|
$exists = isset($alternatives[$collectionName]);
|
||||||
|
|
||||||
|
if (!isset($parts[$i]) && $exists) {
|
||||||
|
$alternatives[$collectionName] += $threshold;
|
||||||
|
continue;
|
||||||
|
} elseif (!isset($parts[$i])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$lev = levenshtein($subname, $parts[$i]);
|
||||||
|
|
||||||
|
if ($lev <= strlen($subname) / 3 ||
|
||||||
|
'' !== $subname &&
|
||||||
|
false !== strpos($parts[$i], $subname)
|
||||||
|
) {
|
||||||
|
$alternatives[$collectionName] = $exists ?
|
||||||
|
$alternatives[$collectionName] + $lev :
|
||||||
|
$lev;
|
||||||
|
} elseif ($exists) {
|
||||||
|
$alternatives[$collectionName] += $threshold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($collection as $item) {
|
||||||
|
$lev = levenshtein($name, $item);
|
||||||
|
|
||||||
|
if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
|
||||||
|
$alternatives[$item] = isset($alternatives[$item]) ?
|
||||||
|
$alternatives[$item] - $lev :
|
||||||
|
$lev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$alternatives = array_filter($alternatives, function ($lev) use ($threshold) {
|
||||||
|
return $lev < 2 * $threshold;
|
||||||
|
});
|
||||||
|
|
||||||
|
asort($alternatives);
|
||||||
|
|
||||||
|
return array_keys($alternatives);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置默认的指令
|
||||||
|
* @access public
|
||||||
|
* @param string $commandName 指令名称
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setDefaultCommand($commandName)
|
||||||
|
{
|
||||||
|
$this->defaultCommand = $commandName;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回所有的命名空间
|
||||||
|
* @access private
|
||||||
|
* @param string $name 指令名称
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function extractAllNamespaces($name)
|
||||||
|
{
|
||||||
|
$namespaces = [];
|
||||||
|
|
||||||
|
foreach (explode(':', $name, -1) as $part) {
|
||||||
|
if (count($namespaces)) {
|
||||||
|
$namespaces[] = end($namespaces) . ':' . $part;
|
||||||
|
} else {
|
||||||
|
$namespaces[] = $part;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $namespaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,229 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace think;
|
||||||
|
|
||||||
|
use think\exception\ValidateException;
|
||||||
|
use traits\controller\Jump;
|
||||||
|
|
||||||
|
Loader::import('controller/Jump', TRAIT_PATH, EXT);
|
||||||
|
|
||||||
|
class Controller
|
||||||
|
{
|
||||||
|
use Jump;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \think\View 视图类实例
|
||||||
|
*/
|
||||||
|
protected $view;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \think\Request Request 实例
|
||||||
|
*/
|
||||||
|
protected $request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool 验证失败是否抛出异常
|
||||||
|
*/
|
||||||
|
protected $failException = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool 是否批量验证
|
||||||
|
*/
|
||||||
|
protected $batchValidate = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array 前置操作方法列表
|
||||||
|
*/
|
||||||
|
protected $beforeActionList = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造方法
|
||||||
|
* @access public
|
||||||
|
* @param Request $request Request 对象
|
||||||
|
*/
|
||||||
|
public function __construct(Request $request = null)
|
||||||
|
{
|
||||||
|
$this->view = View::instance(Config::get('template'), Config::get('view_replace_str'));
|
||||||
|
$this->request = is_null($request) ? Request::instance() : $request;
|
||||||
|
|
||||||
|
// 控制器初始化
|
||||||
|
$this->_initialize();
|
||||||
|
|
||||||
|
// 前置操作方法
|
||||||
|
if ($this->beforeActionList) {
|
||||||
|
foreach ($this->beforeActionList as $method => $options) {
|
||||||
|
is_numeric($method) ?
|
||||||
|
$this->beforeAction($options) :
|
||||||
|
$this->beforeAction($method, $options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化操作
|
||||||
|
* @access protected
|
||||||
|
*/
|
||||||
|
protected function _initialize()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前置操作
|
||||||
|
* @access protected
|
||||||
|
* @param string $method 前置操作方法名
|
||||||
|
* @param array $options 调用参数 ['only'=>[...]] 或者 ['except'=>[...]]
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function beforeAction($method, $options = [])
|
||||||
|
{
|
||||||
|
if (isset($options['only'])) {
|
||||||
|
if (is_string($options['only'])) {
|
||||||
|
$options['only'] = explode(',', $options['only']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in_array($this->request->action(), $options['only'])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} elseif (isset($options['except'])) {
|
||||||
|
if (is_string($options['except'])) {
|
||||||
|
$options['except'] = explode(',', $options['except']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array($this->request->action(), $options['except'])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
call_user_func([$this, $method]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载模板输出
|
||||||
|
* @access protected
|
||||||
|
* @param string $template 模板文件名
|
||||||
|
* @param array $vars 模板输出变量
|
||||||
|
* @param array $replace 模板替换
|
||||||
|
* @param array $config 模板参数
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
protected function fetch($template = '', $vars = [], $replace = [], $config = [])
|
||||||
|
{
|
||||||
|
return $this->view->fetch($template, $vars, $replace, $config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染内容输出
|
||||||
|
* @access protected
|
||||||
|
* @param string $content 模板内容
|
||||||
|
* @param array $vars 模板输出变量
|
||||||
|
* @param array $replace 替换内容
|
||||||
|
* @param array $config 模板参数
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
protected function display($content = '', $vars = [], $replace = [], $config = [])
|
||||||
|
{
|
||||||
|
return $this->view->display($content, $vars, $replace, $config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板变量赋值
|
||||||
|
* @access protected
|
||||||
|
* @param mixed $name 要显示的模板变量
|
||||||
|
* @param mixed $value 变量的值
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
protected function assign($name, $value = '')
|
||||||
|
{
|
||||||
|
$this->view->assign($name, $value);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化模板引擎
|
||||||
|
* @access protected
|
||||||
|
* @param array|string $engine 引擎参数
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
protected function engine($engine)
|
||||||
|
{
|
||||||
|
$this->view->engine($engine);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置验证失败后是否抛出异常
|
||||||
|
* @access protected
|
||||||
|
* @param bool $fail 是否抛出异常
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
protected function validateFailException($fail = true)
|
||||||
|
{
|
||||||
|
$this->failException = $fail;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证数据
|
||||||
|
* @access protected
|
||||||
|
* @param array $data 数据
|
||||||
|
* @param string|array $validate 验证器名或者验证规则数组
|
||||||
|
* @param array $message 提示信息
|
||||||
|
* @param bool $batch 是否批量验证
|
||||||
|
* @param mixed $callback 回调方法(闭包)
|
||||||
|
* @return array|string|true
|
||||||
|
* @throws ValidateException
|
||||||
|
*/
|
||||||
|
protected function validate($data, $validate, $message = [], $batch = false, $callback = null)
|
||||||
|
{
|
||||||
|
if (is_array($validate)) {
|
||||||
|
$v = Loader::validate();
|
||||||
|
$v->rule($validate);
|
||||||
|
} else {
|
||||||
|
// 支持场景
|
||||||
|
if (strpos($validate, '.')) {
|
||||||
|
list($validate, $scene) = explode('.', $validate);
|
||||||
|
}
|
||||||
|
|
||||||
|
$v = Loader::validate($validate);
|
||||||
|
|
||||||
|
!empty($scene) && $v->scene($scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量验证
|
||||||
|
if ($batch || $this->batchValidate) {
|
||||||
|
$v->batch(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置错误信息
|
||||||
|
if (is_array($message)) {
|
||||||
|
$v->message($message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用回调验证
|
||||||
|
if ($callback && is_callable($callback)) {
|
||||||
|
call_user_func_array($callback, [$v, &$data]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$v->check($data)) {
|
||||||
|
if ($this->failException) {
|
||||||
|
throw new ValidateException($v->getError());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $v->getError();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,268 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace think;
|
||||||
|
|
||||||
|
class Cookie
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array cookie 设置参数
|
||||||
|
*/
|
||||||
|
protected static $config = [
|
||||||
|
'prefix' => '', // cookie 名称前缀
|
||||||
|
'expire' => 0, // cookie 保存时间
|
||||||
|
'path' => '/', // cookie 保存路径
|
||||||
|
'domain' => '', // cookie 有效域名
|
||||||
|
'secure' => false, // cookie 启用安全传输
|
||||||
|
'httponly' => false, // httponly 设置
|
||||||
|
'setcookie' => true, // 是否使用 setcookie
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool 是否完成初始化了
|
||||||
|
*/
|
||||||
|
protected static $init;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cookie初始化
|
||||||
|
* @access public
|
||||||
|
* @param array $config 配置参数
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function init(array $config = [])
|
||||||
|
{
|
||||||
|
if (empty($config)) {
|
||||||
|
$config = Config::get('cookie');
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$config = array_merge(self::$config, array_change_key_case($config));
|
||||||
|
|
||||||
|
if (!empty(self::$config['httponly'])) {
|
||||||
|
ini_set('session.cookie_httponly', 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$init = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置或者获取 cookie 作用域(前缀)
|
||||||
|
* @access public
|
||||||
|
* @param string $prefix 前缀
|
||||||
|
* @return string|
|
||||||
|
*/
|
||||||
|
public static function prefix($prefix = '')
|
||||||
|
{
|
||||||
|
if (empty($prefix)) {
|
||||||
|
return self::$config['prefix'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$config['prefix'] = $prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cookie 设置、获取、删除
|
||||||
|
* @access public
|
||||||
|
* @param string $name cookie 名称
|
||||||
|
* @param mixed $value cookie 值
|
||||||
|
* @param mixed $option 可选参数 可能会是 null|integer|string
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function set($name, $value = '', $option = null)
|
||||||
|
{
|
||||||
|
!isset(self::$init) && self::init();
|
||||||
|
|
||||||
|
// 参数设置(会覆盖黙认设置)
|
||||||
|
if (!is_null($option)) {
|
||||||
|
if (is_numeric($option)) {
|
||||||
|
$option = ['expire' => $option];
|
||||||
|
} elseif (is_string($option)) {
|
||||||
|
parse_str($option, $option);
|
||||||
|
}
|
||||||
|
|
||||||
|
$config = array_merge(self::$config, array_change_key_case($option));
|
||||||
|
} else {
|
||||||
|
$config = self::$config;
|
||||||
|
}
|
||||||
|
|
||||||
|
$name = $config['prefix'] . $name;
|
||||||
|
|
||||||
|
// 设置 cookie
|
||||||
|
if (is_array($value)) {
|
||||||
|
array_walk_recursive($value, 'self::jsonFormatProtect', 'encode');
|
||||||
|
$value = 'think:' . json_encode($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$expire = !empty($config['expire']) ?
|
||||||
|
$_SERVER['REQUEST_TIME'] + intval($config['expire']) :
|
||||||
|
0;
|
||||||
|
|
||||||
|
if ($config['setcookie']) {
|
||||||
|
setcookie(
|
||||||
|
$name, $value, $expire, $config['path'], $config['domain'],
|
||||||
|
$config['secure'], $config['httponly']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$_COOKIE[$name] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 永久保存 Cookie 数据
|
||||||
|
* @access public
|
||||||
|
* @param string $name cookie 名称
|
||||||
|
* @param mixed $value cookie 值
|
||||||
|
* @param mixed $option 可选参数 可能会是 null|integer|string
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function forever($name, $value = '', $option = null)
|
||||||
|
{
|
||||||
|
if (is_null($option) || is_numeric($option)) {
|
||||||
|
$option = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$option['expire'] = 315360000;
|
||||||
|
|
||||||
|
self::set($name, $value, $option);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否有 Cookie 数据
|
||||||
|
* @access public
|
||||||
|
* @param string $name cookie 名称
|
||||||
|
* @param string|null $prefix cookie 前缀
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function has($name, $prefix = null)
|
||||||
|
{
|
||||||
|
!isset(self::$init) && self::init();
|
||||||
|
|
||||||
|
$prefix = !is_null($prefix) ? $prefix : self::$config['prefix'];
|
||||||
|
|
||||||
|
return isset($_COOKIE[$prefix . $name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 Cookie 的值
|
||||||
|
* @access public
|
||||||
|
* @param string $name cookie 名称
|
||||||
|
* @param string|null $prefix cookie 前缀
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public static function get($name = '', $prefix = null)
|
||||||
|
{
|
||||||
|
!isset(self::$init) && self::init();
|
||||||
|
|
||||||
|
$prefix = !is_null($prefix) ? $prefix : self::$config['prefix'];
|
||||||
|
$key = $prefix . $name;
|
||||||
|
|
||||||
|
if ('' == $name) {
|
||||||
|
// 获取全部
|
||||||
|
if ($prefix) {
|
||||||
|
$value = [];
|
||||||
|
|
||||||
|
foreach ($_COOKIE as $k => $val) {
|
||||||
|
if (0 === strpos($k, $prefix)) {
|
||||||
|
$value[$k] = $val;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$value = $_COOKIE;
|
||||||
|
}
|
||||||
|
} elseif (isset($_COOKIE[$key])) {
|
||||||
|
$value = $_COOKIE[$key];
|
||||||
|
|
||||||
|
if (0 === strpos($value, 'think:')) {
|
||||||
|
$value = json_decode(substr($value, 6), true);
|
||||||
|
array_walk_recursive($value, 'self::jsonFormatProtect', 'decode');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$value = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除 Cookie
|
||||||
|
* @access public
|
||||||
|
* @param string $name cookie 名称
|
||||||
|
* @param string|null $prefix cookie 前缀
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function delete($name, $prefix = null)
|
||||||
|
{
|
||||||
|
!isset(self::$init) && self::init();
|
||||||
|
|
||||||
|
$config = self::$config;
|
||||||
|
$prefix = !is_null($prefix) ? $prefix : $config['prefix'];
|
||||||
|
$name = $prefix . $name;
|
||||||
|
|
||||||
|
if ($config['setcookie']) {
|
||||||
|
setcookie(
|
||||||
|
$name, '', $_SERVER['REQUEST_TIME'] - 3600, $config['path'],
|
||||||
|
$config['domain'], $config['secure'], $config['httponly']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除指定 cookie
|
||||||
|
unset($_COOKIE[$name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除指定前缀的所有 cookie
|
||||||
|
* @access public
|
||||||
|
* @param string|null $prefix cookie 前缀
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function clear($prefix = null)
|
||||||
|
{
|
||||||
|
if (empty($_COOKIE)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
!isset(self::$init) && self::init();
|
||||||
|
|
||||||
|
// 要删除的 cookie 前缀,不指定则删除 config 设置的指定前缀
|
||||||
|
$config = self::$config;
|
||||||
|
$prefix = !is_null($prefix) ? $prefix : $config['prefix'];
|
||||||
|
|
||||||
|
if ($prefix) {
|
||||||
|
foreach ($_COOKIE as $key => $val) {
|
||||||
|
if (0 === strpos($key, $prefix)) {
|
||||||
|
if ($config['setcookie']) {
|
||||||
|
setcookie(
|
||||||
|
$key, '', $_SERVER['REQUEST_TIME'] - 3600, $config['path'],
|
||||||
|
$config['domain'], $config['secure'], $config['httponly']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($_COOKIE[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* json 转换时的格式保护
|
||||||
|
* @access protected
|
||||||
|
* @param mixed $val 要转换的值
|
||||||
|
* @param string $key 键名
|
||||||
|
* @param string $type 转换类别
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected static function jsonFormatProtect(&$val, $key, $type = 'encode')
|
||||||
|
{
|
||||||
|
if (!empty($val) && true !== $val) {
|
||||||
|
$val = 'decode' == $type ? urldecode($val) : urlencode($val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,180 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace think;
|
||||||
|
|
||||||
|
use think\db\Connection;
|
||||||
|
use think\db\Query;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Db
|
||||||
|
* @package think
|
||||||
|
* @method Query table(string $table) static 指定数据表(含前缀)
|
||||||
|
* @method Query name(string $name) static 指定数据表(不含前缀)
|
||||||
|
* @method Query where(mixed $field, string $op = null, mixed $condition = null) static 查询条件
|
||||||
|
* @method Query join(mixed $join, mixed $condition = null, string $type = 'INNER') static JOIN查询
|
||||||
|
* @method Query union(mixed $union, boolean $all = false) static UNION查询
|
||||||
|
* @method Query limit(mixed $offset, integer $length = null) static 查询LIMIT
|
||||||
|
* @method Query order(mixed $field, string $order = null) static 查询ORDER
|
||||||
|
* @method Query cache(mixed $key = null , integer $expire = null) static 设置查询缓存
|
||||||
|
* @method mixed value(string $field) static 获取某个字段的值
|
||||||
|
* @method array column(string $field, string $key = '') static 获取某个列的值
|
||||||
|
* @method Query view(mixed $join, mixed $field = null, mixed $on = null, string $type = 'INNER') static 视图查询
|
||||||
|
* @method mixed find(mixed $data = null) static 查询单个记录
|
||||||
|
* @method mixed select(mixed $data = null) static 查询多个记录
|
||||||
|
* @method integer insert(array $data, boolean $replace = false, boolean $getLastInsID = false, string $sequence = null) static 插入一条记录
|
||||||
|
* @method integer insertGetId(array $data, boolean $replace = false, string $sequence = null) static 插入一条记录并返回自增ID
|
||||||
|
* @method integer insertAll(array $dataSet) static 插入多条记录
|
||||||
|
* @method integer update(array $data) static 更新记录
|
||||||
|
* @method integer delete(mixed $data = null) static 删除记录
|
||||||
|
* @method boolean chunk(integer $count, callable $callback, string $column = null) static 分块获取数据
|
||||||
|
* @method mixed query(string $sql, array $bind = [], boolean $master = false, bool $pdo = false) static SQL查询
|
||||||
|
* @method integer execute(string $sql, array $bind = [], boolean $fetch = false, boolean $getLastInsID = false, string $sequence = null) static SQL执行
|
||||||
|
* @method Paginator paginate(integer $listRows = 15, mixed $simple = null, array $config = []) static 分页查询
|
||||||
|
* @method mixed transaction(callable $callback) static 执行数据库事务
|
||||||
|
* @method void startTrans() static 启动事务
|
||||||
|
* @method void commit() static 用于非自动提交状态下面的查询提交
|
||||||
|
* @method void rollback() static 事务回滚
|
||||||
|
* @method boolean batchQuery(array $sqlArray) static 批处理执行SQL语句
|
||||||
|
* @method string quote(string $str) static SQL指令安全过滤
|
||||||
|
* @method string getLastInsID($sequence = null) static 获取最近插入的ID
|
||||||
|
*/
|
||||||
|
class Db
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Connection[] 数据库连接实例
|
||||||
|
*/
|
||||||
|
private static $instance = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int 查询次数
|
||||||
|
*/
|
||||||
|
public static $queryTimes = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int 执行次数
|
||||||
|
*/
|
||||||
|
public static $executeTimes = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据库初始化,并取得数据库类实例
|
||||||
|
* @access public
|
||||||
|
* @param mixed $config 连接配置
|
||||||
|
* @param bool|string $name 连接标识 true 强制重新连接
|
||||||
|
* @return Connection
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function connect($config = [], $name = false)
|
||||||
|
{
|
||||||
|
if (false === $name) {
|
||||||
|
$name = md5(serialize($config));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (true === $name || !isset(self::$instance[$name])) {
|
||||||
|
// 解析连接参数 支持数组和字符串
|
||||||
|
$options = self::parseConfig($config);
|
||||||
|
|
||||||
|
if (empty($options['type'])) {
|
||||||
|
throw new \InvalidArgumentException('Undefined db type');
|
||||||
|
}
|
||||||
|
|
||||||
|
$class = false !== strpos($options['type'], '\\') ?
|
||||||
|
$options['type'] :
|
||||||
|
'\\think\\db\\connector\\' . ucwords($options['type']);
|
||||||
|
|
||||||
|
// 记录初始化信息
|
||||||
|
if (App::$debug) {
|
||||||
|
Log::record('[ DB ] INIT ' . $options['type'], 'info');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (true === $name) {
|
||||||
|
$name = md5(serialize($config));
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$instance[$name] = new $class($options);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$instance[$name];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除连接实例
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function clear()
|
||||||
|
{
|
||||||
|
self::$instance = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据库连接参数解析
|
||||||
|
* @access private
|
||||||
|
* @param mixed $config 连接参数
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private static function parseConfig($config)
|
||||||
|
{
|
||||||
|
if (empty($config)) {
|
||||||
|
$config = Config::get('database');
|
||||||
|
} elseif (is_string($config) && false === strpos($config, '/')) {
|
||||||
|
$config = Config::get($config); // 支持读取配置参数
|
||||||
|
}
|
||||||
|
|
||||||
|
return is_string($config) ? self::parseDsn($config) : $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DSN 解析
|
||||||
|
* 格式: mysql://username:passwd@localhost:3306/DbName?param1=val1¶m2=val2#utf8
|
||||||
|
* @access private
|
||||||
|
* @param string $dsnStr 数据库 DSN 字符串解析
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private static function parseDsn($dsnStr)
|
||||||
|
{
|
||||||
|
$info = parse_url($dsnStr);
|
||||||
|
|
||||||
|
if (!$info) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$dsn = [
|
||||||
|
'type' => $info['scheme'],
|
||||||
|
'username' => isset($info['user']) ? $info['user'] : '',
|
||||||
|
'password' => isset($info['pass']) ? $info['pass'] : '',
|
||||||
|
'hostname' => isset($info['host']) ? $info['host'] : '',
|
||||||
|
'hostport' => isset($info['port']) ? $info['port'] : '',
|
||||||
|
'database' => !empty($info['path']) ? ltrim($info['path'], '/') : '',
|
||||||
|
'charset' => isset($info['fragment']) ? $info['fragment'] : 'utf8',
|
||||||
|
];
|
||||||
|
|
||||||
|
if (isset($info['query'])) {
|
||||||
|
parse_str($info['query'], $dsn['params']);
|
||||||
|
} else {
|
||||||
|
$dsn['params'] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $dsn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调用驱动类的方法
|
||||||
|
* @access public
|
||||||
|
* @param string $method 方法名
|
||||||
|
* @param array $params 参数
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public static function __callStatic($method, $params)
|
||||||
|
{
|
||||||
|
return call_user_func_array([self::connect(), $method], $params);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace think;
|
||||||
|
|
||||||
|
class Env
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取环境变量值
|
||||||
|
* @access public
|
||||||
|
* @param string $name 环境变量名(支持二级 . 号分割)
|
||||||
|
* @param string $default 默认值
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public static function get($name, $default = null)
|
||||||
|
{
|
||||||
|
$result = getenv(ENV_PREFIX . strtoupper(str_replace('.', '_', $name)));
|
||||||
|
|
||||||
|
if (false !== $result) {
|
||||||
|
if ('false' === $result) {
|
||||||
|
$result = false;
|
||||||
|
} elseif ('true' === $result) {
|
||||||
|
$result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,136 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: 麦当苗儿 <zuojiazi@vip.qq.com> <http://zjzit.cn>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace think;
|
||||||
|
|
||||||
|
use think\console\Output as ConsoleOutput;
|
||||||
|
use think\exception\ErrorException;
|
||||||
|
use think\exception\Handle;
|
||||||
|
use think\exception\ThrowableError;
|
||||||
|
|
||||||
|
class Error
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 注册异常处理
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function register()
|
||||||
|
{
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
set_error_handler([__CLASS__, 'appError']);
|
||||||
|
set_exception_handler([__CLASS__, 'appException']);
|
||||||
|
register_shutdown_function([__CLASS__, 'appShutdown']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常处理
|
||||||
|
* @access public
|
||||||
|
* @param \Exception|\Throwable $e 异常
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function appException($e)
|
||||||
|
{
|
||||||
|
if (!$e instanceof \Exception) {
|
||||||
|
$e = new ThrowableError($e);
|
||||||
|
}
|
||||||
|
|
||||||
|
$handler = self::getExceptionHandler();
|
||||||
|
$handler->report($e);
|
||||||
|
|
||||||
|
if (IS_CLI) {
|
||||||
|
$handler->renderForConsole(new ConsoleOutput, $e);
|
||||||
|
} else {
|
||||||
|
$handler->render($e)->send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误处理
|
||||||
|
* @access public
|
||||||
|
* @param integer $errno 错误编号
|
||||||
|
* @param integer $errstr 详细错误信息
|
||||||
|
* @param string $errfile 出错的文件
|
||||||
|
* @param integer $errline 出错行号
|
||||||
|
* @return void
|
||||||
|
* @throws ErrorException
|
||||||
|
*/
|
||||||
|
public static function appError($errno, $errstr, $errfile = '', $errline = 0)
|
||||||
|
{
|
||||||
|
$exception = new ErrorException($errno, $errstr, $errfile, $errline);
|
||||||
|
|
||||||
|
// 符合异常处理的则将错误信息托管至 think\exception\ErrorException
|
||||||
|
if (error_reporting() & $errno) {
|
||||||
|
throw $exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
self::getExceptionHandler()->report($exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常中止处理
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function appShutdown()
|
||||||
|
{
|
||||||
|
// 将错误信息托管至 think\ErrorException
|
||||||
|
if (!is_null($error = error_get_last()) && self::isFatal($error['type'])) {
|
||||||
|
self::appException(new ErrorException(
|
||||||
|
$error['type'], $error['message'], $error['file'], $error['line']
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入日志
|
||||||
|
Log::save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确定错误类型是否致命
|
||||||
|
* @access protected
|
||||||
|
* @param int $type 错误类型
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected static function isFatal($type)
|
||||||
|
{
|
||||||
|
return in_array($type, [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取异常处理的实例
|
||||||
|
* @access public
|
||||||
|
* @return Handle
|
||||||
|
*/
|
||||||
|
public static function getExceptionHandler()
|
||||||
|
{
|
||||||
|
static $handle;
|
||||||
|
|
||||||
|
if (!$handle) {
|
||||||
|
// 异常处理 handle
|
||||||
|
$class = Config::get('exception_handle');
|
||||||
|
|
||||||
|
if ($class && is_string($class) && class_exists($class) &&
|
||||||
|
is_subclass_of($class, "\\think\\exception\\Handle")
|
||||||
|
) {
|
||||||
|
$handle = new $class;
|
||||||
|
} else {
|
||||||
|
$handle = new Handle;
|
||||||
|
|
||||||
|
if ($class instanceof \Closure) {
|
||||||
|
$handle->setRender($class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: 麦当苗儿 <zuojiazi@vip.qq.com> <http://zjzit.cn>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace think;
|
||||||
|
|
||||||
|
class Exception extends \Exception
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array 保存异常页面显示的额外 Debug 数据
|
||||||
|
*/
|
||||||
|
protected $data = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置异常额外的 Debug 数据
|
||||||
|
* 数据将会显示为下面的格式
|
||||||
|
*
|
||||||
|
* Exception Data
|
||||||
|
* --------------------------------------------------
|
||||||
|
* Label 1
|
||||||
|
* key1 value1
|
||||||
|
* key2 value2
|
||||||
|
* Label 2
|
||||||
|
* key1 value1
|
||||||
|
* key2 value2
|
||||||
|
*
|
||||||
|
* @access protected
|
||||||
|
* @param string $label 数据分类,用于异常页面显示
|
||||||
|
* @param array $data 需要显示的数据,必须为关联数组
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
final protected function setData($label, array $data)
|
||||||
|
{
|
||||||
|
$this->data[$label] = $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取异常额外 Debug 数据
|
||||||
|
* 主要用于输出到异常页面便于调试
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
final public function getData()
|
||||||
|
{
|
||||||
|
return $this->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,478 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace think;
|
||||||
|
|
||||||
|
use SplFileObject;
|
||||||
|
|
||||||
|
class File extends SplFileObject
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string 错误信息
|
||||||
|
*/
|
||||||
|
private $error = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string 当前完整文件名
|
||||||
|
*/
|
||||||
|
protected $filename;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string 上传文件名
|
||||||
|
*/
|
||||||
|
protected $saveName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string 文件上传命名规则
|
||||||
|
*/
|
||||||
|
protected $rule = 'date';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array 文件上传验证规则
|
||||||
|
*/
|
||||||
|
protected $validate = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool 单元测试
|
||||||
|
*/
|
||||||
|
protected $isTest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array 上传文件信息
|
||||||
|
*/
|
||||||
|
protected $info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array 文件 hash 信息
|
||||||
|
*/
|
||||||
|
protected $hash = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File constructor.
|
||||||
|
* @access public
|
||||||
|
* @param string $filename 文件名称
|
||||||
|
* @param string $mode 访问模式
|
||||||
|
*/
|
||||||
|
public function __construct($filename, $mode = 'r')
|
||||||
|
{
|
||||||
|
parent::__construct($filename, $mode);
|
||||||
|
$this->filename = $this->getRealPath() ?: $this->getPathname();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置是否是单元测试
|
||||||
|
* @access public
|
||||||
|
* @param bool $test 是否是测试
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function isTest($test = false)
|
||||||
|
{
|
||||||
|
$this->isTest = $test;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置上传信息
|
||||||
|
* @access public
|
||||||
|
* @param array $info 上传文件信息
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setUploadInfo($info)
|
||||||
|
{
|
||||||
|
$this->info = $info;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取上传文件的信息
|
||||||
|
* @access public
|
||||||
|
* @param string $name 信息名称
|
||||||
|
* @return array|string
|
||||||
|
*/
|
||||||
|
public function getInfo($name = '')
|
||||||
|
{
|
||||||
|
return isset($this->info[$name]) ? $this->info[$name] : $this->info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取上传文件的文件名
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getSaveName()
|
||||||
|
{
|
||||||
|
return $this->saveName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置上传文件的保存文件名
|
||||||
|
* @access public
|
||||||
|
* @param string $saveName 保存名称
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setSaveName($saveName)
|
||||||
|
{
|
||||||
|
$this->saveName = $saveName;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文件的哈希散列值
|
||||||
|
* @access public
|
||||||
|
* @param string $type 类型
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function hash($type = 'sha1')
|
||||||
|
{
|
||||||
|
if (!isset($this->hash[$type])) {
|
||||||
|
$this->hash[$type] = hash_file($type, $this->filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->hash[$type];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查目录是否可写
|
||||||
|
* @access protected
|
||||||
|
* @param string $path 目录
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
protected function checkPath($path)
|
||||||
|
{
|
||||||
|
if (is_dir($path) || mkdir($path, 0755, true)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->error = ['directory {:path} creation failed', ['path' => $path]];
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文件类型信息
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getMime()
|
||||||
|
{
|
||||||
|
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||||
|
|
||||||
|
return finfo_file($finfo, $this->filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置文件的命名规则
|
||||||
|
* @access public
|
||||||
|
* @param string $rule 文件命名规则
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function rule($rule)
|
||||||
|
{
|
||||||
|
$this->rule = $rule;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置上传文件的验证规则
|
||||||
|
* @access public
|
||||||
|
* @param array $rule 验证规则
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function validate(array $rule = [])
|
||||||
|
{
|
||||||
|
$this->validate = $rule;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测是否合法的上传文件
|
||||||
|
* @access public
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isValid()
|
||||||
|
{
|
||||||
|
return $this->isTest ? is_file($this->filename) : is_uploaded_file($this->filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测上传文件
|
||||||
|
* @access public
|
||||||
|
* @param array $rule 验证规则
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function check($rule = [])
|
||||||
|
{
|
||||||
|
$rule = $rule ?: $this->validate;
|
||||||
|
|
||||||
|
/* 检查文件大小 */
|
||||||
|
if (isset($rule['size']) && !$this->checkSize($rule['size'])) {
|
||||||
|
$this->error = 'filesize not match';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 检查文件 Mime 类型 */
|
||||||
|
if (isset($rule['type']) && !$this->checkMime($rule['type'])) {
|
||||||
|
$this->error = 'mimetype to upload is not allowed';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 检查文件后缀 */
|
||||||
|
if (isset($rule['ext']) && !$this->checkExt($rule['ext'])) {
|
||||||
|
$this->error = 'extensions to upload is not allowed';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 检查图像文件 */
|
||||||
|
if (!$this->checkImg()) {
|
||||||
|
$this->error = 'illegal image files';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测上传文件后缀
|
||||||
|
* @access public
|
||||||
|
* @param array|string $ext 允许后缀
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function checkExt($ext)
|
||||||
|
{
|
||||||
|
if (is_string($ext)) {
|
||||||
|
$ext = explode(',', $ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
$extension = strtolower(pathinfo($this->getInfo('name'), PATHINFO_EXTENSION));
|
||||||
|
|
||||||
|
return in_array($extension, $ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测图像文件
|
||||||
|
* @access public
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function checkImg()
|
||||||
|
{
|
||||||
|
$extension = strtolower(pathinfo($this->getInfo('name'), PATHINFO_EXTENSION));
|
||||||
|
|
||||||
|
// 如果上传的不是图片,或者是图片而且后缀确实符合图片类型则返回 true
|
||||||
|
return !in_array($extension, ['gif', 'jpg', 'jpeg', 'bmp', 'png', 'swf']) || in_array($this->getImageType($this->filename), [1, 2, 3, 4, 6, 13]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断图像类型
|
||||||
|
* @access protected
|
||||||
|
* @param string $image 图片名称
|
||||||
|
* @return bool|int
|
||||||
|
*/
|
||||||
|
protected function getImageType($image)
|
||||||
|
{
|
||||||
|
if (function_exists('exif_imagetype')) {
|
||||||
|
return exif_imagetype($image);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$info = getimagesize($image);
|
||||||
|
return $info ? $info[2] : false;
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测上传文件大小
|
||||||
|
* @access public
|
||||||
|
* @param integer $size 最大大小
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function checkSize($size)
|
||||||
|
{
|
||||||
|
return $this->getSize() <= $size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测上传文件类型
|
||||||
|
* @access public
|
||||||
|
* @param array|string $mime 允许类型
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function checkMime($mime)
|
||||||
|
{
|
||||||
|
$mime = is_string($mime) ? explode(',', $mime) : $mime;
|
||||||
|
|
||||||
|
return in_array(strtolower($this->getMime()), $mime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移动文件
|
||||||
|
* @access public
|
||||||
|
* @param string $path 保存路径
|
||||||
|
* @param string|bool $savename 保存的文件名 默认自动生成
|
||||||
|
* @param boolean $replace 同名文件是否覆盖
|
||||||
|
* @return false|File
|
||||||
|
*/
|
||||||
|
public function move($path, $savename = true, $replace = true)
|
||||||
|
{
|
||||||
|
// 文件上传失败,捕获错误代码
|
||||||
|
if (!empty($this->info['error'])) {
|
||||||
|
$this->error($this->info['error']);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检测合法性
|
||||||
|
if (!$this->isValid()) {
|
||||||
|
$this->error = 'upload illegal files';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证上传
|
||||||
|
if (!$this->check()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$path = rtrim($path, DS) . DS;
|
||||||
|
// 文件保存命名规则
|
||||||
|
$saveName = $this->buildSaveName($savename);
|
||||||
|
$filename = $path . $saveName;
|
||||||
|
|
||||||
|
// 检测目录
|
||||||
|
if (false === $this->checkPath(dirname($filename))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 不覆盖同名文件
|
||||||
|
if (!$replace && is_file($filename)) {
|
||||||
|
$this->error = ['has the same filename: {:filename}', ['filename' => $filename]];
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 移动文件 */
|
||||||
|
if ($this->isTest) {
|
||||||
|
rename($this->filename, $filename);
|
||||||
|
} elseif (!move_uploaded_file($this->filename, $filename)) {
|
||||||
|
$this->error = 'upload write error';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回 File 对象实例
|
||||||
|
$file = new self($filename);
|
||||||
|
$file->setSaveName($saveName)->setUploadInfo($this->info);
|
||||||
|
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取保存文件名
|
||||||
|
* @access protected
|
||||||
|
* @param string|bool $savename 保存的文件名 默认自动生成
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function buildSaveName($savename)
|
||||||
|
{
|
||||||
|
// 自动生成文件名
|
||||||
|
if (true === $savename) {
|
||||||
|
if ($this->rule instanceof \Closure) {
|
||||||
|
$savename = call_user_func_array($this->rule, [$this]);
|
||||||
|
} else {
|
||||||
|
switch ($this->rule) {
|
||||||
|
case 'date':
|
||||||
|
$savename = date('Ymd') . DS . md5(microtime(true));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (in_array($this->rule, hash_algos())) {
|
||||||
|
$hash = $this->hash($this->rule);
|
||||||
|
$savename = substr($hash, 0, 2) . DS . substr($hash, 2);
|
||||||
|
} elseif (is_callable($this->rule)) {
|
||||||
|
$savename = call_user_func($this->rule);
|
||||||
|
} else {
|
||||||
|
$savename = date('Ymd') . DS . md5(microtime(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elseif ('' === $savename || false === $savename) {
|
||||||
|
$savename = $this->getInfo('name');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strpos($savename, '.')) {
|
||||||
|
$savename .= '.' . pathinfo($this->getInfo('name'), PATHINFO_EXTENSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $savename;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取错误代码信息
|
||||||
|
* @access private
|
||||||
|
* @param int $errorNo 错误号
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
private function error($errorNo)
|
||||||
|
{
|
||||||
|
switch ($errorNo) {
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
$this->error = 'upload File size exceeds the maximum value';
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
$this->error = 'only the portion of file is uploaded';
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
$this->error = 'no file to uploaded';
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
$this->error = 'upload temp dir not found';
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
$this->error = 'file write error';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->error = 'unknown upload error';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取错误信息(支持多语言)
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getError()
|
||||||
|
{
|
||||||
|
if (is_array($this->error)) {
|
||||||
|
list($msg, $vars) = $this->error;
|
||||||
|
} else {
|
||||||
|
$msg = $this->error;
|
||||||
|
$vars = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return Lang::has($msg) ? Lang::get($msg, $vars) : $msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 魔法方法,获取文件的 hash 值
|
||||||
|
* @access public
|
||||||
|
* @param string $method 方法名
|
||||||
|
* @param mixed $args 调用参数
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __call($method, $args)
|
||||||
|
{
|
||||||
|
return $this->hash($method);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,677 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace think;
|
||||||
|
|
||||||
|
use think\exception\ClassNotFoundException;
|
||||||
|
|
||||||
|
class Loader
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array 实例数组
|
||||||
|
*/
|
||||||
|
protected static $instance = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array 类名映射
|
||||||
|
*/
|
||||||
|
protected static $classMap = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array 命名空间别名
|
||||||
|
*/
|
||||||
|
protected static $namespaceAlias = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array PSR-4 命名空间前缀长度映射
|
||||||
|
*/
|
||||||
|
private static $prefixLengthsPsr4 = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array PSR-4 的加载目录
|
||||||
|
*/
|
||||||
|
private static $prefixDirsPsr4 = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array PSR-4 加载失败的回退目录
|
||||||
|
*/
|
||||||
|
private static $fallbackDirsPsr4 = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array PSR-0 命名空间前缀映射
|
||||||
|
*/
|
||||||
|
private static $prefixesPsr0 = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array PSR-0 加载失败的回退目录
|
||||||
|
*/
|
||||||
|
private static $fallbackDirsPsr0 = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array 需要加载的文件
|
||||||
|
*/
|
||||||
|
private static $files = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动加载
|
||||||
|
* @access public
|
||||||
|
* @param string $class 类名
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function autoload($class)
|
||||||
|
{
|
||||||
|
// 检测命名空间别名
|
||||||
|
if (!empty(self::$namespaceAlias)) {
|
||||||
|
$namespace = dirname($class);
|
||||||
|
if (isset(self::$namespaceAlias[$namespace])) {
|
||||||
|
$original = self::$namespaceAlias[$namespace] . '\\' . basename($class);
|
||||||
|
if (class_exists($original)) {
|
||||||
|
return class_alias($original, $class, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($file = self::findFile($class)) {
|
||||||
|
// 非 Win 环境不严格区分大小写
|
||||||
|
if (!IS_WIN || pathinfo($file, PATHINFO_FILENAME) == pathinfo(realpath($file), PATHINFO_FILENAME)) {
|
||||||
|
__include_file($file);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找文件
|
||||||
|
* @access private
|
||||||
|
* @param string $class 类名
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
private static function findFile($class)
|
||||||
|
{
|
||||||
|
// 类库映射
|
||||||
|
if (!empty(self::$classMap[$class])) {
|
||||||
|
return self::$classMap[$class];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找 PSR-4
|
||||||
|
$logicalPathPsr4 = strtr($class, '\\', DS) . EXT;
|
||||||
|
$first = $class[0];
|
||||||
|
|
||||||
|
if (isset(self::$prefixLengthsPsr4[$first])) {
|
||||||
|
foreach (self::$prefixLengthsPsr4[$first] as $prefix => $length) {
|
||||||
|
if (0 === strpos($class, $prefix)) {
|
||||||
|
foreach (self::$prefixDirsPsr4[$prefix] as $dir) {
|
||||||
|
if (is_file($file = $dir . DS . substr($logicalPathPsr4, $length))) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找 PSR-4 fallback dirs
|
||||||
|
foreach (self::$fallbackDirsPsr4 as $dir) {
|
||||||
|
if (is_file($file = $dir . DS . $logicalPathPsr4)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找 PSR-0
|
||||||
|
if (false !== $pos = strrpos($class, '\\')) {
|
||||||
|
// namespace class name
|
||||||
|
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||||
|
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DS);
|
||||||
|
} else {
|
||||||
|
// PEAR-like class name
|
||||||
|
$logicalPathPsr0 = strtr($class, '_', DS) . EXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset(self::$prefixesPsr0[$first])) {
|
||||||
|
foreach (self::$prefixesPsr0[$first] as $prefix => $dirs) {
|
||||||
|
if (0 === strpos($class, $prefix)) {
|
||||||
|
foreach ($dirs as $dir) {
|
||||||
|
if (is_file($file = $dir . DS . $logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找 PSR-0 fallback dirs
|
||||||
|
foreach (self::$fallbackDirsPsr0 as $dir) {
|
||||||
|
if (is_file($file = $dir . DS . $logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 找不到则设置映射为 false 并返回
|
||||||
|
return self::$classMap[$class] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册 classmap
|
||||||
|
* @access public
|
||||||
|
* @param string|array $class 类名
|
||||||
|
* @param string $map 映射
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function addClassMap($class, $map = '')
|
||||||
|
{
|
||||||
|
if (is_array($class)) {
|
||||||
|
self::$classMap = array_merge(self::$classMap, $class);
|
||||||
|
} else {
|
||||||
|
self::$classMap[$class] = $map;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册命名空间
|
||||||
|
* @access public
|
||||||
|
* @param string|array $namespace 命名空间
|
||||||
|
* @param string $path 路径
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function addNamespace($namespace, $path = '')
|
||||||
|
{
|
||||||
|
if (is_array($namespace)) {
|
||||||
|
foreach ($namespace as $prefix => $paths) {
|
||||||
|
self::addPsr4($prefix . '\\', rtrim($paths, DS), true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self::addPsr4($namespace . '\\', rtrim($path, DS), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加 PSR-0 命名空间
|
||||||
|
* @access private
|
||||||
|
* @param array|string $prefix 空间前缀
|
||||||
|
* @param array $paths 路径
|
||||||
|
* @param bool $prepend 预先设置的优先级更高
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private static function addPsr0($prefix, $paths, $prepend = false)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
self::$fallbackDirsPsr0 = $prepend ?
|
||||||
|
array_merge((array) $paths, self::$fallbackDirsPsr0) :
|
||||||
|
array_merge(self::$fallbackDirsPsr0, (array) $paths);
|
||||||
|
} else {
|
||||||
|
$first = $prefix[0];
|
||||||
|
|
||||||
|
if (!isset(self::$prefixesPsr0[$first][$prefix])) {
|
||||||
|
self::$prefixesPsr0[$first][$prefix] = (array) $paths;
|
||||||
|
} else {
|
||||||
|
self::$prefixesPsr0[$first][$prefix] = $prepend ?
|
||||||
|
array_merge((array) $paths, self::$prefixesPsr0[$first][$prefix]) :
|
||||||
|
array_merge(self::$prefixesPsr0[$first][$prefix], (array) $paths);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加 PSR-4 空间
|
||||||
|
* @access private
|
||||||
|
* @param array|string $prefix 空间前缀
|
||||||
|
* @param string $paths 路径
|
||||||
|
* @param bool $prepend 预先设置的优先级更高
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private static function addPsr4($prefix, $paths, $prepend = false)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
// Register directories for the root namespace.
|
||||||
|
self::$fallbackDirsPsr4 = $prepend ?
|
||||||
|
array_merge((array) $paths, self::$fallbackDirsPsr4) :
|
||||||
|
array_merge(self::$fallbackDirsPsr4, (array) $paths);
|
||||||
|
|
||||||
|
} elseif (!isset(self::$prefixDirsPsr4[$prefix])) {
|
||||||
|
// Register directories for a new namespace.
|
||||||
|
$length = strlen($prefix);
|
||||||
|
if ('\\' !== $prefix[$length - 1]) {
|
||||||
|
throw new \InvalidArgumentException(
|
||||||
|
"A non-empty PSR-4 prefix must end with a namespace separator."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||||
|
self::$prefixDirsPsr4[$prefix] = (array) $paths;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
self::$prefixDirsPsr4[$prefix] = $prepend ?
|
||||||
|
// Prepend directories for an already registered namespace.
|
||||||
|
array_merge((array) $paths, self::$prefixDirsPsr4[$prefix]) :
|
||||||
|
// Append directories for an already registered namespace.
|
||||||
|
array_merge(self::$prefixDirsPsr4[$prefix], (array) $paths);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册命名空间别名
|
||||||
|
* @access public
|
||||||
|
* @param array|string $namespace 命名空间
|
||||||
|
* @param string $original 源文件
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function addNamespaceAlias($namespace, $original = '')
|
||||||
|
{
|
||||||
|
if (is_array($namespace)) {
|
||||||
|
self::$namespaceAlias = array_merge(self::$namespaceAlias, $namespace);
|
||||||
|
} else {
|
||||||
|
self::$namespaceAlias[$namespace] = $original;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册自动加载机制
|
||||||
|
* @access public
|
||||||
|
* @param callable $autoload 自动加载处理方法
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function register($autoload = null)
|
||||||
|
{
|
||||||
|
// 注册系统自动加载
|
||||||
|
spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true);
|
||||||
|
|
||||||
|
// Composer 自动加载支持
|
||||||
|
if (is_dir(VENDOR_PATH . 'composer')) {
|
||||||
|
if (PHP_VERSION_ID >= 50600 && is_file(VENDOR_PATH . 'composer' . DS . 'autoload_static.php')) {
|
||||||
|
require VENDOR_PATH . 'composer' . DS . 'autoload_static.php';
|
||||||
|
|
||||||
|
$declaredClass = get_declared_classes();
|
||||||
|
$composerClass = array_pop($declaredClass);
|
||||||
|
|
||||||
|
foreach (['prefixLengthsPsr4', 'prefixDirsPsr4', 'fallbackDirsPsr4', 'prefixesPsr0', 'fallbackDirsPsr0', 'classMap', 'files'] as $attr) {
|
||||||
|
if (property_exists($composerClass, $attr)) {
|
||||||
|
self::${$attr} = $composerClass::${$attr};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self::registerComposerLoader();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册命名空间定义
|
||||||
|
self::addNamespace([
|
||||||
|
'think' => LIB_PATH . 'think' . DS,
|
||||||
|
'behavior' => LIB_PATH . 'behavior' . DS,
|
||||||
|
'traits' => LIB_PATH . 'traits' . DS,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 加载类库映射文件
|
||||||
|
if (is_file(RUNTIME_PATH . 'classmap' . EXT)) {
|
||||||
|
self::addClassMap(__include_file(RUNTIME_PATH . 'classmap' . EXT));
|
||||||
|
}
|
||||||
|
|
||||||
|
self::loadComposerAutoloadFiles();
|
||||||
|
|
||||||
|
// 自动加载 extend 目录
|
||||||
|
self::$fallbackDirsPsr4[] = rtrim(EXTEND_PATH, DS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册 composer 自动加载
|
||||||
|
* @access private
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private static function registerComposerLoader()
|
||||||
|
{
|
||||||
|
if (is_file(VENDOR_PATH . 'composer/autoload_namespaces.php')) {
|
||||||
|
$map = require VENDOR_PATH . 'composer/autoload_namespaces.php';
|
||||||
|
foreach ($map as $namespace => $path) {
|
||||||
|
self::addPsr0($namespace, $path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_file(VENDOR_PATH . 'composer/autoload_psr4.php')) {
|
||||||
|
$map = require VENDOR_PATH . 'composer/autoload_psr4.php';
|
||||||
|
foreach ($map as $namespace => $path) {
|
||||||
|
self::addPsr4($namespace, $path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_file(VENDOR_PATH . 'composer/autoload_classmap.php')) {
|
||||||
|
$classMap = require VENDOR_PATH . 'composer/autoload_classmap.php';
|
||||||
|
if ($classMap) {
|
||||||
|
self::addClassMap($classMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_file(VENDOR_PATH . 'composer/autoload_files.php')) {
|
||||||
|
self::$files = require VENDOR_PATH . 'composer/autoload_files.php';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载composer autofile文件
|
||||||
|
public static function loadComposerAutoloadFiles()
|
||||||
|
{
|
||||||
|
foreach (self::$files as $fileIdentifier => $file) {
|
||||||
|
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||||
|
__require_file($file);
|
||||||
|
|
||||||
|
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入所需的类库 同 Java 的 Import 本函数有缓存功能
|
||||||
|
* @access public
|
||||||
|
* @param string $class 类库命名空间字符串
|
||||||
|
* @param string $baseUrl 起始路径
|
||||||
|
* @param string $ext 导入的文件扩展名
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function import($class, $baseUrl = '', $ext = EXT)
|
||||||
|
{
|
||||||
|
static $_file = [];
|
||||||
|
$key = $class . $baseUrl;
|
||||||
|
$class = str_replace(['.', '#'], [DS, '.'], $class);
|
||||||
|
|
||||||
|
if (isset($_file[$key])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($baseUrl)) {
|
||||||
|
list($name, $class) = explode(DS, $class, 2);
|
||||||
|
|
||||||
|
if (isset(self::$prefixDirsPsr4[$name . '\\'])) {
|
||||||
|
// 注册的命名空间
|
||||||
|
$baseUrl = self::$prefixDirsPsr4[$name . '\\'];
|
||||||
|
} elseif ('@' == $name) {
|
||||||
|
// 加载当前模块应用类库
|
||||||
|
$baseUrl = App::$modulePath;
|
||||||
|
} elseif (is_dir(EXTEND_PATH . $name)) {
|
||||||
|
$baseUrl = EXTEND_PATH . $name . DS;
|
||||||
|
} else {
|
||||||
|
// 加载其它模块的类库
|
||||||
|
$baseUrl = APP_PATH . $name . DS;
|
||||||
|
}
|
||||||
|
} elseif (substr($baseUrl, -1) != DS) {
|
||||||
|
$baseUrl .= DS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果类存在则导入类库文件
|
||||||
|
if (is_array($baseUrl)) {
|
||||||
|
foreach ($baseUrl as $path) {
|
||||||
|
if (is_file($filename = $path . DS . $class . $ext)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$filename = $baseUrl . $class . $ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($filename) &&
|
||||||
|
is_file($filename) &&
|
||||||
|
(!IS_WIN || pathinfo($filename, PATHINFO_FILENAME) == pathinfo(realpath($filename), PATHINFO_FILENAME))
|
||||||
|
) {
|
||||||
|
__include_file($filename);
|
||||||
|
$_file[$key] = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实例化(分层)模型
|
||||||
|
* @access public
|
||||||
|
* @param string $name Model名称
|
||||||
|
* @param string $layer 业务层名称
|
||||||
|
* @param bool $appendSuffix 是否添加类名后缀
|
||||||
|
* @param string $common 公共模块名
|
||||||
|
* @return object
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
*/
|
||||||
|
public static function model($name = '', $layer = 'model', $appendSuffix = false, $common = 'common')
|
||||||
|
{
|
||||||
|
$uid = $name . $layer;
|
||||||
|
|
||||||
|
if (isset(self::$instance[$uid])) {
|
||||||
|
return self::$instance[$uid];
|
||||||
|
}
|
||||||
|
|
||||||
|
list($module, $class) = self::getModuleAndClass($name, $layer, $appendSuffix);
|
||||||
|
|
||||||
|
if (class_exists($class)) {
|
||||||
|
$model = new $class();
|
||||||
|
} else {
|
||||||
|
$class = str_replace('\\' . $module . '\\', '\\' . $common . '\\', $class);
|
||||||
|
|
||||||
|
if (class_exists($class)) {
|
||||||
|
$model = new $class();
|
||||||
|
} else {
|
||||||
|
throw new ClassNotFoundException('class not exists:' . $class, $class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$instance[$uid] = $model;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实例化(分层)控制器 格式:[模块名/]控制器名
|
||||||
|
* @access public
|
||||||
|
* @param string $name 资源地址
|
||||||
|
* @param string $layer 控制层名称
|
||||||
|
* @param bool $appendSuffix 是否添加类名后缀
|
||||||
|
* @param string $empty 空控制器名称
|
||||||
|
* @return object
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
*/
|
||||||
|
public static function controller($name, $layer = 'controller', $appendSuffix = false, $empty = '')
|
||||||
|
{
|
||||||
|
list($module, $class) = self::getModuleAndClass($name, $layer, $appendSuffix);
|
||||||
|
|
||||||
|
if (class_exists($class)) {
|
||||||
|
return App::invokeClass($class);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($empty) {
|
||||||
|
$emptyClass = self::parseClass($module, $layer, $empty, $appendSuffix);
|
||||||
|
|
||||||
|
if (class_exists($emptyClass)) {
|
||||||
|
return new $emptyClass(Request::instance());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ClassNotFoundException('class not exists:' . $class, $class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实例化验证类 格式:[模块名/]验证器名
|
||||||
|
* @access public
|
||||||
|
* @param string $name 资源地址
|
||||||
|
* @param string $layer 验证层名称
|
||||||
|
* @param bool $appendSuffix 是否添加类名后缀
|
||||||
|
* @param string $common 公共模块名
|
||||||
|
* @return object|false
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
*/
|
||||||
|
public static function validate($name = '', $layer = 'validate', $appendSuffix = false, $common = 'common')
|
||||||
|
{
|
||||||
|
$name = $name ?: Config::get('default_validate');
|
||||||
|
|
||||||
|
if (empty($name)) {
|
||||||
|
return new Validate;
|
||||||
|
}
|
||||||
|
|
||||||
|
$uid = $name . $layer;
|
||||||
|
if (isset(self::$instance[$uid])) {
|
||||||
|
return self::$instance[$uid];
|
||||||
|
}
|
||||||
|
|
||||||
|
list($module, $class) = self::getModuleAndClass($name, $layer, $appendSuffix);
|
||||||
|
|
||||||
|
if (class_exists($class)) {
|
||||||
|
$validate = new $class;
|
||||||
|
} else {
|
||||||
|
$class = str_replace('\\' . $module . '\\', '\\' . $common . '\\', $class);
|
||||||
|
|
||||||
|
if (class_exists($class)) {
|
||||||
|
$validate = new $class;
|
||||||
|
} else {
|
||||||
|
throw new ClassNotFoundException('class not exists:' . $class, $class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$instance[$uid] = $validate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析模块和类名
|
||||||
|
* @access protected
|
||||||
|
* @param string $name 资源地址
|
||||||
|
* @param string $layer 验证层名称
|
||||||
|
* @param bool $appendSuffix 是否添加类名后缀
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected static function getModuleAndClass($name, $layer, $appendSuffix)
|
||||||
|
{
|
||||||
|
if (false !== strpos($name, '\\')) {
|
||||||
|
$module = Request::instance()->module();
|
||||||
|
$class = $name;
|
||||||
|
} else {
|
||||||
|
if (strpos($name, '/')) {
|
||||||
|
list($module, $name) = explode('/', $name, 2);
|
||||||
|
} else {
|
||||||
|
$module = Request::instance()->module();
|
||||||
|
}
|
||||||
|
|
||||||
|
$class = self::parseClass($module, $layer, $name, $appendSuffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$module, $class];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据库初始化 并取得数据库类实例
|
||||||
|
* @access public
|
||||||
|
* @param mixed $config 数据库配置
|
||||||
|
* @param bool|string $name 连接标识 true 强制重新连接
|
||||||
|
* @return \think\db\Connection
|
||||||
|
*/
|
||||||
|
public static function db($config = [], $name = false)
|
||||||
|
{
|
||||||
|
return Db::connect($config, $name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 远程调用模块的操作方法 参数格式 [模块/控制器/]操作
|
||||||
|
* @access public
|
||||||
|
* @param string $url 调用地址
|
||||||
|
* @param string|array $vars 调用参数 支持字符串和数组
|
||||||
|
* @param string $layer 要调用的控制层名称
|
||||||
|
* @param bool $appendSuffix 是否添加类名后缀
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public static function action($url, $vars = [], $layer = 'controller', $appendSuffix = false)
|
||||||
|
{
|
||||||
|
$info = pathinfo($url);
|
||||||
|
$action = $info['basename'];
|
||||||
|
$module = '.' != $info['dirname'] ? $info['dirname'] : Request::instance()->controller();
|
||||||
|
$class = self::controller($module, $layer, $appendSuffix);
|
||||||
|
|
||||||
|
if ($class) {
|
||||||
|
if (is_scalar($vars)) {
|
||||||
|
if (strpos($vars, '=')) {
|
||||||
|
parse_str($vars, $vars);
|
||||||
|
} else {
|
||||||
|
$vars = [$vars];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return App::invokeMethod([$class, $action . Config::get('action_suffix')], $vars);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串命名风格转换
|
||||||
|
* type 0 将 Java 风格转换为 C 的风格 1 将 C 风格转换为 Java 的风格
|
||||||
|
* @access public
|
||||||
|
* @param string $name 字符串
|
||||||
|
* @param integer $type 转换类型
|
||||||
|
* @param bool $ucfirst 首字母是否大写(驼峰规则)
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function parseName($name, $type = 0, $ucfirst = true)
|
||||||
|
{
|
||||||
|
if ($type) {
|
||||||
|
$name = preg_replace_callback('/_([a-zA-Z])/', function ($match) {
|
||||||
|
return strtoupper($match[1]);
|
||||||
|
}, $name);
|
||||||
|
|
||||||
|
return $ucfirst ? ucfirst($name) : lcfirst($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析应用类的类名
|
||||||
|
* @access public
|
||||||
|
* @param string $module 模块名
|
||||||
|
* @param string $layer 层名 controller model ...
|
||||||
|
* @param string $name 类名
|
||||||
|
* @param bool $appendSuffix 是否添加类名后缀
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function parseClass($module, $layer, $name, $appendSuffix = false)
|
||||||
|
{
|
||||||
|
|
||||||
|
$array = explode('\\', str_replace(['/', '.'], '\\', $name));
|
||||||
|
$class = self::parseName(array_pop($array), 1);
|
||||||
|
$class = $class . (App::$suffix || $appendSuffix ? ucfirst($layer) : '');
|
||||||
|
$path = $array ? implode('\\', $array) . '\\' : '';
|
||||||
|
|
||||||
|
return App::$namespace . '\\' .
|
||||||
|
($module ? $module . '\\' : '') .
|
||||||
|
$layer . '\\' . $path . $class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化类的实例
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function clearInstance()
|
||||||
|
{
|
||||||
|
self::$instance = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 作用范围隔离
|
||||||
|
|
||||||
|
/**
|
||||||
|
* include
|
||||||
|
* @param string $file 文件路径
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
function __include_file($file)
|
||||||
|
{
|
||||||
|
return include $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* require
|
||||||
|
* @param string $file 文件路径
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
function __require_file($file)
|
||||||
|
{
|
||||||
|
return require $file;
|
||||||
|
}
|
||||||
@ -0,0 +1,237 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace think;
|
||||||
|
|
||||||
|
use think\exception\ClassNotFoundException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Log
|
||||||
|
* @package think
|
||||||
|
*
|
||||||
|
* @method void log($msg) static 记录一般日志
|
||||||
|
* @method void error($msg) static 记录错误日志
|
||||||
|
* @method void info($msg) static 记录一般信息日志
|
||||||
|
* @method void sql($msg) static 记录 SQL 查询日志
|
||||||
|
* @method void notice($msg) static 记录提示日志
|
||||||
|
* @method void alert($msg) static 记录报警日志
|
||||||
|
*/
|
||||||
|
class Log
|
||||||
|
{
|
||||||
|
const LOG = 'log';
|
||||||
|
const ERROR = 'error';
|
||||||
|
const INFO = 'info';
|
||||||
|
const SQL = 'sql';
|
||||||
|
const NOTICE = 'notice';
|
||||||
|
const ALERT = 'alert';
|
||||||
|
const DEBUG = 'debug';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array 日志信息
|
||||||
|
*/
|
||||||
|
protected static $log = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array 配置参数
|
||||||
|
*/
|
||||||
|
protected static $config = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array 日志类型
|
||||||
|
*/
|
||||||
|
protected static $type = ['log', 'error', 'info', 'sql', 'notice', 'alert', 'debug'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var log\driver\File|log\driver\Test|log\driver\Socket 日志写入驱动
|
||||||
|
*/
|
||||||
|
protected static $driver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string 当前日志授权 key
|
||||||
|
*/
|
||||||
|
protected static $key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志初始化
|
||||||
|
* @access public
|
||||||
|
* @param array $config 配置参数
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function init($config = [])
|
||||||
|
{
|
||||||
|
$type = isset($config['type']) ? $config['type'] : 'File';
|
||||||
|
$class = false !== strpos($type, '\\') ? $type : '\\think\\log\\driver\\' . ucwords($type);
|
||||||
|
|
||||||
|
self::$config = $config;
|
||||||
|
unset($config['type']);
|
||||||
|
|
||||||
|
if (class_exists($class)) {
|
||||||
|
self::$driver = new $class($config);
|
||||||
|
} else {
|
||||||
|
throw new ClassNotFoundException('class not exists:' . $class, $class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录初始化信息
|
||||||
|
App::$debug && Log::record('[ LOG ] INIT ' . $type, 'info');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取日志信息
|
||||||
|
* @access public
|
||||||
|
* @param string $type 信息类型
|
||||||
|
* @return array|string
|
||||||
|
*/
|
||||||
|
public static function getLog($type = '')
|
||||||
|
{
|
||||||
|
return $type ? self::$log[$type] : self::$log;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录调试信息
|
||||||
|
* @access public
|
||||||
|
* @param mixed $msg 调试信息
|
||||||
|
* @param string $type 信息类型
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function record($msg, $type = 'log')
|
||||||
|
{
|
||||||
|
self::$log[$type][] = $msg;
|
||||||
|
|
||||||
|
// 命令行下面日志写入改进
|
||||||
|
IS_CLI && self::save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空日志信息
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function clear()
|
||||||
|
{
|
||||||
|
self::$log = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置当前日志记录的授权 key
|
||||||
|
* @access public
|
||||||
|
* @param string $key 授权 key
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function key($key)
|
||||||
|
{
|
||||||
|
self::$key = $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查日志写入权限
|
||||||
|
* @access public
|
||||||
|
* @param array $config 当前日志配置参数
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function check($config)
|
||||||
|
{
|
||||||
|
return !self::$key || empty($config['allow_key']) || in_array(self::$key, $config['allow_key']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存调试信息
|
||||||
|
* @access public
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function save()
|
||||||
|
{
|
||||||
|
// 没有需要保存的记录则直接返回
|
||||||
|
if (empty(self::$log)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_null(self::$driver) && self::init(Config::get('log'));
|
||||||
|
|
||||||
|
// 检测日志写入权限
|
||||||
|
if (!self::check(self::$config)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty(self::$config['level'])) {
|
||||||
|
// 获取全部日志
|
||||||
|
$log = self::$log;
|
||||||
|
if (!App::$debug && isset($log['debug'])) {
|
||||||
|
unset($log['debug']);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 记录允许级别
|
||||||
|
$log = [];
|
||||||
|
foreach (self::$config['level'] as $level) {
|
||||||
|
if (isset(self::$log[$level])) {
|
||||||
|
$log[$level] = self::$log[$level];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result = self::$driver->save($log, true)) {
|
||||||
|
self::$log = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
Hook::listen('log_write_done', $log);
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实时写入日志信息 并支持行为
|
||||||
|
* @access public
|
||||||
|
* @param mixed $msg 调试信息
|
||||||
|
* @param string $type 信息类型
|
||||||
|
* @param bool $force 是否强制写入
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function write($msg, $type = 'log', $force = false)
|
||||||
|
{
|
||||||
|
$log = self::$log;
|
||||||
|
|
||||||
|
// 如果不是强制写入,而且信息类型不在可记录的类别中则直接返回 false 不做记录
|
||||||
|
if (true !== $force && !empty(self::$config['level']) && !in_array($type, self::$config['level'])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 封装日志信息
|
||||||
|
$log[$type][] = $msg;
|
||||||
|
|
||||||
|
// 监听 log_write
|
||||||
|
Hook::listen('log_write', $log);
|
||||||
|
|
||||||
|
is_null(self::$driver) && self::init(Config::get('log'));
|
||||||
|
|
||||||
|
// 写入日志
|
||||||
|
if ($result = self::$driver->save($log, false)) {
|
||||||
|
self::$log = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 静态方法调用
|
||||||
|
* @access public
|
||||||
|
* @param string $method 调用方法
|
||||||
|
* @param mixed $args 参数
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function __callStatic($method, $args)
|
||||||
|
{
|
||||||
|
if (in_array($method, self::$type)) {
|
||||||
|
array_push($args, $method);
|
||||||
|
|
||||||
|
call_user_func_array('\\think\\Log::record', $args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,409 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: zhangyajun <448901948@qq.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace think;
|
||||||
|
|
||||||
|
use ArrayAccess;
|
||||||
|
use ArrayIterator;
|
||||||
|
use Countable;
|
||||||
|
use IteratorAggregate;
|
||||||
|
use JsonSerializable;
|
||||||
|
use Traversable;
|
||||||
|
|
||||||
|
abstract class Paginator implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable
|
||||||
|
{
|
||||||
|
/** @var bool 是否为简洁模式 */
|
||||||
|
protected $simple = false;
|
||||||
|
|
||||||
|
/** @var Collection 数据集 */
|
||||||
|
protected $items;
|
||||||
|
|
||||||
|
/** @var integer 当前页 */
|
||||||
|
protected $currentPage;
|
||||||
|
|
||||||
|
/** @var integer 最后一页 */
|
||||||
|
protected $lastPage;
|
||||||
|
|
||||||
|
/** @var integer|null 数据总数 */
|
||||||
|
protected $total;
|
||||||
|
|
||||||
|
/** @var integer 每页的数量 */
|
||||||
|
protected $listRows;
|
||||||
|
|
||||||
|
/** @var bool 是否有下一页 */
|
||||||
|
protected $hasMore;
|
||||||
|
|
||||||
|
/** @var array 一些配置 */
|
||||||
|
protected $options = [
|
||||||
|
'var_page' => 'page',
|
||||||
|
'path' => '/',
|
||||||
|
'query' => [],
|
||||||
|
'fragment' => '',
|
||||||
|
];
|
||||||
|
|
||||||
|
/** @var mixed simple模式下的下个元素 */
|
||||||
|
protected $nextItem;
|
||||||
|
|
||||||
|
public function __construct($items, $listRows, $currentPage = null, $total = null, $simple = false, $options = [])
|
||||||
|
{
|
||||||
|
$this->options = array_merge($this->options, $options);
|
||||||
|
|
||||||
|
$this->options['path'] = '/' != $this->options['path'] ? rtrim($this->options['path'], '/') : $this->options['path'];
|
||||||
|
|
||||||
|
$this->simple = $simple;
|
||||||
|
$this->listRows = $listRows;
|
||||||
|
|
||||||
|
if (!$items instanceof Collection) {
|
||||||
|
$items = Collection::make($items);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($simple) {
|
||||||
|
$this->currentPage = $this->setCurrentPage($currentPage);
|
||||||
|
$this->hasMore = count($items) > ($this->listRows);
|
||||||
|
if ($this->hasMore) {
|
||||||
|
$this->nextItem = $items->slice($this->listRows, 1);
|
||||||
|
}
|
||||||
|
$items = $items->slice(0, $this->listRows);
|
||||||
|
} else {
|
||||||
|
$this->total = $total;
|
||||||
|
$this->lastPage = (int) ceil($total / $listRows);
|
||||||
|
$this->currentPage = $this->setCurrentPage($currentPage);
|
||||||
|
$this->hasMore = $this->currentPage < $this->lastPage;
|
||||||
|
}
|
||||||
|
$this->items = $items;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $items
|
||||||
|
* @param $listRows
|
||||||
|
* @param null $currentPage
|
||||||
|
* @param bool $simple
|
||||||
|
* @param null $total
|
||||||
|
* @param array $options
|
||||||
|
* @return Paginator
|
||||||
|
*/
|
||||||
|
public static function make($items, $listRows, $currentPage = null, $total = null, $simple = false, $options = [])
|
||||||
|
{
|
||||||
|
return new static($items, $listRows, $currentPage, $total, $simple, $options);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function setCurrentPage($currentPage)
|
||||||
|
{
|
||||||
|
if (!$this->simple && $currentPage > $this->lastPage) {
|
||||||
|
return $this->lastPage > 0 ? $this->lastPage : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $currentPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取页码对应的链接
|
||||||
|
*
|
||||||
|
* @param $page
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function url($page)
|
||||||
|
{
|
||||||
|
if ($page <= 0) {
|
||||||
|
$page = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strpos($this->options['path'], '[PAGE]') === false) {
|
||||||
|
$parameters = [$this->options['var_page'] => $page];
|
||||||
|
$path = $this->options['path'];
|
||||||
|
} else {
|
||||||
|
$parameters = [];
|
||||||
|
$path = str_replace('[PAGE]', $page, $this->options['path']);
|
||||||
|
}
|
||||||
|
if (count($this->options['query']) > 0) {
|
||||||
|
$parameters = array_merge($this->options['query'], $parameters);
|
||||||
|
}
|
||||||
|
$url = $path;
|
||||||
|
if (!empty($parameters)) {
|
||||||
|
$url .= '?' . http_build_query($parameters, null, '&');
|
||||||
|
}
|
||||||
|
return $url . $this->buildFragment();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动获取当前页码
|
||||||
|
* @param string $varPage
|
||||||
|
* @param int $default
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public static function getCurrentPage($varPage = 'page', $default = 1)
|
||||||
|
{
|
||||||
|
$page = (int) Request::instance()->param($varPage);
|
||||||
|
|
||||||
|
if (filter_var($page, FILTER_VALIDATE_INT) !== false && $page >= 1) {
|
||||||
|
return $page;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动获取当前的path
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getCurrentPath()
|
||||||
|
{
|
||||||
|
return Request::instance()->baseUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function total()
|
||||||
|
{
|
||||||
|
if ($this->simple) {
|
||||||
|
throw new \DomainException('not support total');
|
||||||
|
}
|
||||||
|
return $this->total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function listRows()
|
||||||
|
{
|
||||||
|
return $this->listRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function currentPage()
|
||||||
|
{
|
||||||
|
return $this->currentPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function lastPage()
|
||||||
|
{
|
||||||
|
if ($this->simple) {
|
||||||
|
throw new \DomainException('not support last');
|
||||||
|
}
|
||||||
|
return $this->lastPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据是否足够分页
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function hasPages()
|
||||||
|
{
|
||||||
|
return !(1 == $this->currentPage && !$this->hasMore);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建一组分页链接
|
||||||
|
*
|
||||||
|
* @param int $start
|
||||||
|
* @param int $end
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getUrlRange($start, $end)
|
||||||
|
{
|
||||||
|
$urls = [];
|
||||||
|
|
||||||
|
for ($page = $start; $page <= $end; $page++) {
|
||||||
|
$urls[$page] = $this->url($page);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $urls;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置URL锚点
|
||||||
|
*
|
||||||
|
* @param string|null $fragment
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function fragment($fragment)
|
||||||
|
{
|
||||||
|
$this->options['fragment'] = $fragment;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加URL参数
|
||||||
|
*
|
||||||
|
* @param array|string $key
|
||||||
|
* @param string|null $value
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function appends($key, $value = null)
|
||||||
|
{
|
||||||
|
if (!is_array($key)) {
|
||||||
|
$queries = [$key => $value];
|
||||||
|
} else {
|
||||||
|
$queries = $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($queries as $k => $v) {
|
||||||
|
if ($k !== $this->options['var_page']) {
|
||||||
|
$this->options['query'][$k] = $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造锚点字符串
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function buildFragment()
|
||||||
|
{
|
||||||
|
return $this->options['fragment'] ? '#' . $this->options['fragment'] : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染分页html
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
abstract public function render();
|
||||||
|
|
||||||
|
public function items()
|
||||||
|
{
|
||||||
|
return $this->items->all();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCollection()
|
||||||
|
{
|
||||||
|
return $this->items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isEmpty()
|
||||||
|
{
|
||||||
|
return $this->items->isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 给每个元素执行个回调
|
||||||
|
*
|
||||||
|
* @param callable $callback
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function each(callable $callback)
|
||||||
|
{
|
||||||
|
foreach ($this->items as $key => $item) {
|
||||||
|
$result = $callback($item, $key);
|
||||||
|
if (false === $result) {
|
||||||
|
break;
|
||||||
|
} elseif (!is_object($item)) {
|
||||||
|
$this->items[$key] = $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve an external iterator
|
||||||
|
* @return Traversable An instance of an object implementing <b>Iterator</b> or
|
||||||
|
* <b>Traversable</b>
|
||||||
|
*/
|
||||||
|
public function getIterator()
|
||||||
|
{
|
||||||
|
return new ArrayIterator($this->items->all());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether a offset exists
|
||||||
|
* @param mixed $offset
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function offsetExists($offset)
|
||||||
|
{
|
||||||
|
return $this->items->offsetExists($offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offset to retrieve
|
||||||
|
* @param mixed $offset
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function offsetGet($offset)
|
||||||
|
{
|
||||||
|
return $this->items->offsetGet($offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offset to set
|
||||||
|
* @param mixed $offset
|
||||||
|
* @param mixed $value
|
||||||
|
*/
|
||||||
|
public function offsetSet($offset, $value)
|
||||||
|
{
|
||||||
|
$this->items->offsetSet($offset, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offset to unset
|
||||||
|
* @param mixed $offset
|
||||||
|
* @return void
|
||||||
|
* @since 5.0.0
|
||||||
|
*/
|
||||||
|
public function offsetUnset($offset)
|
||||||
|
{
|
||||||
|
$this->items->offsetUnset($offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count elements of an object
|
||||||
|
*/
|
||||||
|
public function count()
|
||||||
|
{
|
||||||
|
return $this->items->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return (string) $this->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toArray()
|
||||||
|
{
|
||||||
|
if ($this->simple) {
|
||||||
|
return [
|
||||||
|
'per_page' => $this->listRows,
|
||||||
|
'current_page' => $this->currentPage,
|
||||||
|
'has_more' => $this->hasMore,
|
||||||
|
'next_item' => $this->nextItem,
|
||||||
|
'data' => $this->items->toArray(),
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
return [
|
||||||
|
'total' => $this->total,
|
||||||
|
'per_page' => $this->listRows,
|
||||||
|
'current_page' => $this->currentPage,
|
||||||
|
'last_page' => $this->lastPage,
|
||||||
|
'data' => $this->items->toArray(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify data which should be serialized to JSON
|
||||||
|
*/
|
||||||
|
public function jsonSerialize()
|
||||||
|
{
|
||||||
|
return $this->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __call($name, $arguments)
|
||||||
|
{
|
||||||
|
$collection = $this->getCollection();
|
||||||
|
|
||||||
|
$result = call_user_func_array([$collection, $name], $arguments);
|
||||||
|
|
||||||
|
if ($result === $collection) {
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,239 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace think;
|
||||||
|
|
||||||
|
class View
|
||||||
|
{
|
||||||
|
// 视图实例
|
||||||
|
protected static $instance;
|
||||||
|
// 模板引擎实例
|
||||||
|
public $engine;
|
||||||
|
// 模板变量
|
||||||
|
protected $data = [];
|
||||||
|
// 用于静态赋值的模板变量
|
||||||
|
protected static $var = [];
|
||||||
|
// 视图输出替换
|
||||||
|
protected $replace = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造函数
|
||||||
|
* @access public
|
||||||
|
* @param array $engine 模板引擎参数
|
||||||
|
* @param array $replace 字符串替换参数
|
||||||
|
*/
|
||||||
|
public function __construct($engine = [], $replace = [])
|
||||||
|
{
|
||||||
|
// 初始化模板引擎
|
||||||
|
$this->engine($engine);
|
||||||
|
// 基础替换字符串
|
||||||
|
$request = Request::instance();
|
||||||
|
$base = $request->root();
|
||||||
|
$root = strpos($base, '.') ? ltrim(dirname($base), DS) : $base;
|
||||||
|
if ('' != $root) {
|
||||||
|
$root = '/' . ltrim($root, '/');
|
||||||
|
}
|
||||||
|
$baseReplace = [
|
||||||
|
'__ROOT__' => $root,
|
||||||
|
'__URL__' => $base . '/' . $request->module() . '/' . Loader::parseName($request->controller()),
|
||||||
|
'__STATIC__' => $root . '/static',
|
||||||
|
'__CSS__' => $root . '/static/css',
|
||||||
|
'__JS__' => $root . '/static/js',
|
||||||
|
];
|
||||||
|
$this->replace = array_merge($baseReplace, (array) $replace);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化视图
|
||||||
|
* @access public
|
||||||
|
* @param array $engine 模板引擎参数
|
||||||
|
* @param array $replace 字符串替换参数
|
||||||
|
* @return object
|
||||||
|
*/
|
||||||
|
public static function instance($engine = [], $replace = [])
|
||||||
|
{
|
||||||
|
if (is_null(self::$instance)) {
|
||||||
|
self::$instance = new self($engine, $replace);
|
||||||
|
}
|
||||||
|
return self::$instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板变量静态赋值
|
||||||
|
* @access public
|
||||||
|
* @param mixed $name 变量名
|
||||||
|
* @param mixed $value 变量值
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function share($name, $value = '')
|
||||||
|
{
|
||||||
|
if (is_array($name)) {
|
||||||
|
self::$var = array_merge(self::$var, $name);
|
||||||
|
} else {
|
||||||
|
self::$var[$name] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板变量赋值
|
||||||
|
* @access public
|
||||||
|
* @param mixed $name 变量名
|
||||||
|
* @param mixed $value 变量值
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function assign($name, $value = '')
|
||||||
|
{
|
||||||
|
if (is_array($name)) {
|
||||||
|
$this->data = array_merge($this->data, $name);
|
||||||
|
} else {
|
||||||
|
$this->data[$name] = $value;
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置当前模板解析的引擎
|
||||||
|
* @access public
|
||||||
|
* @param array|string $options 引擎参数
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function engine($options = [])
|
||||||
|
{
|
||||||
|
if (is_string($options)) {
|
||||||
|
$type = $options;
|
||||||
|
$options = [];
|
||||||
|
} else {
|
||||||
|
$type = !empty($options['type']) ? $options['type'] : 'Think';
|
||||||
|
}
|
||||||
|
|
||||||
|
$class = false !== strpos($type, '\\') ? $type : '\\think\\view\\driver\\' . ucfirst($type);
|
||||||
|
if (isset($options['type'])) {
|
||||||
|
unset($options['type']);
|
||||||
|
}
|
||||||
|
$this->engine = new $class($options);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置模板引擎
|
||||||
|
* @access private
|
||||||
|
* @param string|array $name 参数名
|
||||||
|
* @param mixed $value 参数值
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function config($name, $value = null)
|
||||||
|
{
|
||||||
|
$this->engine->config($name, $value);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析和获取模板内容 用于输出
|
||||||
|
* @param string $template 模板文件名或者内容
|
||||||
|
* @param array $vars 模板输出变量
|
||||||
|
* @param array $replace 替换内容
|
||||||
|
* @param array $config 模板参数
|
||||||
|
* @param bool $renderContent 是否渲染内容
|
||||||
|
* @return string
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function fetch($template = '', $vars = [], $replace = [], $config = [], $renderContent = false)
|
||||||
|
{
|
||||||
|
// 模板变量
|
||||||
|
$vars = array_merge(self::$var, $this->data, $vars);
|
||||||
|
|
||||||
|
// 页面缓存
|
||||||
|
ob_start();
|
||||||
|
ob_implicit_flush(0);
|
||||||
|
|
||||||
|
// 渲染输出
|
||||||
|
try {
|
||||||
|
$method = $renderContent ? 'display' : 'fetch';
|
||||||
|
// 允许用户自定义模板的字符串替换
|
||||||
|
$replace = array_merge($this->replace, $replace, (array) $this->engine->config('tpl_replace_string'));
|
||||||
|
$this->engine->config('tpl_replace_string', $replace);
|
||||||
|
$this->engine->$method($template, $vars, $config);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
ob_end_clean();
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取并清空缓存
|
||||||
|
$content = ob_get_clean();
|
||||||
|
// 内容过滤标签
|
||||||
|
Hook::listen('view_filter', $content);
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 视图内容替换
|
||||||
|
* @access public
|
||||||
|
* @param string|array $content 被替换内容(支持批量替换)
|
||||||
|
* @param string $replace 替换内容
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function replace($content, $replace = '')
|
||||||
|
{
|
||||||
|
if (is_array($content)) {
|
||||||
|
$this->replace = array_merge($this->replace, $content);
|
||||||
|
} else {
|
||||||
|
$this->replace[$content] = $replace;
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染内容输出
|
||||||
|
* @access public
|
||||||
|
* @param string $content 内容
|
||||||
|
* @param array $vars 模板输出变量
|
||||||
|
* @param array $replace 替换内容
|
||||||
|
* @param array $config 模板参数
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function display($content, $vars = [], $replace = [], $config = [])
|
||||||
|
{
|
||||||
|
return $this->fetch($content, $vars, $replace, $config, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板变量赋值
|
||||||
|
* @access public
|
||||||
|
* @param string $name 变量名
|
||||||
|
* @param mixed $value 变量值
|
||||||
|
*/
|
||||||
|
public function __set($name, $value)
|
||||||
|
{
|
||||||
|
$this->data[$name] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取得模板显示变量的值
|
||||||
|
* @access protected
|
||||||
|
* @param string $name 模板变量
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function __get($name)
|
||||||
|
{
|
||||||
|
return $this->data[$name];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测模板变量是否设置
|
||||||
|
* @access public
|
||||||
|
* @param string $name 模板变量名
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function __isset($name)
|
||||||
|
{
|
||||||
|
return isset($this->data[$name]);
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue