Commit 93578073 by 刘剑华

init

parents
Folder
*.zip
*.rar
*.via
*.tmp
*.err
/runtime/
.idea
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
# =========================
# Operating System Files
# =========================
# OSX
# =========================
.DS_Store
.AppleDouble
.LSOverride
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
This diff is collapsed. Click to expand it.
Folder
*.zip
*.rar
*.via
*.tmp
*.err
/runtime/
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
# =========================
# Operating System Files
# =========================
# OSX
# =========================
.DS_Store
.AppleDouble
.LSOverride
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
deny from all
\ No newline at end of file
<?php
/**
* 授权基类,所有获取access_token以及验证access_token 异常都在此类中完成
*/
namespace app\api\controller;
use think\Controller;
use think\Request;
use think\Config;
use think\Exception;
use app\api\controller\Factory;
use app\api\controller\Send;
use think\response\Redirect;
use app\api\controller\UnauthorizedException;
class Api extends Controller
{
use Send;
/**
* 对应操作
* @var array
* date:2018-02-03
* @json
*/
public $methodToAction = [
'get' => 'read',
'post' => 'save',
'put' => 'update',
'delete' => 'delete',
'patch' => 'patch',
'head' => 'head',
'options' => 'options',
];
/**
* 允许访问的请求类型
* @var string
*/
public $restMethodList = 'get|post|put|delete|patch|head|options';
/**
* 默认不验证
* @var bool
*/
public $apiAuth = true;
protected $request;
/**
* 当前请求类型
* @var string
*/
protected $method;
/**
* 当前资源类型
* @var string
*/
protected $type;
public static $app;
/**
* 返回的资源类的
* @var string
*/
protected $restTypeList = 'json';
/**
* REST允许输出的资源类型列表
* @var array
*/
protected $restOutputType = [
'json' => 'application/json',
];
/**
* 客户端信息
*/
protected $clientInfo;
/**
* 控制器初始化操作
*/
public function _initialize()
{
$request = Request::instance();
$this->request = $request;
$this->init(); //检查资源类型
$this->clientInfo = $this->checkAuth(); //接口检查
// var_dump($request);die;
}
/**
* 初始化方法
* 检测请求类型,数据格式等操作
*/
public function init()
{
// 资源类型检测
$request = Request::instance();
// var_dump($request);die;
$ext = $request->ext();
if ('' == $ext) {
// 自动检测资源类型
$this->type = $request->type();
} elseif (!preg_match('/\(' . $this->restTypeList . '\)$/i', $ext)) {
// 资源类型非法 则用默认资源类型访问
$this->type = $this->restDefaultType;
} else {
$this->type = $ext;
}
$this->setType();
// 请求方式检测
$method = strtolower($request->method());
$this->method = $method;
if (false === stripos($this->restMethodList, $method)) {
return self::returnmsg(405);
}
}
/**
* 检测客户端是否有权限调用接口
*/
public function checkAuth()
{
$baseAuth = Factory::getInstance(\app\api\controller\Oauth::class);
$clientInfo = $baseAuth->authenticate();
return $clientInfo;
}
/**
* 空操作
* @return \think\Response|\think\response\Json|\think\response\Jsonp|\think\response\Xml
*/
public function _empty()
{
return $this->sendSuccess([], 'empty method!', 403);
}
}
\ No newline at end of file
<?php
/**
*
*/
namespace app\api\controller;
class Factory
{
private static $Factory;
private function __construct()
{
}
public static function getInstance($className, $options = null)
{
if (!isset(self::$Factory[$className]) || !self::$Factory[$className]) {
self::$Factory[$className] = new $className($options);
}
return self::$Factory[$className];
}
}
\ No newline at end of file
<?php
namespace app\api\controller;
use app\api\controller\UnauthorizedException;
use app\api\controller\Send;
use think\Exception;
use think\Request;
use think\Db;
use think\Cache;
class Oauth
{
use Send;
/**
* accessToken存储前缀
*
* @var string
*/
public static $accessTokenPrefix = 'accessToken_';
/**
* accessTokenAndClientPrefix存储前缀
*
* @var string
*/
public static $accessTokenAndClientPrefix = 'accessTokenAndClient_';
/**
* 过期时间秒数
*
* @var int
*/
public static $expires = 72000;
/**
* 客户端信息
*
* @var
*/
public $clientInfo;
/**
* 认证授权 通过用户信息和路由
* @param Request $request
* @return \Exception|UnauthorizedException|mixed|Exception
* @throws UnauthorizedException
*/
final function authenticate()
{
$request = Request::instance();
// var_dump($request);die;
try {
//验证授权
$clientInfo = $this->getClient();
// var_dump($clientInfo);die;
$checkclient = $this->certification($clientInfo);
if($checkclient){
return $clientInfo;
}
} catch (Exception $e) {
// return $this->returnmsg(402,'Invalid1 authentication credentials.');
$this->returnmsg('402',[],[],'service_message','Invalid1 authentication credentials.','验证码错误');
}
}
/**
* 获取用户信息
* @param Request $request
* @return $this
* @throws UnauthorizedException
*/
public function getClient()
{
$request = Request::instance();
//获取头部信息
try {
//========关键信息在头部传入例如key,用户信息,token等,==============
$authorization = $request->header('token');
// var_dump($authorization);die;
// $authorization = explode(" ", base64_decode($authorization));
// $authorization = explode(':', $authorization[1]);
// $app_key = $authorization[0];
$access_token = $authorization;
// $user_id = $authorization[2];//$_SERVER['PHP_AUTH_USER']
// $clientInfo['user_id'] = $user_id;
// $clientInfo['app_key'] = $app_key;
$clientInfo['token'] = $access_token;
// $clientInfo = $request->param();
} catch (Exception $e) {
return $this->returnmsg(402,$e.'Invalid authentication credentials');
}
return $clientInfo;
}
/**
* 获取用户信息后 验证权限
* @return mixed
*/
public function certification($data = []){
// ======下面注释部分是缓存验证access_token是否有效,这次使用数据库验证======
$time = date("Y-m-d H:i:s",time());
$checkclient = Db::name('token')->field('end_time')->where('uuid',$data['uuid'])->where('access_token',$data['access_token'])->find();
if(empty($checkclient)){
$this->returnmsg(401);
}
if($checkclient <= $time){
$this->returnmsg('402',[],[],'service_message','Token time out','token已过期');
}
return true;
// $getCacheAccessToken = Cache::get(self::$accessTokenPrefix . $data['access_token']); //获取缓存access_token
// if(!$getCacheAccessToken){
// return $this->returnmsg(402,'Access_token expired or error!');
// }
// if($getCacheAccessToken['client']['app_key'] != $data['app_key']){
//
// return $this->returnmsg(402,'App_token does not match app_key'); //app_key与缓存中的appkey不匹配
// }
//
// return true;
}
/**
* 生成签名
* _字符开头的变量不参与签名
*/
public function makeSign ($data = [],$app_secret = '')
{
unset($data['version']);
unset($data['signature']);
foreach ($data as $k => $v) {
if(substr($data[$k],0,1) == '_'){
unset($data[$k]);
}
}
dump($data);
return $this->_getOrderMd5($data,$app_secret);
}
/**
* 计算ORDER的MD5签名
*/
private function _getOrderMd5($params = [] , $app_secret = '') {
ksort($params);
$params['key'] = $app_secret;
return strtolower(md5(urldecode(http_build_query($params))));
}
}
\ No newline at end of file
<?php
/**
* 向客户端发送相应基类
*/
namespace app\api\controller;
use think\Response;
use think\response\Redirect;
trait Send
{
/**
* 默认返回资源类型
* @var string
*/
protected $restDefaultType = 'json';
/**
* 设置响应类型
* @param null $type
* @return $this
*/
public function setType($type = null)
{
$this->type = (string)(!empty($type)) ? $type : $this->restDefaultType;
return $this;
}
/**
* 失败响应
* @param int $error
* @param string $message
* @param int $code
* @param array $data
* @param array $headers
* @param array $options
* @return Response|\think\response\Json|\think\response\Jsonp|\think\response\Xml
*/
public function sendError($error = 400, $message = 'error', $code = 400, $data = [], $headers = [], $options = [])
{
$responseData['error'] = (int)$error;
$responseData['message'] = (string)$message;
if (!empty($data)) $responseData['data'] = $data;
$responseData = array_merge($responseData, $options);
return $this->response($responseData, $code, $headers);
}
/**
* 成功响应
* @param array $data
* @param string $message
* @param int $code
* @param array $headers
* @param array $options
* @return Response|\think\response\Json|\think\response\Jsonp|Redirect|\think\response\Xml
*/
public function render($code, $result = '')
{
header('Access-Control-Allow-Origin:*');
header('Access-Control-Allow-Headers:token,content-type');
// 组合返回数据
http_response_code($code);
session_start();
if (is_array($result)) {
foreach ((array)$result as $name => $data) {
// (array)强制转化,增强程序的健壮性
if (strpos($name, '.list')) {
// strrpos() - 查找字符串在另一字符串中最后一次出现的位置(区分大小写)
$model = trim(str_replace('.list', '', $name));
// 替换函数
foreach ((array)$data as $key => $value) {
$result[$name][$key] = $value;
}
} else {
$model = trim($name);
$result[$name] = $data;
}
}
}
// 输出中文字符的时候会进行json格式转码
echo json_encode(
$result
,JSON_UNESCAPED_UNICODE);
$result = null;
unset($result);
ob_flush();
flush();
session_destroy();
exit();
}
public function sendSuccess($data = [], $message = 'success', $code = 200, $headers = [], $options = [])
{
// var_dump($data);die;
// $responseData['error'] = 0;
// $responseData['message'] = (string)$message;
if(empty($data)) $responseData['data']="";
if (!empty($data)) $responseData['data'] = $data;
$responseData = array_merge($responseData, $options);
return $this->response($responseData, $code, $headers);
}
/**
* 重定向
* @param $url
* @param array $params
* @param int $code
* @param array $with
* @return Redirect
*/
public function sendRedirect($url, $params = [], $code = 302, $with = [])
{
$response = new Redirect($url);
if (is_integer($params)) {
$code = $params;
$params = [];
}
$response->code($code)->params($params)->with($with);
return $response;
}
/**
* 响应
* @param $responseData
* @param $code
* @param $headers
* @return Response|\think\response\Json|\think\response\Jsonp|Redirect|\think\response\View|\think\response\Xml
*/
public function response($responseData, $code, $headers)
{
if (!isset($this->type) || empty($this->type)) $this->setType();
return Response::create($responseData, $this->type, $code, $headers);
}
/**
*
* @param code 状态码
* @param message 返回信息
* @param data 返回信息
* @param header 返回头部信息
*/
public function returnmsg($code = '400',$data = [],$header = [],$type="",$reason="",$message="")
{
header('Access-Control-Allow-Origin:*');
header('Access-Control-Allow-Headers:token,content-type');
http_response_code($code);
switch($code)
{
case 400:
$error['error']['type'] = "BAD_REQUEST";
$error['error']['reason'] = "param missing";
$error['error']['message'] = "请求体不完整";
if (!empty($data)) $error['error']['data'] = $data;
// 发送头部信息
foreach ($header as $name => $val) {
if (is_null($val)) {
header($name);
} else {
header($name . ':' . $val);
}
}
break;
case 401:
$error['error']['type'] = "AUTH_ERROR";
$error['error']['reason'] = "token missing.";
$error['error']['message'] = "鉴权失败";
if (!empty($data)) $error['error']['data'] = $data;
// 发送头部信息
foreach ($header as $name => $val) {
if (is_null($val)) {
header($name);
} else {
header($name . ':' . $val);
}
}
break;
case 402:
//自定义
$error['error']['type'] = $type;
$error['error']['reason'] = $reason;
$error['error']['message'] = $message;
// $error['error'] = $message;
if (!empty($data)) $error['error']['data'] = $data;
// 发送头部信息
foreach ($header as $name => $val) {
if (is_null($val)) {
header($name);
} else {
header($name . ':' . $val);
}
}
break;
case 404:
$error['error']['type'] = "NOT_FOUND";
$error['error']['reason'] = "url error.";
$error['error']['message'] = "请求资源不存在";
if (!empty($data)) $error['error']['data'] = $data;
// 发送头部信息
foreach ($header as $name => $val) {
if (is_null($val)) {
header($name);
} else {
header($name . ':' . $val);
}
}
case 500:
$error['error']['type'] = "INNER_SERVER_ERROR";
$error['error']['reason'] = "null point exception.";
$error['error']['message'] = "服务器内部错误";
if (!empty($data)) $error['error']['data'] = $data;
// 发送头部信息
foreach ($header as $name => $val) {
if (is_null($val)) {
header($name);
} else {
header($name . ':' . $val);
}
}
break;
default:
$error['error']['reason']="Method Not Allowed ";
$error['error']['message'] = "资源请求类型有误";
foreach ($header as $name => $val) {
if (is_null($val)) {
header($name);
} else {
header($name . ':' . $val);
}
}
}
exit(json_encode($error,JSON_UNESCAPED_UNICODE));
}
// 按照协议规定答应API接口的处理结果
}
\ No newline at end of file
<?php
namespace app\api\controller;
use app\api\controller\UnauthorizedException;
use app\api\controller\Send;
use think\Exception;
use think\Request;
use think\Db;
use think\Cache;
/**
* 短信接口平台
*/
class Sms
{
function __construct()
{
# code...
}
}
\ No newline at end of file
<?php
/**
* 授权失败
*/
namespace app\api\controller;
use think\Exception;
class UnauthorizedException extends Exception
{
public $authenticate;
public function __construct($challenge = 'Basic', $message = 'authentication Failed')
{
$this->authenticate = $challenge;
$this->message = $message;
}
/**
* 获取验证错误信息
* @access public
* @return array|string
*/
public function getError()
{
return $this->error;
}
/**
* WWW-Authenticate challenge string
* @return array
*/
public function getHeaders()
{
return array('WWW-Authenticate' => $this->authenticate);
}
}
\ No newline at end of file
<?php
/**
* 获取accesstoken
*/
namespace app\api\controller\v1;
use think\Controller;
use think\Request;
use app\api\controller\Api;
use think\Response;
use app\api\controller\UnauthorizedException;
use app\api\controller\Send;
use app\api\controller\Oauth as Oauth2;
use app\api\model\Oauth as Oauth;
use think\Db;
use think\Cache;
class Token extends Controller
{
use Send;
//手机客户端请求验证规则
public static $rule_mobile = [
'app_key' => 'require',
'mobilephone' => 'require',
'nonce' => 'require',
'timestamp' => 'require',
'captcha' => 'number' //手机验证码
];
//微信端请求验证规则
public static $rule_wechat = [
'app_key' => 'require',
'open_id' => 'require',
'nonce' => 'require',
'timestamp' => 'require',
'union_id' => 'require',
'access_token'=> 'require' //微信端的access_token用于验证用户的信息是否真实
];
/**
* 构造函数
* 初始化检测请求时间,签名等
*/
public function __construct()
{
$this->request = Request::instance();
//为了调试注释掉时间验证与前面验证,请开发者自行测试
//$this->checkTime();
//$this->checkSign();
}
public function wechat()
{
$this->checkAppkey(self::$rule_wechat); //检测appkey
}
/**
* 为客户端提供access_token
* 手机号登录,手机号登录必须是注册过的手机号,不支持手机号注册
*/
public function read($uuid){
//$uuid
}
public function save($json){
//项目注册
//验参
if(empty($_POST['json'])){
$this->returnmsg(400);
}
$json=$_POST['json'];
// var_dump($json);die;
$json_obj=json_decode($json);
// var_dump($json_obj);die;
$groupModel = model('Token');
$list=$groupModel->vali($json_obj);
if($list){
//写入数据
$data['uuid']=$json_obj->uuid;
$data['create_time']=date("Y-m-d H:i:s",time());
$data['update_time']=date("Y-m-d H:i:s",time());
$data['expiry_time']=date("Y-m-d H:i:s",time()+604800);
$data['group_id']=$list;
$data['remake']=$json_obj->remake;
$data['accress_token']=md5(md5( $data['uuid'].time().rand(10,19999)));
$data['refresh_token']=md5(md5( $data['uuid'].time().rand(10,19999)));
$token_model= model('Token');
$status=$token_model->save_data($data);
if($status){
$this->render(200,$data);
}else{
$this->returnmsg(401);
}
}else{
$this->returnmsg('402',[],[],'service_message','Key error.','ID和秘钥不匹配');
}
}
public function update(){
//刷新ACCESStoken
// if(empty($type = $_SERVER['REQUEST_METHOD'])){
// $this->returnmsg(400);
// }
// var_dump($_GET['res']);
// $type = $_SERVER['REQUEST_METHOD'];
parse_str(file_get_contents('php://input'), $data);
if(empty($data['refresh_token'])||empty($data['app_id'])||empty($data['app_secret'])){
$this->returnmsg(400);
}
$groupModel = model('Token');
$json=json_decode(json_encode($data));
// var_dump($json);die;
$list=$groupModel->vali($json);
if($list){
//刷新accesstoken
$token_model= model('Token');
$status=$token_model->update_token($data['refresh_token']);
if($status){
$this->render(200,$status);
}else{
$this->returnmsg('402',[],[],'refresh_token','refresh_token error.','refresh_token错误');
}
}else{
$this->returnmsg('402',[],[],'service_message','Key error.','ID和秘钥不匹配');
}
// $data = array_merge($_GET, $_POST, $data);
// var_dump($data['res']);
// $count=count($data);
// var_dump($count);
}
public function mobile()
{
//检测appkey
$this->checkAppkey(self::$rule_mobile);
//获取短信验证码
if(!empty($this->request->param('captcha'))){
//$sms = Factory::getInstance(\app\api\controller\Sms::class);
//$code = $sms->getMobileCode($this->request->param('mobilephone'));
//return $this->returnmsg(200,'success',['code'=>$code]);
}else{
//$mobilebind = Db::name('tb_user')->field('mobilephone,id as user_id')->where('mobilephone',$this->request->param('mobilephone'))->find(); //取数据库对应手机号绑定用户
$mobilebind = ['uuid'=>110,'mobilephone'=>138888888888];
if(!empty($mobilebind)){
try {
$mobilebind['app_key'] = $this->request->param('app_key');
$accessTokenInfo = $this->setAccessToken($mobilebind);
return $this->render(200,$accessTokenInfo);
} catch (\Exception $e) {
$this->sendError(500, 'server error!!', 500);
}
}else{
// return $this->returnmsg(401,'mobilephone is not bind');
$this->returnmsg(401);
}
}
}
/**
* 检测时间+_300秒内请求会异常
*/
public function checkTime()
{
$time = $this->request->param('timestamp');
if($time > time()+300 || $time < time()-300){
return $this->returnmsg(401);
}
}
/**
* 检查微信用户是否真实
*/
public function checkWechat()
{
#todo
}
/**
* 检测appkey的有效性
* @param 验证规则数组
*/
public function checkAppkey($rule)
{
$result = $this->validate($this->request->param(),$rule);
if(true !== $result){
return $this->returnmsg(405);
}
//====调用模型验证app_key是否正确,这里注释,请开发者自行建表======
// $result = Oauth::get(function($query){
// $query->where('app_key', $this->request->param('app_key'));
// $query->where('expires_in','>' ,time());
// });
if(empty($result)){
return $this->returnmsg(401);
}
}
/**
* 检查签名
*/
public function checkSign()
{
$baseAuth = Factory::getInstance(\app\api\controller\Oauth::class);
$app_secret = Oauth::get(['app_key' => $this->request->param('app_key')]);
$sign = $baseAuth->makesign($this->request->param(),$app_secret['app_secret']); //生成签名
if($sign !== $this->request->param['signature']){
return self::returnmsg(401);
}
}
/**
* 设置AccessToken
* @param $clientInfo
* @return int
*/
protected function setAccessToken($clientInfo)
{
//生成令牌
$accessToken = self::buildAccessToken();
$accessTokenInfo = [
'access_token' => $accessToken,//访问令牌
'expires_time' => time() + Oauth2::$expires, //过期时间时间戳
'client' => $clientInfo,//用户信息
];
self::saveAccessToken($accessToken, $accessTokenInfo);
return $accessTokenInfo;
}
/**
* 生成AccessToken
* @return string
*/
protected static function buildAccessToken($lenght = 32)
{
//生成AccessToken
$str_pol = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789abcdefghijklmnopqrstuvwxyz";
return substr(str_shuffle($str_pol), 0, $lenght);
}
/**
* 存储
* @param $accessToken
* @param $accessTokenInfo
*/
protected static function saveAccessToken($accessToken, $accessTokenInfo)
{
//存储accessToken
Cache::set(Oauth2::$accessTokenPrefix . $accessToken, $accessTokenInfo, Oauth2::$expires);
//存储用户与信息索引 用于比较,这里涉及到user_id,如果有需要请关掉注释
//Cache::set(self::$accessTokenAndClientPrefix . $accessTokenInfo['client']['user_id'], $accessToken, self::$expires);
}
}
\ No newline at end of file
<?php
namespace app\api\controller\v1;
use think\Controller;
use think\Request;
use app\api\controller\Api;
use think\Response;
use app\api\controller\UnauthorizedException;
/**
* 所有资源类接都必须继承基类控制器
* 基类控制器提供了基础的验证,包含app_token,请求时间,请求是否合法的一系列的验证
* 在所有子类中可以调用$this->clientInfo对象访问请求客户端信息,返回为一个数组
* 在具体资源方法中,不需要再依赖注入,直接调用$this->request返回为请具体信息的一个对象
* date:2018-02-03
* @json
*/
class User extends Api
{
/**
* 允许访问的方式列表,资源数组如果没有对应的方式列表,请不要把该方法写上,如user这个资源,客户端没有delete操作
*/
public $restMethodList = 'get|post|put|delete';
/**
* restful没有任何参数
*
* @return \think\Response
*/
public function index()
{
return 'index';
}
/**
* post方式
*
* @param \think\Request $request
* @return \think\Response
*/
public function save()
{
echo 'save';
}
/**
* get方式
*
* @param int $id
* @return \think\Response
*/
public function read()
{
echo 'get';
dump($this->request);
dump($this->clientInfo);
}
/**
* PUT方式
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update()
{
echo 'update';
}
/**
* delete方式
*
* @param int $id
* @return \think\Response
*/
public function delete()
{
return 'delete';
}
public function fans($id)
{
return $id;
}
}
<?php
namespace app\api\controller\v2;
use app\api\model\User as UserModel;
class User
{
// 获取用户信息
public function save($id = 0)
{
// var_dump($_POST);
return $id;
}
}
\ No newline at end of file
<?php
namespace app\api\model;
use think\Model;
/**
* 存储用户appid,app_secret等值,为每个用户分配对应的值,生成access_token
*/
class Oauth extends Model{
/**
* 表名,
*/
protected $table = 'cfg_oauth';
/**
* 只读
*/
protected $readonly = ['app_key'];
// 设置返回数据集为数组
protected $resultSetType = '';
/**
* 验证合法的appkey
* @param appkey
* @return true|false
*/
public function checkAppkey($app_key = '')
{
#
}
}
\ No newline at end of file
<?php
namespace app\api\model;
use think\Model;
/**
* 分类
*/
class Token extends Model
{
/**
* 表名,
*/
protected $table = 'oauth_user';
public function vali($json){
// var_dump($json);die;
$where="app_id='{$json->app_id}' and app_secret='{$json->app_secret}'";
$list=$this->where($where)->field('group_id')->find();
if($list){
return $list['group_id'];
}else{
return false;
}
}
public function save_data($data){
$token_db= db('token');
$where="uuid ='{$data['uuid']}'";
$status=$token_db->where($where)->field('*')->find();
if($status){
$list=$token_db->where($where)->update($data);
}else{
$list=$token_db->insert($data);
}
if($list){
return true;
}else{
return false;
}
}
public function update_token($refresh_token){
$where="refresh_token='$refresh_token'";
$token_db=db('token');
$list=$token_db->where($where)->field('*')->find();
if($list){
// $data['create_time']=date("Y-m-d H:i:s",time());
$data['update_time']=date("Y-m-d H:i:s",time());
$data['expiry_time']=date("Y-m-d H:i:s",time()+604800);
$data['accress_token']=md5(md5( $list['uuid'].time().rand(10,19999)));
$data['refresh_token']=md5(md5( $list['uuid'].time().rand(10,19999)));
$up=$token_db->where('refresh_token',$refresh_token)->update($data);
if($up){
$data['uuid']=$list['uuid'];
$data['remake']=$list['remake'];
return $data;
}else{
return false;
}
}else{
return false;
}
}
}
\ No newline at end of file
<?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 [];
\ No newline at end of file
<?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@gmail.com>
// +----------------------------------------------------------------------
// 应用公共文件
/**
* 调试输出
* @param unknown $data
*/
function print_data($data, $var_dump = false)
{
header("Content-type: text/html; charset=utf-8");
echo "<pre>";
if ($var_dump) {
var_dump($data);
} else {
print_r($data);
}
exit();
}
/**
* 验证POS json格式数据
* @param unknown $object
*/
function is_json($string) {
json_decode($string);
return (json_last_error() == JSON_ERROR_NONE);
}
/**
* 输出json格式数据
* @param unknown $object
*/
function print_json($object)
{
header("content-type:text/plan;charset=utf-8");
echo json_encode($object);
exit();
}
/**
* 账户密码加密
* @param string $str password
* @return string(32)
*/
function md6($str)
{
$key = 'account_nobody';
return md5(md5($str).$key);
}
/**
* 替换字符串中间位置字符为星号
* @param [type] $str [description]
* @return [type] [description]
*/
function replaceToStar($str)
{
$len = strlen($str) / 2; //a0dca4d0****************ba444758]
return substr_replace($str, str_repeat('*', $len), floor(($len) / 2), $len);
}
function mduser( $str )
{
$user_auth_key = \think\Config::get('user_auth_key');
return md5(md5($user_auth_key).$str);
}
function uuid($prefix = '')
{
$chars = md5(uniqid(mt_rand(), true));
$uuid = substr($chars,0,8) . '-';
$uuid .= substr($chars,8,4) . '-';
$uuid .= substr($chars,12,4) . '-';
$uuid .= substr($chars,16,4) . '-';
$uuid .= substr($chars,20,12);
return $prefix . $uuid;
}
<?php
namespace app\common\controller;
use think\Config;
use think\Controller;
use think\Lang;
/**
* 公用的控制器,pc、app、微信各端不需要控制权限的控制器,必须继承该控制器
*
* @author json github
* @version 1.0
*/
class Common extends Controller
{
public function _initialize()
{
$now_lang = $this->getSetLang();
$this->assign('set_lang', $now_lang);
}
//暂时只做中英文切换
public function getSetLang()
{
$lang = Lang::detect();
if($lang == 'zh-cn') {
return 'en-us';
}
return 'zh-cn';
}
}
\ No newline at end of file
<?php
namespace app\common\model;
use think\Config;
use think\Controller;
use think\Lang;
use think\Model;
/**
* 公用的控制器,pc、app、微信各端不需要控制权限的控制器,必须继承该控制器
*
* @author json github
* @version 1.0
*/
class Common extends Model
{
}
\ No newline at end of file
<?php
namespace app\common\tools;
use app\admin\model\User;
use \think\Db;
use think\Model;
/**
* 权限验证类
*
* Class Auth
* @package app\common\tools
*/
class Auth
{
/**
* 检查权限
*
* @param $name 获得权限$name 可以是字符串或数组或逗号分割
* @param $uid 认证的用户id
* @param string $relation 是否为or关系,为true是, name为数组,只要数组中有一个条件通过则通过,如果为false需要全部条件通过
* @return bool
* name元素中的字符串需要对大小写保持一致,避免验证 或者添加 strtolower() 函数不区分大小写 为保证数据格式一致,建议转为小(大)写
*/
public function check($uid, $name)
{
$authList = $this->getAuthList($uid);
if (in_array($name, $authList)) {
return true;
}
return false;
}
/**
* 获得权限列表
*
* @param $uid
* @return array
*/
protected function getAuthList($uid)
{
static $_authList = array();
if (isset($_authList[$uid])) {
return $_authList[$uid];
}
//获取所属角色的权限列表
$roles = $this->getRoles($uid);
$ids = array();
foreach ($roles as $g) {
$ids = array_merge($ids, explode(',', trim($g['rule_name'], ',')));
}
$ids = array_unique($ids);
if (empty($ids)) {
$_authList[$uid] = array();
} else {
$_authList[$uid] = $ids;
}
return $_authList[$uid];
}
/**
* 获得用户组,外部也可以调用
*
* @param $uid
* @return mixed
*/
public function getRoles($uid) {
static $groups = array();
if (isset($groups[$uid]))
return $groups[$uid];
$user_groups = Db::name('role_user')->alias('a')->where(['a.user_id'=>$uid])->join('auth_access g', 'a.role_id=g.role_id')->select();
$groups[$uid]=$user_groups?$user_groups:array();
return $groups[$uid];
}
}
<?php
namespace app\common\tools;
use \think\Config;
use \think\Db;
/**
*
*/
class DbManage
{
// 换行符
private static $ds = "\n";
// 一次循环条数
private static $size = 20;
// 每条sql语句的结尾符
private static $sqlEnd = ";";
public static function backup($table, $dir = "backupMysql")
{
$dir = RUNTIME_PATH . $dir . DS . date('Y-m-d') . DS;
if (!file_exists($dir)) {
mkdir($dir, 0755, true);
}
$filename = $table . ".sql";
$sql = self::_startBackup($table);
return file_put_contents($dir . $filename, $sql);
}
/**
* 备份数据表
* @param [type] $table [description]
* @param [type] $dir [description]
* @param [type] $size [description]
* @return [type] [description]
*/
private static function _startBackup($table)
{
try {
$tableColumns = Db::execute("SHOW COLUMNS FROM `{$table}`");
} catch (\PDOException $e) {
return false;
}
// 插入dump信息
$sql = self::_retrieve();
$sql .= self::_insertTableStructure($table);
// 数据总条数
$count = Db::table($table)->count();
if ($count == 0) {
return $sql;
}
// 数据总页数
$pageSize = ceil($count / self::$size);
//数据备份
$sql .= self::_insertRecord($table, $pageSize);
return $sql;
}
/**
* 插入数据库备份基础信息
* @return [type] [description]
*/
private static function _retrieve()
{
$version = self::get('select VERSION() as v');
$value = '';
$value .= '--' . self::$ds;
$value .= '-- MySQL database dump' . self::$ds;
$value .= '-- Created by DbManage class, Power By luffyzhao. ' . self::$ds;
$value .= '-- https://github.com/lovezhao311 ' . self::$ds;
$value .= '--' . self::$ds;
$value .= '-- 主机: ' . Config::get('database.hostname') . self::$ds;
$value .= '-- 生成日期: ' . date('Y') . ' 年 ' . date('m') . ' 月 ' . date('d') . ' 日 ' . date('H:i') . self::$ds;
$value .= '-- MySQL版本: ' . $version['v'] . self::$ds;
$value .= '-- PHP 版本: ' . phpversion() . self::$ds;
$value .= self::$ds;
$value .= '--' . self::$ds;
$value .= '-- 数据库: `' . Config::get('database.database') . '`' . self::$ds;
$value .= '--' . self::$ds . self::$ds;
$value .= '-- -------------------------------------------------------';
$value .= self::$ds . self::$ds;
return $value;
}
/**
* 插入表结构
* @param string $value [description]
* @return [type] [description]
*/
private static function _insertTableStructure($table)
{
$sql = '';
$sql .= "--" . self::$ds;
$sql .= "-- 表的结构" . $table . self::$ds;
$sql .= "--" . self::$ds . self::$ds;
// 如果存在则删除表
$sql .= self::dropTableIfExists($table);
$res = self::get("SHOW CREATE TABLE `user`;");
$sql .= $res['Create Table'] . self::$sqlEnd . self::$ds;
$sql .= self::$ds;
$sql .= "--" . self::$ds;
$sql .= "-- 转存表中的数据 " . $table . self::$ds;
$sql .= "--" . self::$ds;
$sql .= self::$ds;
return $sql;
}
/**
* [_insertRecord description]
* @param [type] $record [description]
* @return [type] [description]
*/
private static function _insertRecord($table, $pageSize)
{
$sql = "INSERT INTO `{$table}` VALUES " . self::$ds;
for ($i = 0; $i < $pageSize; $i++) {
$rows = Db::table($table)->limit($i, self::$size)->select();
$delimiter1 = "";
foreach ($rows as $row) {
$sql .= "{$delimiter1}(";
$delimiter2 = "";
foreach ($row as $value) {
$sql .= "{$delimiter2}" . Db::quote($value);
$delimiter2 = ",";
}
$sql .= ")" . self::$ds;
$delimiter1 = ",";
}
}
$sql .= self::$sqlEnd;
return $sql;
}
/**
* 如果存在则删除表 sql 语句
* @param [type] $table [description]
* @return [type] [description]
*/
private static function dropTableIfExists($table)
{
return "DROP TABLE IF EXISTS `" . $table . '`' . self::$sqlEnd . self::$ds;
}
/**
* [get description]
* @param [type] $sql [description]
* @return [type] [description]
*/
private static function get($sql)
{
$query = Db::query($sql);
return $query[0];
}
}
<?php
namespace app\common\tools;
/**
* ------------------------------------------
* 图片处理类 (GD2库)
* ------------------------------------------
*
* 根据实际需求设计的图片处理类, “居中剪裁”通常使用在用户头像、缩略图等场景, “等比缩放”通常用来压缩图片
*
* 1. 居中剪裁 (宽高自动)
* 2. 等比缩放 (宽高自动, 源图小于宽高的不做缩放)
* 3. 创建缩略图
* 4. 如果操作网络图片, 会在根目录生成"tmp.jpg" (用于测试)
*
*/
class Image
{
protected $sourceImage = ''; // 源文件路径
protected $width = ''; // 要设置的宽度
protected $height = ''; // 要设置的高度
protected $createThumb = false; // 是否创建缩略图
protected $thumbMarker = '_thumb'; // 缩略图后缀
/**
* [__construct description]
* @param array $props [description]
*/
public function __construct($props = array())
{
if (count($props) > 0) {
$this->initialize($props);
}
}
/**
* 初始化配置
* @param [type] $props [description]
* @return [type] [description]
*/
public function initialize($props)
{
$this->clear(); // 清除之前的配置
$this->sourceImage = !isset($props['sourceImage']) ? $this->sourceImage : $props['sourceImage'];
$this->width = !isset($props['width']) ? $this->width : $props['width'];
$this->height = !isset($props['height']) ? $this->height : $props['height'];
$this->createThumb = !isset($props['createThumb']) ? $this->createThumb : $props['createThumb'];
$this->thumbMarker = !isset($props['thumbMarker']) ? $this->thumbMarker : $props['thumbMarker'];
}
/**
* 清除配置
* @return [type] [description]
*/
protected function clear()
{
$this->sourceImage = '';
$this->width = '';
$this->height = '';
$this->createThumb = false;
$this->thumbMarker = '_thumb';
}
/**
* 等比缩放
* @param string $value [description]
* @return [type] [description]
*/
public function resize($value = '')
{
$sourcePath = $this->sourceImage;
$targetWidth = $this->width;
$targetHeight = $this->height;
$sourceInfo = getimagesize($sourcePath);
$sourceWidth = $sourceInfo[0];
$sourceHeight = $sourceInfo[1];
$sourceMime = $sourceInfo['mime'];
switch ($sourceMime) {
case 'image/gif':
$sourceImage = imagecreatefromgif($sourcePath);
break;
case 'image/jpeg':
$sourceImage = imagecreatefromjpeg($sourcePath);
break;
case 'image/png':
$sourceImage = imagecreatefrompng($sourcePath);
break;
default:
$sourceImage = imagecreatefromjpeg($sourcePath); // 兼容app, 许多app上传的图片无mime信息
break;
}
$widthRatio = $targetWidth / $sourceWidth;
$heightRatio = $targetHeight / $sourceHeight;
// 源图宽高均小于要设置的值
if ($widthRatio >= 1 && $heightRatio >= 1) {
$targetImage = $sourceImage;
} else {
// 根据缩放倍率小的宽或者高缩放
if ($widthRatio < $heightRatio) {
$zoom_width = $targetWidth;
$zoom_height = $sourceHeight * ($targetWidth / $sourceWidth);
} else {
$zoom_height = $targetHeight;
$zoom_width = $sourceWidth * ($targetHeight / $sourceHeight);
}
// 声明图片资源
$targetImage = imagecreatetruecolor($zoom_width, $zoom_height);
// 缩放
imagecopyresampled($targetImage, $sourceImage, 0, 0, 0, 0, $zoom_width, $zoom_height, $sourceWidth, $sourceHeight);
}
// 图片地址为url
if (strpos($sourcePath, 'http') !== false) {
imagejpeg($targetImage, $_SERVER['DOCUMENT_ROOT'] . '/tmp.jpg');
} else {
if ($this->createThumb) {
$sourcePath = str_replace('.', $this->thumbMarker . '.', $sourcePath);
}
imagejpeg($targetImage, $sourcePath);
}
//销毁资源
imagedestroy($sourceImage);
@imagedestroy($targetImage);
$this->clear();
}
/**
* 居中剪裁
* @return [type] [description]
*/
public function crop()
{
$sourcePath = $this->sourceImage;
$targetWidth = $this->width;
$targetHeight = $this->height;
$sourceInfo = getimagesize($sourcePath);
$sourceWidth = $sourceInfo[0];
$sourceHeight = $sourceInfo[1];
$sourceMime = $sourceInfo['mime'];
$sourceRatio = $sourceHeight / $sourceWidth;
$targetRatio = $targetHeight / $targetWidth;
if ($sourceRatio > $targetRatio) {
// 源图过高
$croppedWidth = $sourceWidth;
$croppedHeight = $sourceWidth * $targetRatio;
$source_x = 0;
$source_y = ($sourceHeight - $croppedHeight) / 2;
} elseif ($sourceRatio < $targetRatio) {
// 源图过宽
$croppedWidth = $sourceHeight / $targetRatio;
$croppedHeight = $sourceHeight;
$source_x = ($sourceWidth - $croppedWidth) / 2;
$source_y = 0;
} else {
// 源图适中
$croppedWidth = $sourceWidth;
$croppedHeight = $sourceHeight;
$source_x = 0;
$source_y = 0;
}
switch ($sourceMime) {
case 'image/gif':
$sourceImage = imagecreatefromgif($sourcePath);
break;
case 'image/jpeg':
$sourceImage = imagecreatefromjpeg($sourcePath);
break;
case 'image/png':
$sourceImage = imagecreatefrompng($sourcePath);
break;
default:
$sourceImage = imagecreatefromjpeg($sourcePath); // 兼容app, 许多app上传的图片无mime信息
break;
}
// 声明图片资源
$targetImage = imagecreatetruecolor($targetWidth, $targetHeight);
$cropped_image = imagecreatetruecolor($croppedWidth, $croppedHeight);
// 裁剪
imagecopy($cropped_image, $sourceImage, 0, 0, $source_x, $source_y, $croppedWidth, $croppedHeight);
// 缩放
imagecopyresampled($targetImage, $cropped_image, 0, 0, 0, 0, $targetWidth, $targetHeight, $croppedWidth, $croppedHeight);
// 图片地址为url
if (strpos($sourcePath, 'http') !== false) {
imagejpeg($targetImage, $_SERVER['DOCUMENT_ROOT'] . '/tmp.jpg');
} else {
if ($this->createThumb) {
$sourcePath = str_replace('.', $this->thumbMarker . '.', $sourcePath);
}
imagejpeg($targetImage, $sourcePath);
}
// 销毁资源
imagedestroy($sourceImage);
imagedestroy($targetImage);
imagedestroy($cropped_image);
$this->clear();
}
}
<?php
namespace app\common\tools;
/**
* 获取受访者信息
*/
class Strings
{
/**
* 替换字符串中间位置字符为星号
* @param [type] $str [description]
* @return [type] [description]
*/
public static function replaceToStar($str)
{
$len = strlen($str) / 2;
return substr_replace($str, str_repeat('*', $len), floor(($len) / 2), $len);
}
/**
* 获取文件访问地址
* @param string $value [description]
*/
public static function fileWebLink($realPath)
{
$replace = dirname(ROOT_PATH);
return str_replace($replace, '', $realPath);
}
/**
* 通过文件访问地址获取 文件绝对地址
* @param string $value [description]
* @return [type] [description]
*/
public static function fileWebToServer($webLink)
{
$replace = dirname(ROOT_PATH);
return $replace . $webLink;
}
/**
* 删除文件
* @param string $value [description]
* @return [type] [description]
*/
public static function deleteFile($filename)
{
if (!file_exists($filename)) {
$filename = self::fileWebToServer($filename);
}
if (file_exists($filename) && is_file($filename)) {
unlink($filename);
}
}
}
<?php
namespace app\common\tools;
/**
* 获取受访者信息
*/
class Visitor
{
/**
* 获取浏览器
* @return [type] [description]
*/
public static function getBrowser()
{
$agent = $_SERVER["HTTP_USER_AGENT"];
if (strpos($agent, 'MSIE') !== false || strpos($agent, 'rv:11.0')) //ie11判断
{
return "ie";
} else if (strpos($agent, 'Firefox') !== false) {
return "firefox";
} else if (strpos($agent, 'Chrome') !== false) {
return "chrome";
} else if (strpos($agent, 'Opera') !== false) {
return 'opera';
} else if ((strpos($agent, 'Chrome') == false) && strpos($agent, 'Safari') !== false) {
return 'safari';
} else if (strpos($agent, 'MicroMessenger') !== false) {
return 'weixin';
} else {
return 'unknown';
}
}
/**
* 获取浏览器版本号
* @return [type] [description]
*/
public static function getBrowserVer()
{
if (empty($_SERVER['HTTP_USER_AGENT'])) {
//当浏览器没有发送访问者的信息的时候
return 'unknow';
}
$agent = $_SERVER['HTTP_USER_AGENT'];
if (preg_match('/MSIE\s(\d+)\..*/i', $agent, $regs)) {
return $regs[1];
} elseif (preg_match('/FireFox\/(\d+)\..*/i', $agent, $regs)) {
return $regs[1];
} elseif (preg_match('/Opera[\s|\/](\d+)\..*/i', $agent, $regs)) {
return $regs[1];
} elseif (preg_match('/Chrome\/(\d+)\..*/i', $agent, $regs)) {
return $regs[1];
} elseif ((strpos($agent, 'Chrome') == false) && preg_match('/Safari\/(\d+)\..*$/i', $agent, $regs)) {
return $regs[1];
} else {
return 'unknow';
}
}
/**
* 获取ip
* @return [type] [description]
*/
public static function getIP()
{
if (getenv('HTTP_CLIENT_IP')) {
$ip = getenv('HTTP_CLIENT_IP');
} else if (getenv('HTTP_X_FORWARDED_FOR')) {
$ip = getenv('HTTP_X_FORWARDED_FOR');
} else if (getenv('REMOTE_ADDR')) {
$ip = getenv('REMOTE_ADDR');
} else {
$ip = $_SERVER['REMOTE_ADDR'];
}
return $ip;
}
/**
* 获取用户系统
* @return [type] [description]
*/
public static function getOs()
{
$agent = $_SERVER['HTTP_USER_AGENT'];
$os = false;
if (preg_match('/win/i', $agent) && strpos($agent, '95')) {
$os = 'Windows 95';
} else if (preg_match('/win 9x/i', $agent) && strpos($agent, '4.90')) {
$os = 'Windows ME';
} else if (preg_match('/win/i', $agent) && preg_match('/98/i', $agent)) {
$os = 'Windows 98';
} else if (preg_match('/win/i', $agent) && preg_match('/nt 6.0/i', $agent)) {
$os = 'Windows Vista';
} else if (preg_match('/win/i', $agent) && preg_match('/nt 6.1/i', $agent)) {
$os = 'Windows 7';
} else if (preg_match('/win/i', $agent) && preg_match('/nt 6.2/i', $agent)) {
$os = 'Windows 8';
} else if (preg_match('/win/i', $agent) && preg_match('/nt 10.0/i', $agent)) {
$os = 'Windows 10'; #添加win10判断
} else if (preg_match('/win/i', $agent) && preg_match('/nt 5.1/i', $agent)) {
$os = 'Windows XP';
} else if (preg_match('/win/i', $agent) && preg_match('/nt 5/i', $agent)) {
$os = 'Windows 2000';
} else if (preg_match('/win/i', $agent) && preg_match('/nt/i', $agent)) {
$os = 'Windows NT';
} else if (preg_match('/win/i', $agent) && preg_match('/32/i', $agent)) {
$os = 'Windows 32';
} else if (preg_match('/linux/i', $agent)) {
$os = 'Linux';
} else if (preg_match('/unix/i', $agent)) {
$os = 'Unix';
} else if (preg_match('/sun/i', $agent) && preg_match('/os/i', $agent)) {
$os = 'SunOS';
} else if (preg_match('/ibm/i', $agent) && preg_match('/os/i', $agent)) {
$os = 'IBM OS/2';
} else if (preg_match('/Mac/i', $agent) && preg_match('/10_12_2/i', $agent)) {
$os = 'Mac OS X 10_12_2';
}else if (preg_match('/Mac/i', $agent)) {
$os = 'Mac OS X';
}else if (preg_match('/PowerPC/i', $agent)) {
$os = 'PowerPC';
} else if (preg_match('/AIX/i', $agent)) {
$os = 'AIX';
} else if (preg_match('/HPUX/i', $agent)) {
$os = 'HPUX';
} else if (preg_match('/NetBSD/i', $agent)) {
$os = 'NetBSD';
} else if (preg_match('/BSD/i', $agent)) {
$os = 'BSD';
} else if (preg_match('/OSF1/i', $agent)) {
$os = 'OSF1';
} else if (preg_match('/IRIX/i', $agent)) {
$os = 'IRIX';
} else if (preg_match('/FreeBSD/i', $agent)) {
$os = 'FreeBSD';
} else if (preg_match('/teleport/i', $agent)) {
$os = 'teleport';
} else if (preg_match('/flashget/i', $agent)) {
$os = 'flashget';
} else if (preg_match('/webzip/i', $agent)) {
$os = 'webzip';
} else if (preg_match('/offline/i', $agent)) {
$os = 'offline';
} else {
$os = 'unknow';
}
return $os;
}
}
<?php
namespace app\common\validate;
use \think\Db;
trait Validate
{
/**
* 验证是否存在!
* @author luffy<luffyzhao@vip.126.com>
* @dateTime 2016-04-19T09:48:57+0800
* @param [type] $roleId [description]
* @return [type] [description]
*/
public function exist($value, $rule, $data)
{
if (is_string($rule)) {
$rule = explode(',', $rule);
}
$db = Db::table($rule[0]);
$field = isset($rule[1]) ? $rule[1] : 'id';
$map = [$field => $value];
if ($db->where($map)->field($field)->find()) {
return true;
}
return false;
}
/**
* 验证PID是否存在 并且不等于本身
* @author luffy<luffyzhao@vip.126.com>
* @dateTime 2016-06-03T16:47:36+0800
* @param [type] $value [description]
* @param [type] $rule [description]
* @param [type] $data [description]
* @return [type] [description]
*/
public function existPid($value, $rule, $data)
{
if (intval($value) === 0) {
return true;
}
if (is_string($rule)) {
$rule = explode(',', $rule);
}
$db = Db::table($rule[0]);
$field = $db->getPk($rule[0]);
if (isset($data[$field]) && $data[$field] == $value) {
return false;
}
if ($db->where([$field => $value])->field($field)->find()) {
return true;
}
return false;
}
}
<?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_namespace' => 'app',
// 应用调试模式
'app_debug' => true,
// 应用Trace
// 'app_trace' => true,
// 应用模式状态
'app_status' => '',
// 是否支持多模块
'app_multi_module' => true,
// 入口自动绑定模块
'auto_bind_module' => false,
// 注册的根命名空间
'root_namespace' => [],
// 扩展配置文件
'extra_config_list' => ['database', 'validate'],
// 扩展函数文件
'extra_file_list' => [THINK_PATH . 'helper' . EXT],
// 默认输出类型
'default_return_type' => 'html', //DIY
// 默认AJAX 数据返回格式,可选json xml ...
'default_ajax_return' => 'json',
// 默认JSONP格式返回的处理方法
'default_jsonp_handler' => 'jsonpReturn',
// 默认JSONP处理方法
'var_jsonp_handler' => 'callback',
// 默认时区
'default_timezone' => 'PRC',
// 是否开启多语言
'lang_switch_on' => true,
// 默认全局过滤方法 用逗号分隔多个
'default_filter' => '',
// 默认语言
'default_lang' => 'zh-cn',
// 应用类库后缀
'class_suffix' => false,
// 控制器类后缀
'controller_suffix' => false,
// +----------------------------------------------------------------------
// | 模块设置
// +----------------------------------------------------------------------
// 默认模块名
'default_module' => 'www',
// 禁止访问模块
'deny_module_list' => ['common'],
//允许访问模块
'allow_module_list' => ['www','admin'],
// 默认控制器名
'default_controller' => 'Index',
// 默认操作名
'default_action' => 'index',
// 默认验证器
'default_validate' => '',
// 默认的空控制器名
'empty_controller' => 'Error',
// 操作方法后缀
'action_suffix' => '',
// 自动搜索控制器
'controller_auto_search' => false,
// +----------------------------------------------------------------------
// | URL设置
// +----------------------------------------------------------------------
// PATHINFO变量名 用于兼容模式
'var_pathinfo' => 's',
// 兼容PATH_INFO获取
'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
// pathinfo分隔符
'pathinfo_depr' => '/',
// URL伪静态后缀
'url_html_suffix' => 'html',
// URL普通方式参数 用于自动生成
'url_common_param' => false,
// URL参数方式 0 按名称成对解析 1 按顺序解析
'url_param_type' => 0,
// 是否开启路由
'url_route_on' => true,
// 路由配置文件(支持配置多个)
'route_config_file' => ['route'],
// 是否强制使用路由
'url_route_must' => false,
// 域名部署
'url_domain_deploy' => false,
// 域名根,如thinkphp.cn
'url_domain_root' => '',
// 是否自动转换URL中的控制器和操作名
'url_convert' => true,
// 默认的访问控制器层
'url_controller_layer' => 'controller',
// 表单请求类型伪装变量
'var_method' => '_method',
// +----------------------------------------------------------------------
// | 模板设置
// +----------------------------------------------------------------------
'template' => [
// 模板引擎类型 支持 php think 支持扩展
'type' => 'Think',
// 模板路径
'view_path' => '',
// 模板后缀
'view_suffix' => 'html',
// 模板文件名分隔符
'view_depr' => DS,
// 模板引擎普通标签开始标记
'tpl_begin' => '{',
// 模板引擎普通标签结束标记
'tpl_end' => '}',
// 标签库标签开始标记
'taglib_begin' => '{',
// 标签库标签结束标记
'taglib_end' => '}',
],
// 视图输出字符串内容替换
'view_replace_str' => [
'__STATIC__DOMAIN__'=>STATIC_PATH,
],
// 默认跳转页面对应的模板文件
'dispatch_success_tmpl' => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl',
'dispatch_error_tmpl' => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl',
// +----------------------------------------------------------------------
// | 异常及错误设置
// +----------------------------------------------------------------------
// 异常页面的模板文件
'exception_tmpl' => THINK_PATH . 'tpl' . DS . 'think_exception.tpl',
// 错误显示信息,非调试模式有效
'error_message' => '页面错误!请稍后再试~',
// 显示错误信息
'show_error_msg' => false,
// 异常处理handle类 留空使用 \think\exception\Handle
'exception_handle' => '',
// +----------------------------------------------------------------------
// | 日志设置
// +----------------------------------------------------------------------
'log' => [
// 日志记录方式,内置 file socket 支持扩展
'type' => 'File',
// 日志保存目录
'path' => LOG_PATH,
// 日志记录级别
'level' => [],
],
// +----------------------------------------------------------------------
// | Trace设置 开启 app_trace 后 有效
// +----------------------------------------------------------------------
'trace' => [
// 内置Html Console 支持扩展
'type' => 'Html',
],
// +----------------------------------------------------------------------
// | 缓存设置
// +----------------------------------------------------------------------
'cache' => [
// 驱动方式
'type' => 'File',
// 缓存保存目录
'path' => CACHE_PATH,
// 缓存前缀
'prefix' => '',
// 缓存有效期 0表示永久缓存
'expire' => 0,
],
// +----------------------------------------------------------------------
// | 会话设置
// +----------------------------------------------------------------------
'session' => [
'id' => '',
// SESSION_ID的提交变量,解决flash上传跨域
'var_session_id' => '',
// SESSION 前缀
'prefix' => 'think',
// 驱动方式 支持redis memcache memcached
'type' => '',
// 是否自动开启 SESSION
'auto_start' => true,
],
// +----------------------------------------------------------------------
// | Cookie设置
// +----------------------------------------------------------------------
'cookie' => [
// cookie 名称前缀
'prefix' => '',
// cookie 保存时间
'expire' => 0,
// cookie 保存路径
'path' => '/',
// cookie 有效域名
'domain' => '',
// cookie 启用安全传输
'secure' => false,
// httponly设置
'httponly' => '',
// 是否使用 setcookie
'setcookie' => true,
],
//分页配置
'paginate' => [
'type' => 'bootstrap',
'var_page' => 'page',
'list_rows' => 15,
],
//写安装程序的时候随即生成authId
'user_auth_key' => 'authId',
];
<?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' => '',
// 数据库名
'database' => '',
// 用户名
'username' => '',
// 密码
'password' => '',
// 端口
'hostport' => '3306',
// 连接dsn
'dsn' => '',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => 'oauth_',
// 数据库调试模式
'debug' => true,
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => true,
// 数据集返回类型 array 数组 collection Collection对象
'resultset_type' => 'array',
// 是否自动写入时间戳字段
'auto_timestamp' => true,
// 是否需要进行SQL性能分析
'sql_explain' => false,
];
<?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>
// +----------------------------------------------------------------------
use think\Route;
Route::resource(':version/user','api/:version.User'); //注册一个资源路由,对应restful各个方法
Route::resource(':version/Token','api/:version.Token'); //注册一个资源路由,对应restful各个方法
Route::rule(':version/user/:id/fans','api/:version.User/fans'); //restful方法中另外一个方法等。。。
Route::rule(':version/token/mobile','api/:version.Token/mobile');
Route::miss('Error/index');
//if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["REQUEST_URI"])) {
// return false;
//} else {
// require __DIR__ . "/admin/index.php";
//}
return [
'__pattern__' => [
'name' => '\w+',
],
];
<?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' => [],
];
<?php
namespace app\www\controller;
use think\Request;
class Error
{
public function index()
{
return json(array('error'=>405,'message'=>'No routing path can be found for the request.'));
}
}
\ No newline at end of file
<?php
namespace app\www\controller;
use app\common\controller\Common;
class Index extends Common
{
public function index()
{
return '<style type="text/css">*{ padding: 0; margin: 0; } .think_default_text{ padding: 4px 48px;} a{color:#2E5CD5;cursor: pointer;text-decoration: none} a:hover{text-decoration:underline; } body{ background: #fff; font-family: "Century Gothic","Microsoft yahei"; color: #333;font-size:18px} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.6em; font-size: 42px }</style><div style="padding: 24px 48px;"> <h1>:)</h1><p> ThinkPHP V5<br/><span style="font-size:30px">十年磨一剑 - 为API开发设计的高性能框架</span></p><span style="font-size:22px;">[ V5.0 版本由 <a href="http://www.qiniu.com" target="qiniu">七牛云</a> 独家赞助发布 ]</span></div><script type="text/javascript" src="http://tajs.qq.com/stats?sId=9347272" charset="UTF-8"></script><script type="text/javascript" src="http://ad.topthink.com/Public/static/client.js"></script><thinkad id="ad_bd568ce7058a1091"></thinkad>';
}
}
\ No newline at end of file
<?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 [
// 生成应用公共文件
'__file__' => ['common.php', 'config.php', 'database.php'],
// 定义demo模块的自动生成 (按照实际定义的文件名生成)
'demo' => [
'__file__' => ['common.php'],
'__dir__' => ['behavior', 'controller', 'model', 'view'],
'controller' => ['Index', 'Test', 'UserType'],
'model' => ['User', 'UserType'],
'view' => ['index/index'],
],
// 其他更多的模块定义
// 定义test模块的自动生成
'test'=>[
'__dir__' => ['behavior','controller','model','widget'],
'controller'=> ['Index','Test','UserType'],
'model' => ['User','UserType'],
'view' => ['index/index','index/test'],
],
];
{
"name": "topthink/think",
"description": "the new thinkphp framework",
"type": "project",
"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/framework": "^5.0.4",
"topthink/think-captcha": "^1.0.7",
"topthink/think-testing": "^1.0",
"zircote/swagger-php": "^2.0"
},
"extra": {
"think-path": "thinkphp"
},
"config": {
"preferred-install": "dist"
}
}
This diff is collapsed. Click to expand it.
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false">
<testsuites>
<testsuite name="Application Test Suite">
<directory>./tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">application/</directory>
</whitelist>
</filter>
</phpunit>
<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>
<?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>
// +----------------------------------------------------------------------
// [ 应用入口文件 ]
if(version_compare(PHP_VERSION,'5.4.0','<')) die('require PHP > 5.4.0 !');
// 定义应用目录
define('APP_PATH', __DIR__ . '/../app/');
// 定义静态资源目录 或 URL
define('STATIC_PATH', '/static/');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';
User-agent: *
Disallow:
<?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>
// +----------------------------------------------------------------------
// $Id$
if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["REQUEST_URI"])) {
return false;
} else {
require __DIR__ . "/index.php";
}
/**
* @author zhixin wen <wenzhixin2010@gmail.com>
* version: 1.11.0
* https://github.com/wenzhixin/bootstrap-table/
*/
.bootstrap-table .table {
margin-bottom: 0 !important;
border-bottom: 1px solid #dddddd;
border-collapse: collapse !important;
border-radius: 1px;
}
.bootstrap-table .table:not(.table-condensed),
.bootstrap-table .table:not(.table-condensed) > tbody > tr > th,
.bootstrap-table .table:not(.table-condensed) > tfoot > tr > th,
.bootstrap-table .table:not(.table-condensed) > thead > tr > td,
.bootstrap-table .table:not(.table-condensed) > tbody > tr > td,
.bootstrap-table .table:not(.table-condensed) > tfoot > tr > td {
padding: 8px;
}
.bootstrap-table .table.table-no-bordered > thead > tr > th,
.bootstrap-table .table.table-no-bordered > tbody > tr > td {
border-right: 2px solid transparent;
}
.bootstrap-table .table.table-no-bordered > tbody > tr > td:last-child {
border-right: none;
}
.fixed-table-container {
position: relative;
clear: both;
border: 1px solid #dddddd;
border-radius: 4px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
}
.fixed-table-container.table-no-bordered {
border: 1px solid transparent;
}
.fixed-table-footer,
.fixed-table-header {
overflow: hidden;
}
.fixed-table-footer {
border-top: 1px solid #dddddd;
}
.fixed-table-body {
overflow-x: auto;
overflow-y: auto;
height: 100%;
}
.fixed-table-container table {
width: 100%;
}
.fixed-table-container thead th {
height: 0;
padding: 0;
margin: 0;
border-left: 1px solid #dddddd;
}
.fixed-table-container thead th:focus {
outline: 0 solid transparent;
}
.fixed-table-container thead th:first-child {
border-left: none;
border-top-left-radius: 4px;
-webkit-border-top-left-radius: 4px;
-moz-border-radius-topleft: 4px;
}
.fixed-table-container thead th .th-inner,
.fixed-table-container tbody td .th-inner {
padding: 8px;
line-height: 24px;
vertical-align: top;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.fixed-table-container thead th .sortable {
cursor: pointer;
background-position: right;
background-repeat: no-repeat;
padding-right: 30px;
}
.fixed-table-container thead th .both {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7X QMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azioNZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4euts6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC');
}
.fixed-table-container thead th .asc {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBdqEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVoAADeemwtPcZI2wAAAABJRU5ErkJggg==');
}
.fixed-table-container thead th .desc {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWjYBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJzcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII= ');
}
.fixed-table-container th.detail {
width: 30px;
}
.fixed-table-container tbody td {
border-left: 1px solid #dddddd;
}
.fixed-table-container tbody tr:first-child td {
border-top: none;
}
.fixed-table-container tbody td:first-child {
border-left: none;
}
/* the same color with .active */
.fixed-table-container tbody .selected td {
background-color: #f5f5f5;
}
.fixed-table-container .bs-checkbox {
text-align: center;
}
.fixed-table-container .bs-checkbox .th-inner {
padding: 8px 0;
}
.fixed-table-container input[type="radio"],
.fixed-table-container input[type="checkbox"] {
margin: 0 auto !important;
}
.fixed-table-container .no-records-found {
text-align: center;
}
.fixed-table-pagination div.pagination,
.fixed-table-pagination .pagination-detail {
margin-top: 10px;
margin-bottom: 10px;
}
.fixed-table-pagination div.pagination .pagination {
margin: 0;
}
.fixed-table-pagination .pagination a {
padding: 6px 12px;
line-height: 1.428571429;
}
.fixed-table-pagination .pagination-info {
line-height: 34px;
margin-right: 5px;
}
.fixed-table-pagination .btn-group {
position: relative;
display: inline-block;
vertical-align: middle;
}
.fixed-table-pagination .dropup .dropdown-menu {
margin-bottom: 0;
}
.fixed-table-pagination .page-list {
display: inline-block;
}
.fixed-table-toolbar .columns-left {
margin-right: 5px;
}
.fixed-table-toolbar .columns-right {
margin-left: 5px;
}
.fixed-table-toolbar .columns label {
display: block;
padding: 3px 20px;
clear: both;
font-weight: normal;
line-height: 1.428571429;
}
.fixed-table-toolbar .bs-bars,
.fixed-table-toolbar .search,
.fixed-table-toolbar .columns {
position: relative;
margin-top: 10px;
margin-bottom: 10px;
line-height: 34px;
}
.fixed-table-pagination li.disabled a {
pointer-events: none;
cursor: default;
}
.fixed-table-loading {
display: none;
position: absolute;
top: 42px;
right: 0;
bottom: 0;
left: 0;
z-index: 99;
background-color: #fff;
text-align: center;
}
.fixed-table-body .card-view .title {
font-weight: bold;
display: inline-block;
min-width: 30%;
text-align: left !important;
}
/* support bootstrap 2 */
.fixed-table-body thead th .th-inner {
box-sizing: border-box;
}
.table th, .table td {
vertical-align: middle;
box-sizing: border-box;
}
.fixed-table-toolbar .dropdown-menu {
text-align: left;
max-height: 300px;
overflow: auto;
}
.fixed-table-toolbar .btn-group > .btn-group {
display: inline-block;
margin-left: -1px !important;
}
.fixed-table-toolbar .btn-group > .btn-group > .btn {
border-radius: 0;
}
.fixed-table-toolbar .btn-group > .btn-group:first-child > .btn {
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.fixed-table-toolbar .btn-group > .btn-group:last-child > .btn {
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
.bootstrap-table .table > thead > tr > th {
vertical-align: bottom;
border-bottom: 1px solid #ddd;
}
/* support bootstrap 3 */
.bootstrap-table .table thead > tr > th {
padding: 0;
margin: 0;
}
.bootstrap-table .fixed-table-footer tbody > tr > td {
padding: 0 !important;
}
.bootstrap-table .fixed-table-footer .table {
border-bottom: none;
border-radius: 0;
padding: 0 !important;
}
.pull-right .dropdown-menu {
right: 0;
left: auto;
}
/* calculate scrollbar width */
p.fixed-table-scroll-inner {
width: 100%;
height: 200px;
}
div.fixed-table-scroll-outer {
top: 0;
left: 0;
visibility: hidden;
width: 200px;
height: 150px;
overflow: hidden;
}
/*
Common
*/
.wizard,
.tabcontrol
{
display: block;
width: 100%;
overflow: hidden;
}
.wizard a,
.tabcontrol a
{
outline: 0;
}
.wizard ul,
.tabcontrol ul
{
list-style: none !important;
padding: 0;
margin: 0;
}
.wizard ul > li,
.tabcontrol ul > li
{
display: block;
padding: 0;
}
/* Accessibility */
.wizard > .steps .current-info,
.tabcontrol > .steps .current-info
{
position: absolute;
left: -999em;
}
.wizard > .content > .title,
.tabcontrol > .content > .title
{
position: absolute;
left: -999em;
}
/*
Wizard
*/
.wizard > .steps
{
position: relative;
display: block;
width: 100%;
}
.wizard.vertical > .steps
{
display: inline;
float: left;
width: 30%;
}
.wizard > .steps > ul > li
{
width: 25%;
}
.wizard > .steps > ul > li,
.wizard > .actions > ul > li
{
float: left;
}
.wizard.vertical > .steps > ul > li
{
float: none;
width: 100%;
}
.wizard > .steps a,
.wizard > .steps a:hover,
.wizard > .steps a:active
{
display: block;
width: auto;
margin: 0 0.5em 0.5em;
padding: 8px;
text-decoration: none;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
.wizard > .steps .disabled a,
.wizard > .steps .disabled a:hover,
.wizard > .steps .disabled a:active
{
background: #eee;
color: #aaa;
cursor: default;
}
.wizard > .steps .current a,
.wizard > .steps .current a:hover,
.wizard > .steps .current a:active
{
background: #1AB394;
color: #fff;
cursor: default;
}
.wizard > .steps .done a,
.wizard > .steps .done a:hover,
.wizard > .steps .done a:active
{
background: #6fd1bd;
color: #fff;
}
.wizard > .steps .error a,
.wizard > .steps .error a:hover,
.wizard > .steps .error a:active
{
background: #ED5565 ;
color: #fff;
}
.wizard > .content
{
background: #eee;
display: block;
margin: 5px 5px 10px 5px;
min-height: 120px;
overflow: hidden;
position: relative;
width: auto;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
.wizard-big.wizard > .content {
min-height: 320px;
}
.wizard.vertical > .content
{
display: inline;
float: left;
margin: 0 2.5% 0.5em 2.5%;
width: 65%;
}
.wizard > .content > .body
{
float: left;
position: absolute;
width: 95%;
height: 95%;
padding: 2.5%;
}
.wizard > .content > .body ul
{
list-style: disc !important;
}
.wizard > .content > .body ul > li
{
display: list-item;
}
.wizard > .content > .body > iframe
{
border: 0 none;
width: 100%;
height: 100%;
}
.wizard > .content > .body input
{
display: block;
border: 1px solid #ccc;
}
.wizard > .content > .body input[type="checkbox"]
{
display: inline-block;
}
.wizard > .content > .body input.error
{
background: rgb(251, 227, 228);
border: 1px solid #fbc2c4;
color: #8a1f11;
}
.wizard > .content > .body label
{
display: inline-block;
margin-bottom: 0.5em;
}
.wizard > .content > .body label.error
{
color: #8a1f11;
display: inline-block;
margin-left: 1.5em;
}
.wizard > .actions
{
position: relative;
display: block;
text-align: right;
width: 100%;
}
.wizard.vertical > .actions
{
display: inline;
float: right;
margin: 0 2.5%;
width: 95%;
}
.wizard > .actions > ul
{
display: inline-block;
text-align: right;
}
.wizard > .actions > ul > li
{
margin: 0 0.5em;
}
.wizard.vertical > .actions > ul > li
{
margin: 0 0 0 1em;
}
.wizard > .actions a,
.wizard > .actions a:hover,
.wizard > .actions a:active
{
background: #1AB394;
color: #fff;
display: block;
padding: 0.5em 1em;
text-decoration: none;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
.wizard > .actions .disabled a,
.wizard > .actions .disabled a:hover,
.wizard > .actions .disabled a:active
{
background: #eee;
color: #aaa;
}
.wizard > .loading
{
}
.wizard > .loading .spinner
{
}
/*
Tabcontrol
*/
.tabcontrol > .steps
{
position: relative;
display: block;
width: 100%;
}
.tabcontrol > .steps > ul
{
position: relative;
margin: 6px 0 0 0;
top: 1px;
z-index: 1;
}
.tabcontrol > .steps > ul > li
{
float: left;
margin: 5px 2px 0 0;
padding: 1px;
-webkit-border-top-left-radius: 5px;
-webkit-border-top-right-radius: 5px;
-moz-border-radius-topleft: 5px;
-moz-border-radius-topright: 5px;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
.tabcontrol > .steps > ul > li:hover
{
background: #edecec;
border: 1px solid #bbb;
padding: 0;
}
.tabcontrol > .steps > ul > li.current
{
background: #fff;
border: 1px solid #bbb;
border-bottom: 0 none;
padding: 0 0 1px 0;
margin-top: 0;
}
.tabcontrol > .steps > ul > li > a
{
color: #5f5f5f;
display: inline-block;
border: 0 none;
margin: 0;
padding: 10px 30px;
text-decoration: none;
}
.tabcontrol > .steps > ul > li > a:hover
{
text-decoration: none;
}
.tabcontrol > .steps > ul > li.current > a
{
padding: 15px 30px 10px 30px;
}
.tabcontrol > .content
{
position: relative;
display: inline-block;
width: 100%;
height: 35em;
overflow: hidden;
border-top: 1px solid #bbb;
padding-top: 20px;
}
.tabcontrol > .content > .body
{
float: left;
position: absolute;
width: 95%;
height: 95%;
padding: 2.5%;
}
.tabcontrol > .content > .body ul
{
list-style: disc !important;
}
.tabcontrol > .content > .body ul > li
{
display: list-item;
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
// validator
function zh_validator() {
// 验证手机号
jQuery.validator.addMethod("mobile", function(value, element) {
var tel = /^1[3|4|5|7|8]\d{9}$/;
return this.optional(element) || (tel.test(value));
}, "Please enter a valid phone number");
// 验证身份证号
jQuery.validator.addMethod("cardid", function(value, element) {
var tel = /^(\d{15}$|^\d{18}$|^\d{17}(\d|X|x))$/;
return this.optional(element) || (tel.test(value));
}, "Please enter a valid ID number");
// 自定义正则验证
jQuery.validator.addMethod("regular", function(value, element) {
var regular = eval(element.getAttribute('data-rule-regular'));
return this.optional(element) || (regular.test(value));
}, "Input error");
$.extend($.validator.messages, {
required: "This field is required.",
remote: "Please fix this field.",
email: "Please enter a valid email address.",
url: "Please enter a valid URL.",
date: "Please enter a valid date.",
dateISO: "Please enter a valid date ( ISO ).",
number: "Please enter a valid number.",
digits: "Please enter only digits.",
equalTo: "Please enter the same value again.",
maxlength: $.validator.format( "Please enter no more than {0} characters." ),
minlength: $.validator.format( "Please enter at least {0} characters." ),
rangelength: $.validator.format( "Please enter a value between {0} and {1} characters long." ),
range: $.validator.format( "Please enter a value between {0} and {1}." ),
max: $.validator.format( "Please enter a value less than or equal to {0}." ),
min: $.validator.format( "Please enter a value greater than or equal to {0}." ),
step: $.validator.format( "Please enter a multiple of {0}." )
});
}
// table
function zh_table() {
$.extend($.fn.bootstrapTable.defaults, {
formatLoadingMessage: function () {
return 'Loading, please wait...';
},
formatRecordsPerPage: function (pageNumber) {
return pageNumber + ' rows per page';
},
formatShowingRows: function (pageFrom, pageTo, totalRows) {
return 'Showing ' + pageFrom + ' to ' + pageTo + ' of ' + totalRows + ' rows';
},
formatSearch: function () {
return 'Search';
},
formatNoMatches: function () {
return 'No matching records found';
},
formatPaginationSwitch: function () {
return 'Hide/Show pagination';
},
formatRefresh: function () {
return 'Refresh';
},
formatToggle: function () {
return 'Toggle';
},
formatColumns: function () {
return 'Columns';
},
formatAllRows: function () {
return 'All';
},
formatExport: function () {
return 'Export data';
},
formatClearFilters: function () {
return 'Clear filters';
}
});
}
/*
* metismenu - v2.0.2
* A jQuery menu plugin
* https://github.com/onokumus/metisMenu
*
* Made by Osman Nuri Okumus
* Under MIT License
*/
!function(a){"use strict";function b(){var a=document.createElement("mm"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}function c(b){return this.each(function(){var c=a(this),d=c.data("mm"),f=a.extend({},e.DEFAULTS,c.data(),"object"==typeof b&&b);d||c.data("mm",d=new e(this,f)),"string"==typeof b&&d[b]()})}a.fn.emulateTransitionEnd=function(b){var c=!1,e=this;a(this).one("mmTransitionEnd",function(){c=!0});var f=function(){c||a(e).trigger(d.end)};return setTimeout(f,b),this};var d=b();d&&(a.event.special.mmTransitionEnd={bindType:d.end,delegateType:d.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}});var e=function(b,c){this.$element=a(b),this.options=a.extend({},e.DEFAULTS,c),this.transitioning=null,this.init()};e.TRANSITION_DURATION=350,e.DEFAULTS={toggle:!0,doubleTapToGo:!1,activeClass:"active"},e.prototype.init=function(){var b=this,c=this.options.activeClass;this.$element.find("li."+c).has("ul").children("ul").addClass("collapse in"),this.$element.find("li").not("."+c).has("ul").children("ul").addClass("collapse"),this.options.doubleTapToGo&&this.$element.find("li."+c).has("ul").children("a").addClass("doubleTapToGo"),this.$element.find("li").has("ul").children("a").on("click.metisMenu",function(d){var e=a(this),f=e.parent("li"),g=f.children("ul");return d.preventDefault(),f.hasClass(c)?b.hide(g):b.show(g),b.options.doubleTapToGo&&b.doubleTapToGo(e)&&"#"!==e.attr("href")&&""!==e.attr("href")?(d.stopPropagation(),void(document.location=e.attr("href"))):void 0})},e.prototype.doubleTapToGo=function(a){var b=this.$element;return a.hasClass("doubleTapToGo")?(a.removeClass("doubleTapToGo"),!0):a.parent().children("ul").length?(b.find(".doubleTapToGo").removeClass("doubleTapToGo"),a.addClass("doubleTapToGo"),!1):void 0},e.prototype.show=function(b){var c=this.options.activeClass,f=a(b),g=f.parent("li");if(!this.transitioning&&!f.hasClass("in")){g.addClass(c),this.options.toggle&&this.hide(g.siblings().children("ul.in")),f.removeClass("collapse").addClass("collapsing").height(0),this.transitioning=1;var h=function(){f.removeClass("collapsing").addClass("collapse in").height(""),this.transitioning=0};return d?void f.one("mmTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(e.TRANSITION_DURATION).height(f[0].scrollHeight):h.call(this)}},e.prototype.hide=function(b){var c=this.options.activeClass,f=a(b);if(!this.transitioning&&f.hasClass("in")){f.parent("li").removeClass(c),f.height(f.height())[0].offsetHeight,f.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var g=function(){this.transitioning=0,f.removeClass("collapsing").addClass("collapse")};return d?void f.height(0).one("mmTransitionEnd",a.proxy(g,this)).emulateTransitionEnd(e.TRANSITION_DURATION):g.call(this)}};var f=a.fn.metisMenu;a.fn.metisMenu=c,a.fn.metisMenu.Constructor=e,a.fn.metisMenu.noConflict=function(){return a.fn.metisMenu=f,this}}(jQuery);
\ No newline at end of file
/*! Copyright (c) 2011 Piotr Rochala (http://rocha.la)
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
*
* Version: 1.3.6
*
*/
(function(e){e.fn.extend({slimScroll:function(g){var a=e.extend({width:"auto",height:"250px",size:"7px",color:"#000",position:"right",distance:"1px",start:"top",opacity:.4,alwaysVisible:!1,disableFadeOut:!1,railVisible:!1,railColor:"#333",railOpacity:.2,railDraggable:!0,railClass:"slimScrollRail",barClass:"slimScrollBar",wrapperClass:"slimScrollDiv",allowPageScroll:!1,wheelStep:20,touchScrollStep:200,borderRadius:"7px",railBorderRadius:"7px"},g);this.each(function(){function v(d){if(r){d=d||window.event;
var c=0;d.wheelDelta&&(c=-d.wheelDelta/120);d.detail&&(c=d.detail/3);e(d.target||d.srcTarget||d.srcElement).closest("."+a.wrapperClass).is(b.parent())&&m(c,!0);d.preventDefault&&!k&&d.preventDefault();k||(d.returnValue=!1)}}function m(d,e,g){k=!1;var f=d,h=b.outerHeight()-c.outerHeight();e&&(f=parseInt(c.css("top"))+d*parseInt(a.wheelStep)/100*c.outerHeight(),f=Math.min(Math.max(f,0),h),f=0<d?Math.ceil(f):Math.floor(f),c.css({top:f+"px"}));l=parseInt(c.css("top"))/(b.outerHeight()-c.outerHeight());
f=l*(b[0].scrollHeight-b.outerHeight());g&&(f=d,d=f/b[0].scrollHeight*b.outerHeight(),d=Math.min(Math.max(d,0),h),c.css({top:d+"px"}));b.scrollTop(f);b.trigger("slimscrolling",~~f);w();p()}function x(){u=Math.max(b.outerHeight()/b[0].scrollHeight*b.outerHeight(),30);c.css({height:u+"px"});var a=u==b.outerHeight()?"none":"block";c.css({display:a})}function w(){x();clearTimeout(B);l==~~l?(k=a.allowPageScroll,C!=l&&b.trigger("slimscroll",0==~~l?"top":"bottom")):k=!1;C=l;u>=b.outerHeight()?k=!0:(c.stop(!0,
!0).fadeIn("fast"),a.railVisible&&h.stop(!0,!0).fadeIn("fast"))}function p(){a.alwaysVisible||(B=setTimeout(function(){a.disableFadeOut&&r||y||z||(c.fadeOut("slow"),h.fadeOut("slow"))},1E3))}var r,y,z,B,A,u,l,C,k=!1,b=e(this);if(b.parent().hasClass(a.wrapperClass)){var n=b.scrollTop(),c=b.closest("."+a.barClass),h=b.closest("."+a.railClass);x();if(e.isPlainObject(g)){if("height"in g&&"auto"==g.height){b.parent().css("height","auto");b.css("height","auto");var q=b.parent().parent().height();b.parent().css("height",
q);b.css("height",q)}if("scrollTo"in g)n=parseInt(a.scrollTo);else if("scrollBy"in g)n+=parseInt(a.scrollBy);else if("destroy"in g){c.remove();h.remove();b.unwrap();return}m(n,!1,!0)}}else if(!(e.isPlainObject(g)&&"destroy"in g)){a.height="auto"==a.height?b.parent().height():a.height;n=e("<div></div>").addClass(a.wrapperClass).css({position:"relative",overflow:"hidden",width:a.width,height:a.height});b.css({overflow:"hidden",width:a.width,height:a.height});var h=e("<div></div>").addClass(a.railClass).css({width:a.size,
height:"100%",position:"absolute",top:0,display:a.alwaysVisible&&a.railVisible?"block":"none","border-radius":a.railBorderRadius,background:a.railColor,opacity:a.railOpacity,zIndex:90}),c=e("<div></div>").addClass(a.barClass).css({background:a.color,width:a.size,position:"absolute",top:0,opacity:a.opacity,display:a.alwaysVisible?"block":"none","border-radius":a.borderRadius,BorderRadius:a.borderRadius,MozBorderRadius:a.borderRadius,WebkitBorderRadius:a.borderRadius,zIndex:99}),q="right"==a.position?
{right:a.distance}:{left:a.distance};h.css(q);c.css(q);b.wrap(n);b.parent().append(c);b.parent().append(h);a.railDraggable&&c.bind("mousedown",function(a){var b=e(document);z=!0;t=parseFloat(c.css("top"));pageY=a.pageY;b.bind("mousemove.slimscroll",function(a){currTop=t+a.pageY-pageY;c.css("top",currTop);m(0,c.position().top,!1)});b.bind("mouseup.slimscroll",function(a){z=!1;p();b.unbind(".slimscroll")});return!1}).bind("selectstart.slimscroll",function(a){a.stopPropagation();a.preventDefault();return!1});
h.hover(function(){w()},function(){p()});c.hover(function(){y=!0},function(){y=!1});b.hover(function(){r=!0;w();p()},function(){r=!1;p()});b.bind("touchstart",function(a,b){a.originalEvent.touches.length&&(A=a.originalEvent.touches[0].pageY)});b.bind("touchmove",function(b){k||b.originalEvent.preventDefault();b.originalEvent.touches.length&&(m((A-b.originalEvent.touches[0].pageY)/a.touchScrollStep,!0),A=b.originalEvent.touches[0].pageY)});x();"bottom"===a.start?(c.css({top:b.outerHeight()-c.outerHeight()}),
m(0,!0)):"top"!==a.start&&(m(e(a.start).position().top,null,!0),a.alwaysVisible||c.hide());window.addEventListener?(this.addEventListener("DOMMouseScroll",v,!1),this.addEventListener("mousewheel",v,!1)):document.attachEvent("onmousewheel",v)}});return this}});e.fn.extend({slimscroll:e.fn.slimScroll})})(jQuery);
\ No newline at end of file
// validator
function zh_validator() {
// 验证手机号
jQuery.validator.addMethod("mobile", function(value, element) {
var tel = /^1[3|4|5|7|8]\d{9}$/;
return this.optional(element) || (tel.test(value));
}, "请输入有效的手机号码");
// 验证身份证号
jQuery.validator.addMethod("cardid", function(value, element) {
var tel = /^(\d{15}$|^\d{18}$|^\d{17}(\d|X|x))$/;
return this.optional(element) || (tel.test(value));
}, "请输入有效的身份证号");
// 自定义正则验证
jQuery.validator.addMethod("regular", function(value, element) {
var regular = eval(element.getAttribute('data-rule-regular'));
return this.optional(element) || (regular.test(value));
}, "输入有误");
$.extend($.validator.messages, {
required: "这是必填字段",
remote: "请修正此字段",
email: "请输入有效的电子邮件地址",
url: "请输入有效的网址",
date: "请输入有效的日期",
dateISO: "请输入有效的日期 (YYYY-MM-DD)",
number: "请输入有效的数字",
digits: "只能输入数字",
creditcard: "请输入有效的信用卡号码",
equalTo: "你的输入不相同",
extension: "请输入有效的后缀",
maxlength: $.validator.format("最多可以输入 {0} 个字符"),
minlength: $.validator.format("最少要输入 {0} 个字符"),
rangelength: $.validator.format("请输入长度在 {0} 到 {1} 位字符"),
range: $.validator.format("请输入范围在 {0} 到 {1} 之间的数值"),
max: $.validator.format("请输入不大于 {0} 的数值"),
min: $.validator.format("请输入不小于 {0} 的数值")
});
}
// table
function zh_table() {
$.extend($.fn.bootstrapTable.defaults, {
formatLoadingMessage: function() {
return '加载数据中,请稍候……'; },
formatRecordsPerPage: function(pageNumber) {
return '每页显示 ' + pageNumber + ' 条记录'; },
formatShowingRows: function(pageFrom, pageTo, totalRows) {
return '显示第 ' + pageFrom + ' 到第 ' + pageTo + ' 条记录,总共 ' + totalRows + ' 条记录'; },
formatSearch: function() {
return '搜索'; },
formatNoMatches: function() {
return '没有找到匹配的记录'; },
formatRefresh: function() {
return '刷新'; },
formatToggle: function() {
return '切换'; },
formatColumns: function() {
return '选择列'; }
});
}
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
require('../../js/transition.js')
require('../../js/alert.js')
require('../../js/button.js')
require('../../js/carousel.js')
require('../../js/collapse.js')
require('../../js/dropdown.js')
require('../../js/modal.js')
require('../../js/tooltip.js')
require('../../js/popover.js')
require('../../js/scrollspy.js')
require('../../js/tab.js')
require('../../js/affix.js')
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"swagger": "2.0",
"paths": {
"/index": {
"get": {
"tags": [
"\u7528\u6237\u4fe1\u606f"
],
"summary": "Add a new pet to the store",
"description": "",
"operationId": "read",
"consumes": [
"multipart/form-data"
],
"produces": [
"multipart/form-data"
],
"parameters": [
{
"name": "id",
"description": "Pet object that needs to be added to the store",
"required": false,
"schema": {
"$ref": "#/definitions/Pet"
},
"paramType": "form"
}
],
"responses": {
"405": {
"description": "Invalid input"
}
},
"security": [
{
"petstore_auth": [
"write:pets",
"read:pets"
]
}
]
}
}
},
"definitions": {}
}
\ No newline at end of file
#!/usr/bin/env php
<?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>
// +----------------------------------------------------------------------
// 定义项目路径
define('APP_PATH', __DIR__.'/app/');
// 加载框架引导文件
require './thinkphp/console.php';
\ No newline at end of file
/composer.lock
/vendor
.idea
.DS_Store
deny from all
\ No newline at end of file
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_CodeSniffer
- vendor/bin/phpcs --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 --standard=PSR2 --ignore="vendor/*" ./
## 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)
如何贡献我的源代码
===
此文档介绍了 ThinkPHP 团队的组成以及运转机制,您提交的代码将给 ThinkPHP 项目带来什么好处,以及如何才能加入我们的行列。
## 通过 Github 贡献代码
ThinkPHP 目前使用 Git 来控制程序版本,如果你想为 ThinkPHP 贡献源代码,请先大致了解 Git 的使用方法。我们目前把项目托管在 GitHub 上,任何 GitHub 用户都可以向我们贡献代码。
参与的方式很简单,`fork`一份 ThinkPHP 的代码到你的仓库中,修改后提交,并向我们发起`pull request`申请,我们会及时对代码进行审查并处理你的申请并。审查通过后,你的代码将被`merge`进我们的仓库中,这样你就会自动出现在贡献者名单里了,非常方便。
我们希望你贡献的代码符合:
* ThinkPHP 的编码规范
* 适当的注释,能让其他人读懂
* 遵循 Apache2 开源协议
**如果想要了解更多细节或有任何疑问,请继续阅读下面的内容**
### 注意事项
* 本项目代码格式化标准选用 [**PSR-2**](http://www.kancloud.cn/thinkphp/php-fig-psr/3141)
* 类名和类文件名遵循 [**PSR-4**](http://www.kancloud.cn/thinkphp/php-fig-psr/3144)
* 对于 Issues 的处理,请使用诸如 `fix #xxx(Issue ID)` 的 commit title 直接关闭 issue。
* 系统会自动在 PHP 5.4 5.5 5.6 7.0 和 HHVM 上测试修改,其中 HHVM 下的测试容许报错,请确保你的修改符合 PHP 5.4 ~ 5.6 和 PHP 7.0 的语法规范;
* 管理员不会合并造成 CI faild 的修改,若出现 CI faild 请检查自己的源代码或修改相应的[单元测试文件](tests)
## GitHub Issue
GitHub 提供了 Issue 功能,该功能可以用于:
* 提出 bug
* 提出功能改进
* 反馈使用体验
该功能不应该用于:
* 提出修改意见(涉及代码署名和修订追溯问题)
* 不友善的言论
## 快速修改
**GitHub 提供了快速编辑文件的功能**
1. 登录 GitHub 帐号;
2. 浏览项目文件,找到要进行修改的文件;
3. 点击右上角铅笔图标进行修改;
4. 填写 `Commit changes` 相关内容(Title 必填);
5. 提交修改,等待 CI 验证和管理员合并。
**若您需要一次提交大量修改,请继续阅读下面的内容**
## 完整流程
1. `fork`本项目;
2. 克隆(`clone`)你 `fork` 的项目到本地;
3. 新建分支(`branch`)并检出(`checkout`)新分支;
4. 添加本项目到你的本地 git 仓库作为上游(`upstream`);
5. 进行修改,若你的修改包含方法或函数的增减,请记得修改[单元测试文件](tests)
6. 变基(衍合 `rebase`)你的分支到上游 master 分支;
7. `push` 你的本地仓库到 GitHub;
8. 提交 `pull request`
9. 等待 CI 验证(若不通过则重复 5~7,GitHub 会自动更新你的 `pull request`);
10. 等待管理员处理,并及时 `rebase` 你的分支到上游 master 分支(若上游 master 分支有修改)。
*若有必要,可以 `git push -f` 强行推送 rebase 后的分支到自己的 `fork`*
*绝对不可以使用 `git push -f` 强行推送修改到上游*
### 注意事项
* 若对上述流程有任何不清楚的地方,请查阅 GIT 教程,如 [这个](http://backlogtool.com/git-guide/cn/)
* 对于代码**不同方面**的修改,请在自己 `fork` 的项目中**创建不同的分支**(原因参见`完整流程`第9条备注部分);
* 变基及交互式变基操作参见 [Git 交互式变基](http://pakchoi.me/2015/03/17/git-interactive-rebase/)
## 推荐资源
### 开发环境
* XAMPP for Windows 5.5.x
* WampServer (for Windows)
* upupw Apache PHP5.4 ( for Windows)
或自行安装
- Apache / Nginx
- PHP 5.4 ~ 5.6
- MySQL / MariaDB
*Windows 用户推荐添加 PHP bin 目录到 PATH,方便使用 composer*
*Linux 用户自行配置环境, Mac 用户推荐使用内置 Apache 配合 Homebrew 安装 PHP 和 MariaDB*
### 编辑器
Sublime Text 3 + phpfmt 插件
phpfmt 插件参数
```json
{
"autocomplete": true,
"enable_auto_align": true,
"format_on_save": true,
"indent_with_space": true,
"psr1_naming": false,
"psr2": true,
"version": 4
}
```
或其他 编辑器 / IDE 配合 PSR2 自动格式化工具
### Git GUI
* SourceTree
* GitHub Desktop
或其他 Git 图形界面客户端
ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn)
All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
Apache Licence是著名的非盈利开源组织Apache采用的协议。
该协议和BSD类似,鼓励代码共享和尊重原作者的著作权,
允许代码修改,再作为开源或商业软件发布。需要满足
的条件:
1. 需要给代码的用户一份Apache Licence ;
2. 如果你修改了代码,需要在被修改的文件中说明;
3. 在延伸的代码中(修改和有源代码衍生的代码中)需要
带有原来代码中的协议,商标,专利声明和其他原来作者规
定需要包含的说明;
4. 如果再发布的产品中包含一个Notice文件,则在Notice文
件中需要带有本协议内容。你可以在Notice中增加自己的
许可,但不可以表现为对Apache Licence构成更改。
具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
ThinkPHP 5.0
===============
[![Build Status](https://travis-ci.org/top-think/framework.svg?branch=master)](https://travis-ci.org/top-think/framework)
[![codecov.io](http://codecov.io/github/top-think/framework/coverage.svg?branch=master)](http://codecov.io/github/github/top-think/framework?branch=master)
[![Total Downloads](https://poser.pugx.org/topthink/framework/downloads)](https://packagist.org/packages/topthink/framework)
[![Latest Stable Version](https://poser.pugx.org/topthink/framework/v/stable)](https://packagist.org/packages/topthink/framework)
[![Latest Unstable Version](https://poser.pugx.org/topthink/framework/v/unstable)](https://packagist.org/packages/topthink/framework)
[![License](https://poser.pugx.org/topthink/framework/license)](https://packagist.org/packages/topthink/framework)
ThinkPHP5在保持快速开发和大道至简的核心理念不变的同时,PHP版本要求提升到5.4,优化核心,减少依赖,基于全新的架构思想和命名空间实现,是ThinkPHP突破原有框架思路的颠覆之作,其主要特性包括:
+ 基于命名空间和众多PHP新特性
+ 核心功能组件化
+ 强化路由功能
+ 更灵活的控制器
+ 重构的模型和数据库类
+ 配置文件可分离
+ 重写的自动验证和完成
+ 简化扩展机制
+ API支持完善
+ 改进的Log类
+ 命令行访问支持
+ REST支持
+ 引导文件支持
+ 方便的自动生成定义
+ 真正惰性加载
+ 分布式环境支持
+ 支持Composer
> ThinkPHP5的运行环境要求PHP5.4以上。
详细开发文档参考 [ThinkPHP5完全开发手册](http://www.kancloud.cn/manual/thinkphp5)
## 目录结构
初始的目录结构如下:
~~~
www WEB部署目录(或者子目录)
├─application 应用目录
│ ├─common 公共模块目录(可以更改)
│ ├─module_name 模块目录
│ │ ├─config.php 模块配置文件
│ │ ├─common.php 模块函数文件
│ │ ├─controller 控制器目录
│ │ ├─model 模型目录
│ │ ├─view 视图目录
│ │ └─ ... 更多类库目录
│ │
│ ├─command.php 命令行工具配置文件
│ ├─common.php 公共函数文件
│ ├─config.php 公共配置文件
│ ├─route.php 路由配置文件
│ ├─tags.php 应用行为扩展定义文件
│ └─database.php 数据库配置文件
├─public WEB目录(对外访问目录)
│ ├─index.php 入口文件
│ ├─router.php 快速测试文件
│ └─.htaccess 用于apache的重写
├─thinkphp 框架系统目录
│ ├─lang 语言文件目录
│ ├─library 框架类库目录
│ │ ├─think Think类库包目录
│ │ └─traits 系统Trait目录
│ │
│ ├─tpl 系统模板目录
│ ├─base.php 基础定义文件
│ ├─console.php 控制台入口文件
│ ├─convention.php 框架惯例配置文件
│ ├─helper.php 助手函数文件
│ ├─phpunit.xml phpunit配置文件
│ └─start.php 框架入口文件
├─extend 扩展类库目录
├─runtime 应用的运行时目录(可写,可定制)
├─vendor 第三方类库目录(Composer依赖库)
├─build.php 自动生成定义文件(参考)
├─composer.json composer 定义文件
├─LICENSE.txt 授权说明文件
├─README.md README 文件
├─think 命令行入口文件
~~~
> router.php用于php自带webserver支持,可用于快速测试
> 切换到public目录后,启动命令:php -S localhost:8888 router.php
> 上面的目录结构和名称是可以改变的,这取决于你的入口文件和配置参数。
## 命名规范
ThinkPHP5的命名规范遵循PSR-2规范以及PSR-4自动加载规范。
## 参与开发
注册并登录 Github 帐号, fork 本项目并进行改动。
更多细节参阅 [CONTRIBUTING.md](CONTRIBUTING.md)
## 版权信息
ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
本项目包含的第三方源码和二进制文件之版权信息另行标注。
版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn)
All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
更多细节参阅 [LICENSE.txt](LICENSE.txt)
<?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('THINK_VERSION', '5.0.4');
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);
comment:
layout: header, changes, diff
coverage:
ignore:
- base.php
- helper.php
- convention.php
- lang/zh-cn.php
- start.php
- console.php
status:
patch: false
{
"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.*",
"squizlabs/php_codesniffer": "2.*",
"phpdocumentor/reflection-docblock": "^2.0"
},
"autoload": {
"psr-4": {
"think\\": "library/think"
}
}
}
<?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>
// +----------------------------------------------------------------------
namespace think;
// ThinkPHP 引导文件
// 加载基础文件
require __DIR__ . '/base.php';
// 执行应用
App::initCommon();
Console::init();
\ No newline at end of file
<?php
return [
// +----------------------------------------------------------------------
// | 应用设置
// +----------------------------------------------------------------------
// 应用命名空间
'app_namespace' => 'app',
// 应用调试模式
'app_debug' => true,
// 应用Trace
'app_trace' => false,
// 应用模式状态
'app_status' => '',
// 是否支持多模块
'app_multi_module' => true,
// 入口自动绑定模块
'auto_bind_module' => false,
// 注册的根命名空间
'root_namespace' => [],
// 扩展函数文件
'extra_file_list' => [THINK_PATH . 'helper' . EXT],
// 默认输出类型
'default_return_type' => 'html',
// 默认AJAX 数据返回格式,可选json xml ...
'default_ajax_return' => 'json',
// 默认JSONP格式返回的处理方法
'default_jsonp_handler' => 'jsonpReturn',
// 默认JSONP处理方法
'var_jsonp_handler' => 'callback',
// 默认时区
'default_timezone' => 'PRC',
// 是否开启多语言
'lang_switch_on' => false,
// 默认全局过滤方法 用逗号分隔多个
'default_filter' => '',
// 默认语言
'default_lang' => 'zh-cn',
// 应用类库后缀
'class_suffix' => false,
// 控制器类后缀
'controller_suffix' => false,
// +----------------------------------------------------------------------
// | 模块设置
// +----------------------------------------------------------------------
// 默认模块名
'default_module' => 'index',
// 禁止访问模块
'deny_module_list' => ['common'],
// 默认控制器名
'default_controller' => 'Index',
// 默认操作名
'default_action' => 'index',
// 默认验证器
'default_validate' => '',
// 默认的空控制器名
'empty_controller' => 'Error',
// 操作方法前缀
'use_action_prefix' => false,
// 操作方法后缀
'action_suffix' => '',
// 自动搜索控制器
'controller_auto_search' => false,
// +----------------------------------------------------------------------
// | URL设置
// +----------------------------------------------------------------------
// PATHINFO变量名 用于兼容模式
'var_pathinfo' => 's',
// 兼容PATH_INFO获取
'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
// pathinfo分隔符
'pathinfo_depr' => '/',
// URL伪静态后缀
'url_html_suffix' => 'html',
// URL普通方式参数 用于自动生成
'url_common_param' => false,
// URL参数方式 0 按名称成对解析 1 按顺序解析
'url_param_type' => 0,
// 是否开启路由
'url_route_on' => true,
// 路由配置文件(支持配置多个)
'route_config_file' => ['route'],
// 路由使用完整匹配
'route_complete_match' => false,
// 是否强制使用路由
'url_route_must' => false,
// 域名部署
'url_domain_deploy' => false,
// 域名根,如thinkphp.cn
'url_domain_root' => '',
// 是否自动转换URL中的控制器和操作名
'url_convert' => true,
// 默认的访问控制器层
'url_controller_layer' => 'controller',
// 表单请求类型伪装变量
'var_method' => '_method',
// 表单ajax伪装变量
'var_ajax' => '_ajax',
// 表单pjax伪装变量
'var_pjax' => '_pjax',
// 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
'request_cache' => false,
// 请求缓存有效期
'request_cache_expire' => null,
// +----------------------------------------------------------------------
// | 模板设置
// +----------------------------------------------------------------------
'template' => [
// 模板引擎类型 支持 php think 支持扩展
'type' => 'Think',
// 视图基础目录,配置目录为所有模块的视图起始目录
'view_base' => '',
// 当前模板的视图目录 留空为自动获取
'view_path' => '',
// 模板后缀
'view_suffix' => 'html',
// 模板文件名分隔符
'view_depr' => DS,
// 模板引擎普通标签开始标记
'tpl_begin' => '{',
// 模板引擎普通标签结束标记
'tpl_end' => '}',
// 标签库标签开始标记
'taglib_begin' => '{',
// 标签库标签结束标记
'taglib_end' => '}',
],
// 视图输出字符串内容替换
'view_replace_str' => [],
// 默认跳转页面对应的模板文件
'dispatch_success_tmpl' => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl',
'dispatch_error_tmpl' => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl',
// +----------------------------------------------------------------------
// | 异常及错误设置
// +----------------------------------------------------------------------
// 异常页面的模板文件
'exception_tmpl' => THINK_PATH . 'tpl' . DS . 'think_exception.tpl',
// 错误显示信息,非调试模式有效
'error_message' => '页面错误!请稍后再试~',
// 显示错误信息
'show_error_msg' => false,
// 异常处理handle类 留空使用 \think\exception\Handle
'exception_handle' => '',
// +----------------------------------------------------------------------
// | 日志设置
// +----------------------------------------------------------------------
'log' => [
// 日志记录方式,内置 file socket 支持扩展
'type' => 'File',
// 日志保存目录
'path' => LOG_PATH,
// 日志记录级别
'level' => [],
],
// +----------------------------------------------------------------------
// | Trace设置 开启 app_trace 后 有效
// +----------------------------------------------------------------------
'trace' => [
// 内置Html Console 支持扩展
'type' => 'Html',
],
// +----------------------------------------------------------------------
// | 缓存设置
// +----------------------------------------------------------------------
'cache' => [
// 驱动方式
'type' => 'File',
// 缓存保存目录
'path' => CACHE_PATH,
// 缓存前缀
'prefix' => '',
// 缓存有效期 0表示永久缓存
'expire' => 0,
],
// +----------------------------------------------------------------------
// | 会话设置
// +----------------------------------------------------------------------
'session' => [
'id' => '',
// SESSION_ID的提交变量,解决flash上传跨域
'var_session_id' => '',
// SESSION 前缀
'prefix' => 'think',
// 驱动方式 支持redis memcache memcached
'type' => '',
// 是否自动开启 SESSION
'auto_start' => true,
],
// +----------------------------------------------------------------------
// | Cookie设置
// +----------------------------------------------------------------------
'cookie' => [
// cookie 名称前缀
'prefix' => '',
// cookie 保存时间
'expire' => 0,
// cookie 保存路径
'path' => '/',
// cookie 有效域名
'domain' => '',
// cookie 启用安全传输
'secure' => false,
// httponly设置
'httponly' => '',
// 是否使用 setcookie
'setcookie' => true,
],
// +----------------------------------------------------------------------
// | 数据库设置
// +----------------------------------------------------------------------
'database' => [
// 数据库类型
'type' => 'mysql',
// 数据库连接DSN配置
'dsn' => '',
// 服务器地址
'hostname' => 'localhost',
// 数据库名
'database' => '',
// 数据库用户名
'username' => 'root',
// 数据库密码
'password' => '',
// 数据库连接端口
'hostport' => '',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => '',
// 数据库调试模式
'debug' => false,
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => true,
// 自动写入时间戳字段
'auto_timestamp' => false,
],
//分页配置
'paginate' => [
'type' => 'bootstrap',
'var_page' => 'page',
'list_rows' => 15,
],
];
<?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 [
// 系统错误提示
'Undefined variable' => '未定义变量',
'Undefined index' => '未定义数组索引',
'Undefined offset' => '未定义数组下标',
'Parse error' => '语法解析错误',
'Type error' => '类型错误',
'Fatal error' => '致命错误',
'syntax error' => '语法错误',
// 框架核心错误提示
'dispatch type not support' => '不支持的调度类型',
'method param miss' => '方法参数错误',
'method not exists' => '方法不存在',
'module not exists' => '模块不存在',
'controller not exists' => '控制器不存在',
'class not exists' => '类不存在',
'property not exists' => '类的属性不存在',
'template not exists' => '模板文件不存在',
'illegal controller name' => '非法的控制器名称',
'illegal action name' => '非法的操作名称',
'url suffix deny' => '禁止的URL后缀访问',
'Route Not Found' => '当前访问路由未定义',
'Underfined db type' => '未定义数据库类型',
'variable type error' => '变量类型错误',
'PSR-4 error' => 'PSR-4 规范错误',
'not support total' => '简洁模式下不能获取数据总数',
'not support last' => '简洁模式下不能获取最后一页',
'error session handler' => '错误的SESSION处理器类',
'not allow php tag' => '模板不允许使用PHP语法',
'not support' => '不支持',
'redisd master' => 'Redisd 主服务器错误',
'redisd slave' => 'Redisd 从服务器错误',
'must run at sae' => '必须在SAE运行',
'memcache init error' => '未开通Memcache服务,请在SAE管理平台初始化Memcache服务',
'KVDB init error' => '没有初始化KVDB,请在SAE管理平台初始化KVDB服务',
'fields not exists' => '数据表字段不存在',
'where express error' => '查询表达式错误',
'no data to update' => '没有任何数据需要更新',
'miss data to insert' => '缺少需要写入的数据',
'miss complex primary data' => '缺少复合主键数据',
'miss update condition' => '缺少更新条件',
'model data Not Found' => '模型数据不存在',
'table data not Found' => '表数据不存在',
'delete without condition' => '没有条件不会执行删除操作',
'miss relation data' => '缺少关联表数据',
'tag attr must' => '模板标签属性必须',
'tag error' => '模板标签错误',
'cache write error' => '缓存写入失败',
'sae mc write error' => 'SAE mc 写入错误',
'route name not exists' => '路由标识不存在(或参数不够)',
'invalid request' => '非法请求',
'bind attr has exists' => '模型的属性已经存在',
];
<?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>
// +----------------------------------------------------------------------
namespace think;
class Build
{
/**
* 根据传入的build资料创建目录和文件
* @access protected
* @param array $build build列表
* @param string $namespace 应用类库命名空间
* @param bool $suffix 类库后缀
* @return void
*/
public static function run(array $build = [], $namespace = 'app', $suffix = false)
{
// 锁定
$lockfile = APP_PATH . 'build.lock';
if (is_writable($lockfile)) {
return;
} elseif (!touch($lockfile)) {
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($lockfile);
}
/**
* 创建目录
* @access protected
* @param array $list 目录列表
* @return void
*/
protected static function buildDir($list)
{
foreach ($list as $dir) {
if (!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 ? $module : '';
if (!is_dir(APP_PATH . $module)) {
// 创建模块目录
mkdir(APP_PATH . $module);
}
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) {
if (!is_dir($modulePath . $dir)) {
// 创建目录
mkdir($modulePath . $dir, 0755, true);
}
}
} 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';
if (!is_dir(dirname($filename))) {
// 创建目录
mkdir(dirname($filename), 0755, true);
}
$content = '';
break;
default:
// 其他文件
$content = "<?php\nnamespace {$space};\n\nclass {$class}\n{\n\n}";
}
if (!is_file($filename)) {
file_put_contents($filename, $content);
}
}
}
}
}
/**
* 创建模块的欢迎页面
* @access public
* @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)) {
$content = file_get_contents(THINK_PATH . 'tpl' . DS . 'default_index.tpl');
$content = str_replace(['{$app}', '{$module}', '{layer}', '{$suffix}'], [$namespace, $module ? $module . '\\' : '', 'controller', $suffix ? 'Controller' : ''], $content);
if (!is_dir(dirname($filename))) {
mkdir(dirname($filename), 0755, true);
}
file_put_contents($filename, $content);
}
}
/**
* 创建模块的公共文件
* @access public
* @param string $module 模块名
* @return void
*/
protected static function buildCommon($module)
{
$filename = CONF_PATH . ($module ? $module . DS : '') . 'config.php';
if (!is_file($filename)) {
file_put_contents($filename, "<?php\n//配置文件\nreturn [\n\n];");
}
$filename = APP_PATH . ($module ? $module . DS : '') . 'common.php';
if (!is_file($filename)) {
file_put_contents($filename, "<?php\n");
}
}
}
<?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>
// +----------------------------------------------------------------------
namespace think;
use think\App;
class Cache
{
protected static $instance = [];
public static $readTimes = 0;
public static $writeTimes = 0;
/**
* 操作句柄
* @var object
* @access protected
*/
protected static $handler;
/**
* 连接缓存
* @access public
* @param array $options 配置数组
* @param bool|string $name 缓存连接标识 true 强制重新连接
* @return \think\cache\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, '\\') ? $type : '\\think\\cache\\driver\\' . ucwords($type);
// 记录初始化信息
App::$debug && Log::record('[ CACHE ] INIT ' . $type, 'info');
if (true === $name) {
return new $class($options);
} else {
self::$instance[$name] = new $class($options);
}
}
self::$handler = self::$instance[$name];
return self::$handler;
}
/**
* 自动初始化缓存
* @access public
* @param array $options 配置数组
* @return void
*/
public static function init(array $options = [])
{
if (is_null(self::$handler)) {
// 自动初始化缓存
if (!empty($options)) {
self::connect($options);
} elseif ('complex' == Config::get('cache.type')) {
self::connect(Config::get('cache.default'));
} else {
self::connect(Config::get('cache'));
}
}
}
/**
* 切换缓存类型 需要配置 cache.type 为 complex
* @access public
* @param string $name 缓存标识
* @return \think\cache\Driver
*/
public static function store($name)
{
if ('complex' == Config::get('cache.type')) {
self::connect(Config::get('cache.' . $name), strtolower($name));
}
return self::$handler;
}
/**
* 判断缓存是否存在
* @access public
* @param string $name 缓存变量名
* @return bool
*/
public static function has($name)
{
self::init();
self::$readTimes++;
return self::$handler->has($name);
}
/**
* 读取缓存
* @access public
* @param string $name 缓存标识
* @param mixed $default 默认值
* @return mixed
*/
public static function get($name, $default = false)
{
self::init();
self::$readTimes++;
return self::$handler->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::init();
self::$writeTimes++;
return self::$handler->set($name, $value, $expire);
}
/**
* 自增缓存(针对数值缓存)
* @access public
* @param string $name 缓存变量名
* @param int $step 步长
* @return false|int
*/
public static function inc($name, $step = 1)
{
self::init();
self::$writeTimes++;
return self::$handler->inc($name, $step);
}
/**
* 自减缓存(针对数值缓存)
* @access public
* @param string $name 缓存变量名
* @param int $step 步长
* @return false|int
*/
public static function dec($name, $step = 1)
{
self::init();
self::$writeTimes++;
return self::$handler->dec($name, $step);
}
/**
* 删除缓存
* @access public
* @param string $name 缓存标识
* @return boolean
*/
public static function rm($name)
{
self::init();
self::$writeTimes++;
return self::$handler->rm($name);
}
/**
* 清除缓存
* @access public
* @param string $tag 标签名
* @return boolean
*/
public static function clear($tag = null)
{
self::init();
self::$writeTimes++;
return self::$handler->clear($tag);
}
/**
* 读取缓存并删除
* @access public
* @param string $name 缓存变量名
* @return mixed
*/
public static function pull($name)
{
self::init();
self::$readTimes++;
self::$writeTimes++;
return self::$handler->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::init();
self::$readTimes++;
return self::$handler->remember($name, $value, $expire);
}
/**
* 缓存标签
* @access public
* @param string $name 标签名
* @param string|array $keys 缓存标识
* @param bool $overlay 是否覆盖
* @return \think\cache\Driver
*/
public static function tag($name, $keys = null, $overlay = false)
{
self::init();
return self::$handler->tag($name, $keys, $overlay);
}
}
<?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: zhangyajun <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think;
use ArrayAccess;
use ArrayIterator;
use Countable;
use IteratorAggregate;
use JsonSerializable;
class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable
{
protected $items = [];
public function __construct($items = [])
{
$this->items = $this->convertToArray($items);
}
public static function make($items = [])
{
return new static($items);
}
/**
* 是否为空
* @return bool
*/
public function isEmpty()
{
return empty($this->items);
}
public function toArray()
{
return array_map(function ($value) {
return ($value instanceof Model || $value instanceof self) ? $value->toArray() : $value;
}, $this->items);
}
public function all()
{
return $this->items;
}
/**
* 合并数组
*
* @param mixed $items
* @return static
*/
public function merge($items)
{
return new static(array_merge($this->items, $this->convertToArray($items)));
}
/**
* 比较数组,返回差集
*
* @param mixed $items
* @return static
*/
public function diff($items)
{
return new static(array_diff($this->items, $this->convertToArray($items)));
}
/**
* 交换数组中的键和值
*
* @return static
*/
public function flip()
{
return new static(array_flip($this->items));
}
/**
* 比较数组,返回交集
*
* @param mixed $items
* @return static
*/
public function intersect($items)
{
return new static(array_intersect($this->items, $this->convertToArray($items)));
}
/**
* 返回数组中所有的键名
*
* @return static
*/
public function keys()
{
return new static(array_keys($this->items));
}
/**
* 删除数组的最后一个元素(出栈)
*
* @return mixed
*/
public function pop()
{
return array_pop($this->items);
}
/**
* 通过使用用户自定义函数,以字符串返回数组
*
* @param callable $callback
* @param mixed $initial
* @return mixed
*/
public function reduce(callable $callback, $initial = null)
{
return array_reduce($this->items, $callback, $initial);
}
/**
* 以相反的顺序返回数组。
*
* @return static
*/
public function reverse()
{
return new static(array_reverse($this->items));
}
/**
* 删除数组中首个元素,并返回被删除元素的值
*
* @return mixed
*/
public function shift()
{
return array_shift($this->items);
}
/**
* 把一个数组分割为新的数组块.
*
* @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);
}
/**
* 在数组开头插入一个元素
* @param mixed $value
* @param null $key
* @return int
*/
public function unshift($value, $key = null)
{
if (is_null($key)) {
array_unshift($this->items, $value);
} else {
$this->items = [$key => $value] + $this->items;
}
}
/**
* 给每个元素执行个回调
*
* @param callable $callback
* @return $this
*/
public function each(callable $callback)
{
foreach ($this->items as $key => $item) {
if ($callback($item, $key) === false) {
break;
}
}
return $this;
}
/**
* 用回调函数过滤数组中的元素
* @param callable|null $callback
* @return static
*/
public function filter(callable $callback = null)
{
if ($callback) {
return new static(array_filter($this->items, $callback));
}
return new static(array_filter($this->items));
}
/**
* 返回数组中指定的一列
* @param $column_key
* @param null $index_key
* @return array
*/
public function column($column_key, $index_key = null)
{
if (function_exists('array_column')) {
return array_column($this->items, $column_key, $index_key);
}
$result = [];
foreach ($this->items as $row) {
$key = $value = null;
$keySet = $valueSet = false;
if (null !== $index_key && array_key_exists($index_key, $row)) {
$keySet = true;
$key = (string)$row[$index_key];
}
if (null === $column_key) {
$valueSet = true;
$value = $row;
} elseif (is_array($row) && array_key_exists($column_key, $row)) {
$valueSet = true;
$value = $row[$column_key];
}
if ($valueSet) {
if ($keySet) {
$result[$key] = $value;
} else {
$result[] = $value;
}
}
}
return $result;
}
/**
* 对数组排序
*
* @param callable|null $callback
* @return static
*/
public function sort(callable $callback = null)
{
$items = $this->items;
$callback ? uasort($items, $callback) : uasort($items, function ($a, $b) {
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
});
return new static($items);
}
/**
* 将数组打乱
*
* @return static
*/
public function shuffle()
{
$items = $this->items;
shuffle($items);
return new static($items);
}
/**
* 截取数组
*
* @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));
}
// ArrayAccess
public function offsetExists($offset)
{
return array_key_exists($offset, $this->items);
}
public function offsetGet($offset)
{
return $this->items[$offset];
}
public function offsetSet($offset, $value)
{
if (is_null($offset)) {
$this->items[] = $value;
} else {
$this->items[$offset] = $value;
}
}
public function offsetUnset($offset)
{
unset($this->items[$offset]);
}
//Countable
public function count()
{
return count($this->items);
}
//IteratorAggregate
public function getIterator()
{
return new ArrayIterator($this->items);
}
//JsonSerializable
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);
}
public function __toString()
{
return $this->toJson();
}
/**
* 转换成数组
*
* @param mixed $items
* @return array
*/
protected function convertToArray($items)
{
if ($items instanceof self) {
return $items->all();
}
return (array)$items;
}
}
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment