目录结构调整
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
namespace think;
|
||||
|
||||
use think\Config;
|
||||
use think\debug\Trace;
|
||||
use think\Exception;
|
||||
use think\exception\HttpException;
|
||||
use think\exception\HttpResponseException;
|
||||
@@ -70,7 +71,7 @@ class App
|
||||
* 执行应用程序
|
||||
* @access public
|
||||
* @param Request $request Request对象
|
||||
* @return mixed
|
||||
* @return Response
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function run(Request $request = null)
|
||||
@@ -136,22 +137,29 @@ class App
|
||||
$data = $exception->getResponse();
|
||||
}
|
||||
|
||||
// 监听app_end
|
||||
Hook::listen('app_end', $data);
|
||||
// 清空类的实例化
|
||||
Loader::clearInstance();
|
||||
|
||||
// 输出数据到客户端
|
||||
if ($data instanceof Response) {
|
||||
return $data;
|
||||
$response = $data;
|
||||
} elseif (!is_null($data)) {
|
||||
// 默认自动识别响应输出类型
|
||||
$isAjax = $request->isAjax();
|
||||
$type = $isAjax ? Config::get('default_ajax_return') : Config::get('default_return_type');
|
||||
return Response::create($data, $type);
|
||||
$response = Response::create($data, $type);
|
||||
} else {
|
||||
return Response::create();
|
||||
$response = Response::create();
|
||||
}
|
||||
|
||||
|
||||
// 监听app_end
|
||||
Hook::listen('app_end', $response);
|
||||
|
||||
//注入Trace
|
||||
self::$debug && Trace::inject($response);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -349,6 +357,15 @@ class App
|
||||
self::$debug = Config::get('app_debug');
|
||||
if (!self::$debug) {
|
||||
ini_set('display_errors', 'Off');
|
||||
} else {
|
||||
//重新申请一块比较大的buffer
|
||||
if (ob_get_level() > 0) {
|
||||
$output = ob_get_clean();
|
||||
}
|
||||
ob_start();
|
||||
if (!empty($output)) {
|
||||
echo $output;
|
||||
}
|
||||
}
|
||||
|
||||
// 应用命名空间
|
||||
|
||||
@@ -81,7 +81,7 @@ class Config
|
||||
|
||||
if (!strpos($name, '.')) {
|
||||
// 判断环境变量
|
||||
$result = getenv(ENV_PREFIX . $name);
|
||||
$result = getenv(ENV_PREFIX . strtoupper($name));
|
||||
if (false !== $result) {
|
||||
return $result;
|
||||
}
|
||||
@@ -89,7 +89,7 @@ class Config
|
||||
} else {
|
||||
// 二维数组设置和获取支持
|
||||
$name = explode('.', $name);
|
||||
$result = getenv(ENV_PREFIX . $name[0] . '_' . $name[1]);
|
||||
$result = getenv(ENV_PREFIX . strtoupper($name[0] . '_' . $name[1]));
|
||||
// 判断环境变量
|
||||
if (false !== $result) {
|
||||
return $result;
|
||||
@@ -113,7 +113,7 @@ class Config
|
||||
}
|
||||
|
||||
if (!strpos($name, '.')) {
|
||||
$result = getenv(ENV_PREFIX . $name);
|
||||
$result = getenv(ENV_PREFIX . strtoupper($name));
|
||||
if (false !== $result) {
|
||||
return $result;
|
||||
}
|
||||
@@ -122,7 +122,7 @@ class Config
|
||||
} else {
|
||||
// 二维数组设置和获取支持
|
||||
$name = explode('.', $name);
|
||||
$result = getenv(ENV_PREFIX . $name[0] . '_' . $name[1]);
|
||||
$result = getenv(ENV_PREFIX . strtoupper($name[0] . '_' . $name[1]));
|
||||
// 判断环境变量
|
||||
if (false !== $result) {
|
||||
return $result;
|
||||
|
||||
@@ -43,9 +43,8 @@ class Hook
|
||||
|
||||
/**
|
||||
* 批量导入插件
|
||||
* @param array $data 插件信息
|
||||
* @param boolean $recursive 是否递归合并
|
||||
* @return void
|
||||
* @param array $tags 插件信息
|
||||
* @param boolean $recursive 是否递归合并
|
||||
*/
|
||||
public static function import($tags, $recursive = true)
|
||||
{
|
||||
|
||||
@@ -55,7 +55,7 @@ class Loader
|
||||
return false;
|
||||
}
|
||||
|
||||
includeFile($file);
|
||||
__include_file($file);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -142,35 +142,88 @@ class Loader
|
||||
{
|
||||
if (is_array($namespace)) {
|
||||
foreach ($namespace as $prefix => $paths) {
|
||||
self::setPsr4($prefix . '\\', rtrim($paths, DS));
|
||||
self::addPsr4($prefix . '\\', rtrim($paths, DS), true);
|
||||
}
|
||||
} else {
|
||||
self::setPsr4($namespace . '\\', rtrim($path, DS));
|
||||
self::addPsr4($namespace . '\\', rtrim($path, DS), true);
|
||||
}
|
||||
}
|
||||
|
||||
// 注册Psr0空间
|
||||
private static function setPsr0($prefix, $paths)
|
||||
// 添加Ps0空间
|
||||
private static function addPsr0($prefix, $paths, $prepend = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
self::$fallbackDirsPsr0 = (array)$paths;
|
||||
if ($prepend) {
|
||||
self::$fallbackDirsPsr0 = array_merge(
|
||||
(array)$paths,
|
||||
self::$fallbackDirsPsr0
|
||||
);
|
||||
} else {
|
||||
self::$fallbackDirsPsr0 = array_merge(
|
||||
self::$fallbackDirsPsr0,
|
||||
(array)$paths
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$first = $prefix[0];
|
||||
if (!isset(self::$prefixesPsr0[$first][$prefix])) {
|
||||
self::$prefixesPsr0[$first][$prefix] = (array)$paths;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($prepend) {
|
||||
self::$prefixesPsr0[$first][$prefix] = array_merge(
|
||||
(array)$paths,
|
||||
self::$prefixesPsr0[$first][$prefix]
|
||||
);
|
||||
} else {
|
||||
self::$prefixesPsr0[$prefix[0]][$prefix] = (array)$paths;
|
||||
self::$prefixesPsr0[$first][$prefix] = array_merge(
|
||||
self::$prefixesPsr0[$first][$prefix],
|
||||
(array)$paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 注册Psr4空间
|
||||
private static function setPsr4($prefix, $paths)
|
||||
|
||||
// 添加Psr4空间
|
||||
private static function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
self::$fallbackDirsPsr4 = (array)$paths;
|
||||
} else {
|
||||
// Register directories for the root namespace.
|
||||
if ($prepend) {
|
||||
self::$fallbackDirsPsr4 = array_merge(
|
||||
(array)$paths,
|
||||
self::$fallbackDirsPsr4
|
||||
);
|
||||
} else {
|
||||
self::$fallbackDirsPsr4 = array_merge(
|
||||
self::$fallbackDirsPsr4,
|
||||
(array)$paths
|
||||
);
|
||||
}
|
||||
} elseif (!isset(self::$prefixDirsPsr4[$prefix])) {
|
||||
// Register directories for a new namespace.
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
self::$prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
self::$prefixDirsPsr4[$prefix] = (array)$paths;
|
||||
} elseif ($prepend) {
|
||||
// Prepend directories for an already registered namespace.
|
||||
self::$prefixDirsPsr4[$prefix] = array_merge(
|
||||
(array)$paths,
|
||||
self::$prefixDirsPsr4[$prefix]
|
||||
);
|
||||
} else {
|
||||
// Append directories for an already registered namespace.
|
||||
self::$prefixDirsPsr4[$prefix] = array_merge(
|
||||
self::$prefixDirsPsr4[$prefix],
|
||||
(array)$paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,7 +250,9 @@ class Loader
|
||||
'traits' => LIB_PATH . 'traits' . DS,
|
||||
]);
|
||||
// 加载类库映射文件
|
||||
self::addClassMap(includeFile(THINK_PATH . 'classmap' . EXT));
|
||||
if (is_file(RUNTIME_PATH . 'classmap' . EXT)) {
|
||||
self::addClassMap(__include_file(RUNTIME_PATH . 'classmap' . EXT));
|
||||
}
|
||||
|
||||
// Composer自动加载支持
|
||||
if (is_dir(VENDOR_PATH . 'composer')) {
|
||||
@@ -214,14 +269,14 @@ class Loader
|
||||
if (is_file(VENDOR_PATH . 'composer/autoload_namespaces.php')) {
|
||||
$map = require VENDOR_PATH . 'composer/autoload_namespaces.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
self::setPsr0($namespace, $path);
|
||||
self::addPsr0($namespace, $path);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_file(VENDOR_PATH . 'composer/autoload_psr4.php')) {
|
||||
$map = require VENDOR_PATH . 'composer/autoload_psr4.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
self::setPsr4($namespace, $path);
|
||||
self::addPsr4($namespace, $path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,7 +291,7 @@ class Loader
|
||||
$includeFiles = require VENDOR_PATH . 'composer/autoload_files.php';
|
||||
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||
if (empty(self::$autoloadFiles[$fileIdentifier])) {
|
||||
requireFile($file);
|
||||
__require_file($file);
|
||||
self::$autoloadFiles[$fileIdentifier] = true;
|
||||
}
|
||||
}
|
||||
@@ -253,16 +308,18 @@ class Loader
|
||||
public static function import($class, $baseUrl = '', $ext = EXT)
|
||||
{
|
||||
static $_file = [];
|
||||
$key = $class . $baseUrl;
|
||||
$class = str_replace(['.', '#'], [DS, '.'], $class);
|
||||
if (isset($_file[$class . $baseUrl])) {
|
||||
if (isset($_file[$key])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (empty($baseUrl)) {
|
||||
list($name, $class) = explode(DS, $class, 2);
|
||||
if (isset(self::$prefixDirsPsr4[$name])) {
|
||||
|
||||
if (isset(self::$prefixDirsPsr4[$name . '\\'])) {
|
||||
// 注册的命名空间
|
||||
$baseUrl = self::$prefixDirsPsr4[$name];
|
||||
$baseUrl = self::$prefixDirsPsr4[$name . '\\'];
|
||||
} elseif ('@' == $name) {
|
||||
//加载当前模块应用类库
|
||||
$baseUrl = App::$modulePath;
|
||||
@@ -292,8 +349,8 @@ class Loader
|
||||
if (IS_WIN && pathinfo($filename, PATHINFO_FILENAME) != pathinfo(realpath($filename), PATHINFO_FILENAME)) {
|
||||
return false;
|
||||
}
|
||||
includeFile($filename);
|
||||
$_file[$class . $baseUrl] = true;
|
||||
__include_file($filename);
|
||||
$_file[$key] = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -483,12 +540,12 @@ class Loader
|
||||
* @param $file
|
||||
* @return mixed
|
||||
*/
|
||||
function includeFile($file)
|
||||
function __include_file($file)
|
||||
{
|
||||
return include $file;
|
||||
}
|
||||
|
||||
function requireFile($file)
|
||||
function __require_file($file)
|
||||
{
|
||||
return require $file;
|
||||
}
|
||||
@@ -10,9 +10,19 @@
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think;
|
||||
use think\exception\ClassNotFoundException;
|
||||
|
||||
use think\App;
|
||||
|
||||
/**
|
||||
* Class Log
|
||||
* @package think
|
||||
*
|
||||
* @method void log($msg) static
|
||||
* @method void error($msg) static
|
||||
* @method void info($msg) static
|
||||
* @method void sql($msg) static
|
||||
* @method void notice($msg) static
|
||||
* @method void alert($msg) static
|
||||
*/
|
||||
class Log
|
||||
{
|
||||
const LOG = 'log';
|
||||
@@ -30,40 +40,29 @@ class Log
|
||||
protected static $type = ['log', 'error', 'info', 'sql', 'notice', 'alert'];
|
||||
// 日志写入驱动
|
||||
protected static $driver;
|
||||
// 通知发送驱动
|
||||
protected static $alarm;
|
||||
|
||||
// 当前日志授权key
|
||||
protected static $key;
|
||||
|
||||
/**
|
||||
* 日志初始化
|
||||
* @return void
|
||||
* @param array $config
|
||||
*/
|
||||
public static function init($config = [])
|
||||
public static function init($config = [])
|
||||
{
|
||||
$type = isset($config['type']) ? $config['type'] : 'File';
|
||||
$class = false !== strpos($type, '\\') ? $type : '\\think\\log\\driver\\' . ucwords($type);
|
||||
self::$config = $config;
|
||||
unset($config['type']);
|
||||
self::$driver = new $class($config);
|
||||
if(class_exists($class)) {
|
||||
self::$driver = new $class($config);
|
||||
} else {
|
||||
throw new ClassNotFoundException('class not exists:' . $class, $class);
|
||||
}
|
||||
// 记录初始化信息
|
||||
App::$debug && Log::record('[ LOG ] INIT ' . $type . ': ' . var_export($config, true), 'info');
|
||||
}
|
||||
|
||||
/**
|
||||
* 通知初始化
|
||||
* @return void
|
||||
*/
|
||||
public static function alarm($config = [])
|
||||
{
|
||||
$type = isset($config['type']) ? $config['type'] : 'Email';
|
||||
$class = false !== strpos($type, '\\') ? $type : '\\think\\log\\alarm\\' . ucwords($type);
|
||||
unset($config['type']);
|
||||
self::$alarm = new $class($config['alarm']);
|
||||
// 记录初始化信息
|
||||
App::$debug && Log::record('[ CACHE ] ALARM ' . $type . ': ' . var_export($config, true), 'info');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取日志信息
|
||||
* @param string $type 信息类型
|
||||
@@ -164,19 +163,11 @@ class Log
|
||||
return self::$driver->save($log);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送预警通知
|
||||
* @param mixed $msg 调试信息
|
||||
* @return void
|
||||
*/
|
||||
public static function send($msg)
|
||||
{
|
||||
self::$alarm && self::$alarm->send($msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 静态调用
|
||||
* @return void
|
||||
* @param $method
|
||||
* @param $args
|
||||
* @return mixed
|
||||
*/
|
||||
public static function __callStatic($method, $args)
|
||||
{
|
||||
|
||||
@@ -135,7 +135,7 @@ class Request
|
||||
{
|
||||
if (array_key_exists($method, self::$hook)) {
|
||||
array_unshift($args, $this);
|
||||
call_user_func_array(self::$hook[$method], $args);
|
||||
return call_user_func_array(self::$hook[$method], $args);
|
||||
} else {
|
||||
throw new Exception('method not exists:' . __CLASS__ . '->' . $method);
|
||||
}
|
||||
|
||||
@@ -93,9 +93,6 @@ class Response
|
||||
// 处理输出数据
|
||||
$data = $this->getContent();
|
||||
|
||||
// 监听response_data
|
||||
Hook::listen('response_data', $data, $this);
|
||||
|
||||
if (!headers_sent() && !empty($this->header)) {
|
||||
// 发送状态码
|
||||
http_response_code($this->code);
|
||||
@@ -165,6 +162,26 @@ class Response
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置页面输出内容
|
||||
* @param $content
|
||||
* @return $this
|
||||
*/
|
||||
public function content($content)
|
||||
{
|
||||
if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable([
|
||||
$content,
|
||||
'__toString',
|
||||
])
|
||||
) {
|
||||
throw new \InvalidArgumentException(sprintf('variable type error: %s', gettype($content)));
|
||||
}
|
||||
|
||||
$this->content = (string)$content;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送HTTP状态
|
||||
* @param integer $code 状态码
|
||||
@@ -231,7 +248,7 @@ class Response
|
||||
$this->header['Content-Type'] = $contentType . '; charset=' . $charset;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取头部信息
|
||||
* @param string $name 头部名称
|
||||
@@ -257,17 +274,20 @@ class Response
|
||||
*/
|
||||
public function getContent()
|
||||
{
|
||||
$content = $this->output($this->data);
|
||||
if ($this->content == null) {
|
||||
$content = $this->output($this->data);
|
||||
|
||||
if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable([
|
||||
$content,
|
||||
'__toString',
|
||||
])
|
||||
) {
|
||||
throw new \InvalidArgumentException(sprintf('variable type error: %s', gettype($content)));
|
||||
if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable([
|
||||
$content,
|
||||
'__toString',
|
||||
])
|
||||
) {
|
||||
throw new \InvalidArgumentException(sprintf('variable type error: %s', gettype($content)));
|
||||
}
|
||||
|
||||
$this->content = (string)$content;
|
||||
}
|
||||
|
||||
return (string) $content;
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -776,8 +776,13 @@ class Query
|
||||
$fields[] = $alias . '.' . $val;
|
||||
$this->options['map'][$val] = $alias . '.' . $val;
|
||||
} else {
|
||||
$fields[] = $alias . '.' . $key . ' AS ' . $val;
|
||||
$this->options['map'][$val] = $alias . '.' . $key;
|
||||
if (preg_match('/[,=\.\'\"\(\s]/', $key)) {
|
||||
$name = $key;
|
||||
} else {
|
||||
$name = $alias . '.' . $key;
|
||||
}
|
||||
$fields[] = $name . ' AS ' . $val;
|
||||
$this->options['map'][$val] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1661,6 +1666,7 @@ class Query
|
||||
// 如果存在主键数据 则自动作为更新条件
|
||||
if (is_string($pk) && isset($data[$pk])) {
|
||||
$where[$pk] = $data[$pk];
|
||||
$key = 'think:' . $options['table'] . '|' . $data[$pk];
|
||||
unset($data[$pk]);
|
||||
} elseif (is_array($pk)) {
|
||||
// 增加复合主键支持
|
||||
@@ -1687,6 +1693,11 @@ class Query
|
||||
// 获取实际执行的SQL语句
|
||||
return $this->connection->getRealSql($sql, $this->bind);
|
||||
} else {
|
||||
// 检测缓存
|
||||
if (isset($key) && Cache::get($key)) {
|
||||
// 删除缓存
|
||||
Cache::rm($key);
|
||||
}
|
||||
// 执行操作
|
||||
return '' == $sql ? 0 : $this->execute($sql, $this->getBind());
|
||||
}
|
||||
@@ -1808,8 +1819,12 @@ class Query
|
||||
$result = false;
|
||||
if (empty($options['fetch_sql']) && !empty($options['cache'])) {
|
||||
// 判断查询缓存
|
||||
$cache = $options['cache'];
|
||||
$key = is_string($cache['key']) ? $cache['key'] : md5(serialize($options));
|
||||
$cache = $options['cache'];
|
||||
if (true === $cache['key'] && !is_array($data)) {
|
||||
$key = 'think:' . $options['table'] . '|' . $data;
|
||||
} else {
|
||||
$key = is_string($cache['key']) ? $cache['key'] : md5(serialize($options));
|
||||
}
|
||||
$result = Cache::get($key);
|
||||
}
|
||||
if (!$result) {
|
||||
@@ -1959,6 +1974,10 @@ class Query
|
||||
$options = $this->parseExpress();
|
||||
|
||||
if (!is_null($data) && true !== $data) {
|
||||
if (!is_array($data)) {
|
||||
// 缓存标识
|
||||
$key = 'think:' . $options['table'] . '|' . $data;
|
||||
}
|
||||
// AR模式分析主键条件
|
||||
$this->parsePkWhere($data, $options);
|
||||
}
|
||||
@@ -1969,10 +1988,17 @@ class Query
|
||||
}
|
||||
// 生成删除SQL语句
|
||||
$sql = $this->builder()->delete($options);
|
||||
|
||||
if ($options['fetch_sql']) {
|
||||
// 获取实际执行的SQL语句
|
||||
return $this->connection->getRealSql($sql, $this->bind);
|
||||
}
|
||||
|
||||
// 检测缓存
|
||||
if (isset($key) && Cache::get($key)) {
|
||||
// 删除缓存
|
||||
Cache::rm($key);
|
||||
}
|
||||
// 执行操作
|
||||
return $this->execute($sql, $this->getBind());
|
||||
}
|
||||
|
||||
63
core/library/think/debug/Trace.php
Normal file
63
core/library/think/debug/Trace.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace think\debug;
|
||||
|
||||
use think\Config;
|
||||
use think\exception\ClassNotFoundException;
|
||||
use think\Log;
|
||||
use think\Request;
|
||||
use think\Response;
|
||||
use think\response\Redirect;
|
||||
|
||||
class Trace
|
||||
{
|
||||
public static function inject(Response $response)
|
||||
{
|
||||
$config = Config::get('trace');
|
||||
|
||||
$type = isset($config['type']) ? $config['type'] : 'Html';
|
||||
|
||||
if ($type !== false) {
|
||||
$request = Request::instance();
|
||||
$accept = $request->header('accept');
|
||||
$contentType = $response->getHeader('Content-Type');
|
||||
|
||||
$class = false !== strpos($type, '\\') ? $type : '\\think\\debug\\trace\\' . ucwords($type);
|
||||
unset($config['type']);
|
||||
if(class_exists($class)) {
|
||||
$trace = new $class($config);
|
||||
} else {
|
||||
throw new ClassNotFoundException('class not exists:' . $class, $class);
|
||||
}
|
||||
|
||||
if ($response instanceof Redirect) {
|
||||
//TODO 记录
|
||||
} elseif (strpos($accept, 'application/json') === 0 || $request->isAjax()) {
|
||||
//TODO 记录
|
||||
} elseif (!empty($contentType) && strpos($contentType, 'html') === false) {
|
||||
//TODO 记录
|
||||
} else {
|
||||
$output = $trace->output(Log::getLog());
|
||||
|
||||
$content = $response->getContent();
|
||||
|
||||
$pos = strripos($content, '</body>');
|
||||
if (false !== $pos) {
|
||||
$content = substr($content, 0, $pos) . $output . substr($content, $pos);
|
||||
} else {
|
||||
$content = $content . $output;
|
||||
}
|
||||
|
||||
$response->content($content);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,18 +9,17 @@
|
||||
// | Author: yangweijie <yangweijiester@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\log\driver;
|
||||
namespace think\debug\trace;
|
||||
|
||||
use think\Cache;
|
||||
use think\Config;
|
||||
use think\Db;
|
||||
use think\Debug;
|
||||
use think\Request;
|
||||
|
||||
/**
|
||||
* 浏览器调试输出
|
||||
*/
|
||||
class Browser
|
||||
class Console
|
||||
{
|
||||
protected $config = [
|
||||
'trace_tabs' => ['base' => '基本', 'file' => '文件', 'info' => '流程', 'notice|error' => '错误', 'sql' => 'SQL', 'debug|log' => '调试'],
|
||||
@@ -40,21 +39,22 @@ class Browser
|
||||
* @param array $log 日志信息
|
||||
* @return bool
|
||||
*/
|
||||
public function save(array $log = [])
|
||||
public function output(array $log = [])
|
||||
{
|
||||
if (IS_CLI || IS_API || Request::instance()->isAjax() || (defined('RESPONSE_TYPE') && !in_array(RESPONSE_TYPE, ['html', 'view']))) {
|
||||
// ajax cli api方式下不输出
|
||||
return false;
|
||||
}
|
||||
// 获取基本信息
|
||||
$runtime = microtime(true) - START_TIME;
|
||||
$reqs = number_format(1 / number_format($runtime, 8), 2);
|
||||
$runtime = number_format($runtime, 6);
|
||||
$runtime = number_format(microtime(true), 8, '.', '') - START_TIME;
|
||||
$reqs = number_format(1 / $runtime, 2);
|
||||
$mem = number_format((memory_get_usage() - START_MEM) / 1024, 2);
|
||||
|
||||
if (isset($_SERVER['HTTP_HOST'])) {
|
||||
$uri = $_SERVER['SERVER_PROTOCOL'] . ' ' . $_SERVER['REQUEST_METHOD'] . ' : ' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
||||
} else {
|
||||
$uri = "cmd:" . implode(' ', $_SERVER['argv']);
|
||||
}
|
||||
|
||||
// 页面Trace信息
|
||||
$base = [
|
||||
'请求信息' => date('Y-m-d H:i:s', $_SERVER['REQUEST_TIME']) . ' ' . $_SERVER['SERVER_PROTOCOL'] . ' ' . $_SERVER['REQUEST_METHOD'] . ' : ' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'],
|
||||
'请求信息' => date('Y-m-d H:i:s', $_SERVER['REQUEST_TIME']) . ' ' . $uri,
|
||||
'运行时间' => "{$runtime}s [ 吞吐率:{$reqs}req/s ] 内存消耗:{$mem}kb 文件加载:" . count(get_included_files()),
|
||||
'查询信息' => Db::$queryTimes . ' queries ' . Db::$executeTimes . ' writes ',
|
||||
'缓存信息' => Cache::$readTimes . ' reads,' . Cache::$writeTimes . ' writes',
|
||||
@@ -96,54 +96,53 @@ class Browser
|
||||
//输出到控制台
|
||||
$lines = '';
|
||||
foreach ($trace as $type => $msg) {
|
||||
$lines .= $this->output($type, $msg);
|
||||
$lines .= $this->console($type, $msg);
|
||||
}
|
||||
$js = <<<JS
|
||||
|
||||
<script>
|
||||
<script type='text/javascript'>
|
||||
{$lines}
|
||||
</script>
|
||||
JS;
|
||||
echo $js;
|
||||
return true;
|
||||
return $js;
|
||||
}
|
||||
|
||||
public function output($type, $msg)
|
||||
protected function console($type, $msg)
|
||||
{
|
||||
$type = strtolower($type);
|
||||
$trace_tabs = array_values($this->config['trace_tabs']);
|
||||
$line[] = ($type == $trace_tabs[0] || '调试' == $type || '错误'== $type)
|
||||
? "console.group('{$type}');"
|
||||
: "console.groupCollapsed('{$type}');";
|
||||
$line[] = ($type == $trace_tabs[0] || '调试' == $type || '错误' == $type)
|
||||
? "console.group('{$type}');"
|
||||
: "console.groupCollapsed('{$type}');";
|
||||
|
||||
foreach ((array)$msg as $key => $m) {
|
||||
foreach ((array) $msg as $key => $m) {
|
||||
switch ($type) {
|
||||
case '调试':
|
||||
$var_type = gettype($m);
|
||||
if(in_array($var_type, ['array', 'string'])){
|
||||
$line[] = "console.log(".json_encode($m).");";
|
||||
}else{
|
||||
$line[] = "console.log(".json_encode(var_export($m, 1)).");";
|
||||
if (in_array($var_type, ['array', 'string'])) {
|
||||
$line[] = "console.log(" . json_encode($m) . ");";
|
||||
} else {
|
||||
$line[] = "console.log(" . json_encode(var_export($m, 1)) . ");";
|
||||
}
|
||||
break;
|
||||
case '错误':
|
||||
$msg = str_replace(PHP_EOL, '\n', $m);
|
||||
$style = 'color:#F4006B;font-size:14px;';
|
||||
$line[] = "console.error(\"%c{$msg}\", \"{$style}\");";
|
||||
$msg = str_replace(PHP_EOL, '\n', $m);
|
||||
$style = 'color:#F4006B;font-size:14px;';
|
||||
$line[] = "console.error(\"%c{$msg}\", \"{$style}\");";
|
||||
break;
|
||||
case 'sql':
|
||||
$msg = str_replace(PHP_EOL, '\n', $m);
|
||||
$style = "color:#009bb4;";
|
||||
$line[] = "console.log(\"%c{$msg}\", \"{$style}\");";
|
||||
$msg = str_replace(PHP_EOL, '\n', $m);
|
||||
$style = "color:#009bb4;";
|
||||
$line[] = "console.log(\"%c{$msg}\", \"{$style}\");";
|
||||
break;
|
||||
default:
|
||||
$m = is_string($key)? $key . ' ' . $m : $key+1 . ' ' . $m;
|
||||
$msg = json_encode($m);
|
||||
$line[] = "console.log({$msg});";
|
||||
$m = is_string($key) ? $key . ' ' . $m : $key + 1 . ' ' . $m;
|
||||
$msg = json_encode($m);
|
||||
$line[] = "console.log({$msg});";
|
||||
break;
|
||||
}
|
||||
}
|
||||
$line[]= "console.groupEnd();";
|
||||
$line[] = "console.groupEnd();";
|
||||
return implode(PHP_EOL, $line);
|
||||
}
|
||||
|
||||
@@ -9,18 +9,17 @@
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\log\driver;
|
||||
namespace think\debug\trace;
|
||||
|
||||
use think\Cache;
|
||||
use think\Config;
|
||||
use think\Db;
|
||||
use think\Debug;
|
||||
use think\Request;
|
||||
|
||||
/**
|
||||
* 页面Trace调试
|
||||
*/
|
||||
class Trace
|
||||
class Html
|
||||
{
|
||||
protected $config = [
|
||||
'trace_file' => '',
|
||||
@@ -40,22 +39,22 @@ class Trace
|
||||
* @param array $log 日志信息
|
||||
* @return bool
|
||||
*/
|
||||
public function save(array $log = [])
|
||||
public function output(array $log = [])
|
||||
{
|
||||
if (IS_CLI || IS_API || Request::instance()->isAjax() || (defined('RESPONSE_TYPE') && !in_array(RESPONSE_TYPE, ['html', 'view']))) {
|
||||
// ajax cli api方式下不输出
|
||||
return false;
|
||||
}
|
||||
|
||||
// 获取基本信息
|
||||
$runtime = microtime(true) - START_TIME;
|
||||
$reqs = number_format(1 / number_format($runtime, 8), 2);
|
||||
$runtime = number_format($runtime, 6);
|
||||
$runtime = number_format(microtime(true), 8, '.', '') - START_TIME;
|
||||
$reqs = number_format(1 / $runtime, 2);
|
||||
$mem = number_format((memory_get_usage() - START_MEM) / 1024, 2);
|
||||
|
||||
// 页面Trace信息
|
||||
if (isset($_SERVER['HTTP_HOST'])) {
|
||||
$uri = $_SERVER['SERVER_PROTOCOL'] . ' ' . $_SERVER['REQUEST_METHOD'] . ' : ' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
||||
} else {
|
||||
$uri = "cmd:" . implode(' ', $_SERVER['argv']);
|
||||
}
|
||||
$base = [
|
||||
'请求信息' => date('Y-m-d H:i:s', $_SERVER['REQUEST_TIME']) . ' ' . $_SERVER['SERVER_PROTOCOL'] . ' ' . $_SERVER['REQUEST_METHOD'] . ' : ' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'],
|
||||
'请求信息' => date('Y-m-d H:i:s', $_SERVER['REQUEST_TIME']) . ' ' . $uri,
|
||||
'运行时间' => "{$runtime}s [ 吞吐率:{$reqs}req/s ] 内存消耗:{$mem}kb 文件加载:" . count(get_included_files()),
|
||||
'查询信息' => Db::$queryTimes . ' queries ' . Db::$executeTimes . ' writes ',
|
||||
'缓存信息' => Cache::$readTimes . ' reads,' . Cache::$writeTimes . ' writes',
|
||||
@@ -96,8 +95,7 @@ class Trace
|
||||
// 调用Trace页面模板
|
||||
ob_start();
|
||||
include $this->config['trace_file'];
|
||||
echo ob_get_clean();
|
||||
return true;
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -155,8 +155,10 @@ class Handle
|
||||
while (ob_get_level() > 1) {
|
||||
ob_end_clean();
|
||||
}
|
||||
|
||||
$data['echo'] = ob_get_clean();
|
||||
|
||||
ob_start();
|
||||
ob_implicit_flush(0);
|
||||
extract($data);
|
||||
include Config::get('exception_tmpl');
|
||||
// 获取并清空缓存
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
<?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: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\log\alarm;
|
||||
|
||||
/**
|
||||
* 邮件通知驱动
|
||||
*/
|
||||
class Email
|
||||
{
|
||||
|
||||
protected $config = [
|
||||
'address' => '',
|
||||
];
|
||||
|
||||
// 实例化并传入参数
|
||||
public function __construct($config = [])
|
||||
{
|
||||
$this->config = array_merge($this->config, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通知发送接口
|
||||
* @access public
|
||||
* @param string $msg 日志信息
|
||||
* @return bool
|
||||
*/
|
||||
public function send($msg = '')
|
||||
{
|
||||
return error_log($msg, 1, $this->config['address']);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -54,9 +54,8 @@ class File
|
||||
} else {
|
||||
$current_uri = "cmd:" . implode(' ', $_SERVER['argv']);
|
||||
}
|
||||
$runtime = microtime(true) - START_TIME;
|
||||
$reqs = number_format(1 / number_format($runtime, 8), 2);
|
||||
$runtime = number_format($runtime, 6);
|
||||
$runtime = number_format(microtime(true), 8, '.', '') - START_TIME;
|
||||
$reqs = number_format(1 / $runtime, 2);
|
||||
$time_str = " [运行时间:{$runtime}s] [吞吐率:{$reqs}req/s]";
|
||||
$memory_use = number_format((memory_get_usage() - START_MEM) / 1024, 2);
|
||||
$memory_str = " [内存消耗:{$memory_use}kb]";
|
||||
@@ -67,7 +66,7 @@ class File
|
||||
foreach ($val as $msg) {
|
||||
if (!is_string($msg)) {
|
||||
$msg = var_export($msg, true);
|
||||
}
|
||||
}
|
||||
$info .= '[ ' . $type . ' ] ' . $msg . "\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,9 +33,8 @@ class Sae
|
||||
} else {
|
||||
$current_uri = "cmd:" . implode(' ', $_SERVER['argv']);
|
||||
}
|
||||
$runtime = microtime(true) - START_TIME;
|
||||
$reqs = number_format(1 / number_format($runtime, 8), 2);
|
||||
$runtime = number_format($runtime, 6);
|
||||
$runtime = number_format(microtime(true), 8, '.', '') - START_TIME;
|
||||
$reqs = number_format(1 / $runtime, 2);
|
||||
$time_str = " [运行时间:{$runtime}s] [吞吐率:{$reqs}req/s]";
|
||||
$memory_use = number_format((memory_get_usage() - START_MEM) / 1024, 2);
|
||||
$memory_str = " [内存消耗:{$memory_use}kb]";
|
||||
@@ -46,7 +45,7 @@ class Sae
|
||||
foreach ($val as $msg) {
|
||||
if (!is_string($msg)) {
|
||||
$msg = var_export($msg, true);
|
||||
}
|
||||
}
|
||||
$info .= '[ ' . $type . ' ] ' . $msg . "\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,9 +65,8 @@ class Socket
|
||||
if (!$this->check()) {
|
||||
return false;
|
||||
}
|
||||
$runtime = microtime(true) - START_TIME;
|
||||
$runtime = number_format(microtime(true), 8, '.', '') - START_TIME;
|
||||
$reqs = number_format(1 / number_format($runtime, 8), 2);
|
||||
$runtime = number_format($runtime, 6);
|
||||
$time_str = " [运行时间:{$runtime}s][吞吐率:{$reqs}req/s]";
|
||||
$memory_use = number_format((memory_get_usage() - START_MEM) / 1024, 2);
|
||||
$memory_str = " [内存消耗:{$memory_use}kb]";
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
namespace think\response;
|
||||
|
||||
use think\Request;
|
||||
use think\Response;
|
||||
|
||||
class Jsonp extends Response
|
||||
@@ -32,8 +33,9 @@ class Jsonp extends Response
|
||||
*/
|
||||
protected function output($data)
|
||||
{
|
||||
// 返回JSON数据格式到客户端 包含状态信息
|
||||
$handler = !empty($_GET[$this->options['var_jsonp_handler']]) ? $_GET[$this->options['var_jsonp_handler']] : $this->options['default_jsonp_handler'];
|
||||
// 返回JSON数据格式到客户端 包含状态信息 [当url_common_param为false时是无法获取到$_GET的数据的,故使用Request来获取<xiaobo.sun@qq.com>]
|
||||
$var_jsonp_handler = Request::instance()->param($this->options['var_jsonp_handler'], "");
|
||||
$handler = !empty($var_jsonp_handler) ? $var_jsonp_handler : $this->options['default_jsonp_handler'];
|
||||
$data = $handler . '(' . json_encode($data, $this->options['json_encode_param']) . ');';
|
||||
return $data;
|
||||
}
|
||||
|
||||
@@ -620,9 +620,9 @@ class Cx extends Taglib
|
||||
return $parseStr;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* U函数的tag标签
|
||||
* 格式:<url link="模块/控制器/方法" vars="参数" suffix="true或者false 是否带有后缀" domain="true或者false 是否携带域名" />
|
||||
* 格式:{url link="模块/控制器/方法" vars="参数" suffix="true或者false 是否带有后缀" domain="true或者false 是否携带域名" /}
|
||||
* @access public
|
||||
* @param array $tag 标签属性
|
||||
* @param string $content 标签内容
|
||||
|
||||
Reference in New Issue
Block a user