更新composer组件

This commit is contained in:
Anyon 2017-02-09 21:17:45 -05:00
parent b086a795e9
commit 8817a436be
30 changed files with 335 additions and 153 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
.idea .idea
.svn .svn
runtime runtime
composer.lock

View File

@ -5,3 +5,4 @@
@composer update --profile --prefer-dist --optimize-autoloader @composer update --profile --prefer-dist --optimize-autoloader
@echo ========= 压缩并发布插件 ========= @echo ========= 压缩并发布插件 =========
@composer dump-autoload --optimize @composer dump-autoload --optimize
pause

View File

@ -28,6 +28,7 @@ ThinkPHP5在保持快速开发和大道至简的核心理念不变的同时PH
+ 真正惰性加载 + 真正惰性加载
+ 分布式环境支持 + 分布式环境支持
+ 支持Composer + 支持Composer
+ 支持MongoDb
> ThinkPHP5的运行环境要求PHP5.4以上。 > ThinkPHP5的运行环境要求PHP5.4以上。

View File

@ -9,7 +9,7 @@
// | Author: liu21st <liu21st@gmail.com> // | Author: liu21st <liu21st@gmail.com>
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
define('THINK_VERSION', '5.0.5'); define('THINK_VERSION', '5.0.6');
define('THINK_START_TIME', microtime(true)); define('THINK_START_TIME', microtime(true));
define('THINK_START_MEM', memory_get_usage()); define('THINK_START_MEM', memory_get_usage());
define('EXT', '.php'); define('EXT', '.php');

View File

@ -107,6 +107,8 @@ return [
'request_cache' => false, 'request_cache' => false,
// 请求缓存有效期 // 请求缓存有效期
'request_cache_expire' => null, 'request_cache_expire' => null,
// 全局请求缓存排除规则
'request_cache_except' => [],
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | 模板设置 // | 模板设置
@ -272,10 +274,6 @@ return [
'datetime_format' => 'Y-m-d H:i:s', 'datetime_format' => 'Y-m-d H:i:s',
// 是否需要进行SQL性能分析 // 是否需要进行SQL性能分析
'sql_explain' => false, 'sql_explain' => false,
// Builder类
'builder' => '',
// Query类
'query' => '\\think\\db\\Query',
], ],
//分页配置 //分页配置

View File

@ -495,15 +495,16 @@ if (!function_exists('redirect')) {
* @param mixed $url 重定向地址 支持Url::build方法的地址 * @param mixed $url 重定向地址 支持Url::build方法的地址
* @param array|integer $params 额外参数 * @param array|integer $params 额外参数
* @param integer $code 状态码 * @param integer $code 状态码
* @param array $with 隐式传参
* @return \think\response\Redirect * @return \think\response\Redirect
*/ */
function redirect($url = [], $params = [], $code = 302) function redirect($url = [], $params = [], $code = 302, $with = [])
{ {
if (is_integer($params)) { if (is_integer($params)) {
$code = $params; $code = $params;
$params = []; $params = [];
} }
return Response::create($url, 'redirect', $code)->params($params); return Response::create($url, 'redirect', $code)->params($params)->with($with);
} }
} }

View File

@ -118,7 +118,7 @@ class App
// 监听app_begin // 监听app_begin
Hook::listen('app_begin', $dispatch); Hook::listen('app_begin', $dispatch);
// 请求缓存检查 // 请求缓存检查
$request->cache($config['request_cache'], $config['request_cache_expire']); $request->cache($config['request_cache'], $config['request_cache_expire'], $config['request_cache_except']);
switch ($dispatch['type']) { switch ($dispatch['type']) {
case 'redirect': case 'redirect':
@ -336,7 +336,7 @@ class App
$request->module($module); $request->module($module);
$config = self::init($module); $config = self::init($module);
// 模块请求缓存检查 // 模块请求缓存检查
$request->cache($config['request_cache'], $config['request_cache_expire']); $request->cache($config['request_cache'], $config['request_cache_expire'], $config['request_cache_except']);
} else { } else {
throw new HttpException(404, 'module not exists:' . $module); throw new HttpException(404, 'module not exists:' . $module);
} }

View File

@ -81,9 +81,9 @@ class Cache
* @param string $name 缓存标识 * @param string $name 缓存标识
* @return Driver * @return Driver
*/ */
public static function store($name) public static function store($name = '')
{ {
if ('complex' == Config::get('cache.type')) { if ('' !== $name && 'complex' == Config::get('cache.type')) {
self::connect(Config::get('cache.' . $name), strtolower($name)); self::connect(Config::get('cache.' . $name), strtolower($name));
} }
return self::$handler; return self::$handler;

View File

@ -189,7 +189,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
} }
// 全局作用域 // 全局作用域
if ($baseQuery && method_exists($this, 'base')) { if ($baseQuery && method_exists($this, 'base')) {
call_user_func_array([$this, 'base'], [& self::$links[$model]]); call_user_func_array([$this, 'base'], [ & self::$links[$model]]);
} }
// 返回当前模型的数据库查询对象 // 返回当前模型的数据库查询对象
return self::$links[$model]; return self::$links[$model];
@ -328,7 +328,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
} elseif (is_string($this->autoWriteTimestamp) && in_array(strtolower($this->autoWriteTimestamp), [ } elseif (is_string($this->autoWriteTimestamp) && in_array(strtolower($this->autoWriteTimestamp), [
'datetime', 'datetime',
'date', 'date',
'timestamp' 'timestamp',
]) ])
) { ) {
$value = $this->formatDateTime($_SERVER['REQUEST_TIME'], $this->dateFormat); $value = $this->formatDateTime($_SERVER['REQUEST_TIME'], $this->dateFormat);
@ -350,7 +350,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
{ {
if (false !== strpos($format, '\\')) { if (false !== strpos($format, '\\')) {
$time = new $format($time); $time = new $format($time);
} elseif (!$timestamp) { } elseif (!$timestamp && false !== $format) {
$time = date($format, $time); $time = date($format, $time);
} }
return $time; return $time;
@ -441,7 +441,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
if (is_string($this->autoWriteTimestamp) && in_array(strtolower($this->autoWriteTimestamp), [ if (is_string($this->autoWriteTimestamp) && in_array(strtolower($this->autoWriteTimestamp), [
'datetime', 'datetime',
'date', 'date',
'timestamp' 'timestamp',
]) ])
) { ) {
$value = $this->formatDateTime(strtotime($value), $this->dateFormat); $value = $this->formatDateTime(strtotime($value), $this->dateFormat);
@ -1018,6 +1018,21 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
return $this; return $this;
} }
/**
* 设置只读字段
* @access public
* @param mixed $field 只读字段
* @return $this
*/
public function readonly($field)
{
if (is_string($field)) {
$field = explode(',', $field);
}
$this->readonly = $field;
return $this;
}
/** /**
* 是否为更新数据 * 是否为更新数据
* @access public * @access public
@ -1219,7 +1234,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
if (isset(self::$event[$this->class][$event])) { if (isset(self::$event[$this->class][$event])) {
foreach (self::$event[$this->class][$event] as $callback) { foreach (self::$event[$this->class][$event] as $callback) {
if (is_callable($callback)) { if (is_callable($callback)) {
$result = call_user_func_array($callback, [& $params]); $result = call_user_func_array($callback, [ & $params]);
if (false === $result) { if (false === $result) {
return false; return false;
} }
@ -1275,6 +1290,10 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
*/ */
public static function get($data = null, $with = [], $cache = false) public static function get($data = null, $with = [], $cache = false)
{ {
if (true === $with || is_int($with)) {
$cache = $with;
$with = [];
}
$query = static::parseQuery($data, $with, $cache); $query = static::parseQuery($data, $with, $cache);
return $query->find($data); return $query->find($data);
} }
@ -1290,6 +1309,10 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
*/ */
public static function all($data = null, $with = [], $cache = false) public static function all($data = null, $with = [], $cache = false)
{ {
if (true === $with || is_int($with)) {
$cache = $with;
$with = [];
}
$query = static::parseQuery($data, $with, $cache); $query = static::parseQuery($data, $with, $cache);
return $query->select($data); return $query->select($data);
} }
@ -1309,7 +1332,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
$result = $result->where($data); $result = $result->where($data);
$data = null; $data = null;
} elseif ($data instanceof \Closure) { } elseif ($data instanceof \Closure) {
call_user_func_array($data, [& $result]); call_user_func_array($data, [ & $result]);
$data = null; $data = null;
} elseif ($data instanceof Query) { } elseif ($data instanceof Query) {
$result = $data->with($with)->cache($cache); $result = $data->with($with)->cache($cache);
@ -1332,7 +1355,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
$query->where($data); $query->where($data);
$data = null; $data = null;
} elseif ($data instanceof \Closure) { } elseif ($data instanceof \Closure) {
call_user_func_array($data, [& $query]); call_user_func_array($data, [ & $query]);
$data = null; $data = null;
} elseif (is_null($data)) { } elseif (is_null($data)) {
return 0; return 0;
@ -1399,15 +1422,20 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
* @param mixed $operator 比较操作符 * @param mixed $operator 比较操作符
* @param integer $count 个数 * @param integer $count 个数
* @param string $id 关联表的统计字段 * @param string $id 关联表的统计字段
* @return Model * @return Relation|Query
*/ */
public static function has($relation, $operator = '>=', $count = 1, $id = '*') public static function has($relation, $operator = '>=', $count = 1, $id = '*')
{ {
$model = new static(); $model = new static();
$relation = $model->$relation();
if ($relation instanceof HasMany) {
if (is_array($operator) || $operator instanceof \Closure) { if (is_array($operator) || $operator instanceof \Closure) {
return $model->$relation()->hasWhere($operator); return $relation->hasWhere($operator);
}
return $relation->has($operator, $count, $id);
} else {
return $relation;
} }
return $model->$relation()->has($operator, $count, $id);
} }
/** /**
@ -1415,12 +1443,17 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
* @access public * @access public
* @param string $relation 关联方法名 * @param string $relation 关联方法名
* @param mixed $where 查询条件(数组或者闭包) * @param mixed $where 查询条件(数组或者闭包)
* @return Model * @return Relation|Query
*/ */
public static function hasWhere($relation, $where = []) public static function hasWhere($relation, $where = [])
{ {
$model = new static(); $model = new static();
return $model->$relation()->hasWhere($where); $relation = $model->$relation();
if ($relation instanceof HasMany) {
return $relation->hasWhere($where);
} else {
return $relation;
}
} }
/** /**

View File

@ -1502,9 +1502,10 @@ class Request
* @access public * @access public
* @param string $key 缓存标识,支持变量规则 ,例如 item/:name/:id * @param string $key 缓存标识,支持变量规则 ,例如 item/:name/:id
* @param mixed $expire 缓存有效期 * @param mixed $expire 缓存有效期
* @param array $except 缓存排除
* @return void * @return void
*/ */
public function cache($key, $expire = null) public function cache($key, $expire = null, $except = [])
{ {
if (false !== $key && $this->isGet() && !$this->isCheckCache) { if (false !== $key && $this->isGet() && !$this->isCheckCache) {
// 标记请求缓存检查 // 标记请求缓存检查
@ -1516,6 +1517,11 @@ class Request
if ($key instanceof \Closure) { if ($key instanceof \Closure) {
$key = call_user_func_array($key, [$this]); $key = call_user_func_array($key, [$this]);
} elseif (true === $key) { } elseif (true === $key) {
foreach ($except as $rule) {
if (0 === strpos($this->url(), $rule)) {
return;
}
}
// 自动缓存功能 // 自动缓存功能
$key = '__URL__'; $key = '__URL__';
} elseif (strpos($key, '|')) { } elseif (strpos($key, '|')) {

View File

@ -153,7 +153,8 @@ class Url
// 检测域名 // 检测域名
$domain = self::parseDomain($url, $domain); $domain = self::parseDomain($url, $domain);
// URL组装 // URL组装
$url = $domain . (self::$root ?: Request::instance()->root()) . '/' . ltrim($url, '/'); $url = $domain . rtrim(self::$root ?: Request::instance()->root(), '/') . '/' . ltrim($url, '/');
self::$bindCheck = false; self::$bindCheck = false;
return $url; return $url;
} }

View File

@ -568,7 +568,7 @@ class Validate
break; break;
case 'ip': case 'ip':
// 是否为IP地址 // 是否为IP地址
$result = $this->filter($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6); $result = $this->filter($value, [FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6]);
break; break;
case 'url': case 'url':
// 是否为一个URL地址 // 是否为一个URL地址
@ -656,7 +656,7 @@ class Validate
if (!in_array($rule, ['ipv4', 'ipv6'])) { if (!in_array($rule, ['ipv4', 'ipv6'])) {
$rule = 'ipv4'; $rule = 'ipv4';
} }
return $this->filter($value, FILTER_VALIDATE_IP, 'ipv6' == $rule ? FILTER_FLAG_IPV6 : FILTER_FLAG_IPV4); return $this->filter($value, [FILTER_VALIDATE_IP, 'ipv6' == $rule ? FILTER_FLAG_IPV6 : FILTER_FLAG_IPV4]);
} }
/** /**
@ -872,6 +872,7 @@ class Validate
list($rule, $param) = explode(',', $rule); list($rule, $param) = explode(',', $rule);
} elseif (is_array($rule)) { } elseif (is_array($rule)) {
$param = isset($rule[1]) ? $rule[1] : null; $param = isset($rule[1]) ? $rule[1] : null;
$rule = $rule[0];
} else { } else {
$param = null; $param = null;
} }

View File

@ -250,7 +250,10 @@ abstract class Builder
// 使用闭包查询 // 使用闭包查询
$query = new Query($this->connection); $query = new Query($this->connection);
call_user_func_array($value, [ & $query]); call_user_func_array($value, [ & $query]);
$str[] = ' ' . $key . ' ( ' . $this->buildWhere($query->getOptions('where'), $options) . ' )'; $whereClause = $this->buildWhere($query->getOptions('where'), $options);
if (!empty($whereClause)) {
$str[] = ' ' . $key . ' ( ' . $whereClause . ' )';
}
} elseif (strpos($field, '|')) { } elseif (strpos($field, '|')) {
// 不同字段使用相同查询条件OR // 不同字段使用相同查询条件OR
$array = explode('|', $field); $array = explode('|', $field);

View File

@ -50,8 +50,6 @@ abstract class Connection
protected $linkRead; protected $linkRead;
protected $linkWrite; protected $linkWrite;
// 查询结果类型
protected $resultSetType = 'array';
// 查询结果类型 // 查询结果类型
protected $fetchType = PDO::FETCH_ASSOC; protected $fetchType = PDO::FETCH_ASSOC;
// 字段属性大小写 // 字段属性大小写
@ -60,6 +58,8 @@ abstract class Connection
protected static $event = []; protected static $event = [];
// 查询对象 // 查询对象
protected $query = []; protected $query = [];
// 使用Builder类
protected $builder;
// 数据库连接参数配置 // 数据库连接参数配置
protected $config = [ protected $config = [
// 数据库类型 // 数据库类型
@ -108,6 +108,8 @@ abstract class Connection
'builder' => '', 'builder' => '',
// Query类 // Query类
'query' => '\\think\\db\\Query', 'query' => '\\think\\db\\Query',
// 是否需要断线重连
'break_reconnect' => false,
]; ];
// PDO连接参数 // PDO连接参数
@ -150,6 +152,20 @@ abstract class Connection
return $this->query[$model]; return $this->query[$model];
} }
/**
* 获取当前连接器类对应的Builder类
* @access public
* @return string
*/
public function getBuilder()
{
if (!empty($this->builder)) {
return $this->builder;
} else {
return $this->getConfig('builder') ?: '\\think\\db\\builder\\' . ucfirst($this->getConfig('type'));
}
}
/** /**
* 调用Query类的查询方法 * 调用Query类的查询方法
* @access public * @access public
@ -269,10 +285,7 @@ abstract class Connection
} }
// 记录当前字段属性大小写设置 // 记录当前字段属性大小写设置
$this->attrCase = $params[PDO::ATTR_CASE]; $this->attrCase = $params[PDO::ATTR_CASE];
// 记录数据集返回类型
if (isset($config['resultset_type'])) {
$this->resultSetType = $config['resultset_type'];
}
// 数据返回类型 // 数据返回类型
if (isset($config['result_type'])) { if (isset($config['result_type'])) {
$this->fetchType = $config['result_type']; $this->fetchType = $config['result_type'];
@ -380,6 +393,9 @@ abstract class Connection
// 返回结果集 // 返回结果集
return $this->getResult($pdo, $procedure); return $this->getResult($pdo, $procedure);
} catch (\PDOException $e) { } catch (\PDOException $e) {
if ($this->config['break_reconnect'] && $this->isBreak($e)) {
return $this->close()->query($sql, $bind, $master, $pdo);
}
throw new PDOException($e, $this->config, $this->getLastsql()); throw new PDOException($e, $this->config, $this->getLastsql());
} }
} }
@ -435,6 +451,9 @@ abstract class Connection
$this->numRows = $this->PDOStatement->rowCount(); $this->numRows = $this->PDOStatement->rowCount();
return $this->numRows; return $this->numRows;
} catch (\PDOException $e) { } catch (\PDOException $e) {
if ($this->config['break_reconnect'] && $this->isBreak($e)) {
return $this->close()->execute($sql, $bind);
}
throw new PDOException($e, $this->config, $this->getLastsql()); throw new PDOException($e, $this->config, $this->getLastsql());
} }
} }
@ -510,11 +529,13 @@ abstract class Connection
protected function bindParam($bind) protected function bindParam($bind)
{ {
foreach ($bind as $key => $val) { foreach ($bind as $key => $val) {
if (is_numeric($key)) { $param = is_numeric($key) ? $key + 1 : ':' . $key;
$key = $key + 1; if (is_array($val)) {
} array_unshift($val, $param);
array_unshift($val, $key);
$result = call_user_func_array([$this->PDOStatement, 'bindParam'], $val); $result = call_user_func_array([$this->PDOStatement, 'bindParam'], $val);
} else {
$result = $this->PDOStatement->bindValue($param, $val);
}
if (!$result) { if (!$result) {
$param = array_shift($val); $param = array_shift($val);
throw new BindParamException( throw new BindParamException(
@ -734,12 +755,28 @@ abstract class Connection
} }
/** /**
* 关闭数据库 * 关闭数据库(或者重新连接)
* @access public * @access public
* @return $this
*/ */
public function close() public function close()
{ {
$this->linkID = null; $this->linkID = null;
$this->linkWrite = null;
$this->linkRead = null;
$this->links = [];
return $this;
}
/**
* 是否断线
* @access protected
* @param \PDOException $e 异常
* @return bool
*/
protected function isBreak($e)
{
return false;
} }
/** /**

View File

@ -124,8 +124,7 @@ class Query
*/ */
protected function setBuilder() protected function setBuilder()
{ {
$builder = $this->connection->getConfig('builder') ?: $this->connection->getConfig('type'); $class = $this->connection->getBuilder();
$class = false !== strpos($builder, '\\') ? $builder : '\\think\\db\\builder\\' . ucfirst($builder);
$this->builder = new $class($this->connection, $this); $this->builder = new $class($this->connection, $this);
} }
@ -420,11 +419,7 @@ class Query
} }
if (isset($cache)) { if (isset($cache)) {
// 缓存数据 // 缓存数据
if (isset($cache['tag'])) { $this->cacheData($key, $result, $cache);
Cache::tag($cache['tag'])->set($key, $result, $cache['expire']);
} else {
Cache::set($key, $result, $cache['expire']);
}
} }
} else { } else {
// 清空查询条件 // 清空查询条件
@ -492,11 +487,7 @@ class Query
} }
if (isset($cache) && isset($guid)) { if (isset($cache) && isset($guid)) {
// 缓存数据 // 缓存数据
if (isset($cache['tag'])) { $this->cacheData($guid, $result, $cache);
Cache::tag($cache['tag'])->set($guid, $result, $cache['expire']);
} else {
Cache::set($guid, $result, $cache['expire']);
}
} }
} else { } else {
// 清空查询条件 // 清空查询条件
@ -2071,11 +2062,18 @@ class Query
// 执行操作 // 执行操作
$result = $this->execute($sql, $bind); $result = $this->execute($sql, $bind);
if ($result) { if ($result) {
$this->trigger('after_insert', $options);
}
if ($getLastInsID) {
$sequence = $sequence ?: (isset($options['sequence']) ? $options['sequence'] : null); $sequence = $sequence ?: (isset($options['sequence']) ? $options['sequence'] : null);
return $this->getLastInsID($sequence); $lastInsId = $this->getLastInsID($sequence);
if ($lastInsId) {
$pk = $this->getPk($options);
$data[$pk] = $lastInsId;
}
$options['data'] = $data;
$this->trigger('after_insert', $options);
if ($getLastInsID) {
return $lastInsId;
}
} }
return $result; return $result;
} }
@ -2158,8 +2156,8 @@ class Query
$options = $this->parseExpress(); $options = $this->parseExpress();
$data = array_merge($options['data'], $data); $data = array_merge($options['data'], $data);
$pk = $this->getPk($options); $pk = $this->getPk($options);
if (isset($options['cache']) && is_string($options['cache'])) { if (isset($options['cache']) && is_string($options['cache']['key'])) {
$key = $options['cache']; $key = $options['cache']['key'];
} }
if (empty($options['where'])) { if (empty($options['where'])) {
@ -2188,9 +2186,10 @@ class Query
} else { } else {
$options['where']['AND'] = $where; $options['where']['AND'] = $where;
} }
} elseif (is_string($pk) && isset($options['where']['AND'][$pk]) && is_scalar($options['where']['AND'][$pk])) { } elseif (!isset($key) && is_string($pk) && isset($options['where']['AND'][$pk])) {
$key = 'think:' . $options['table'] . '|' . $options['where']['AND'][$pk]; $key = $this->getCacheKey($options['where']['AND'][$pk], $options);
} }
// 生成UPDATE SQL语句 // 生成UPDATE SQL语句
$sql = $this->builder->update($data, $options); $sql = $this->builder->update($data, $options);
// 获取参数绑定 // 获取参数绑定
@ -2207,6 +2206,13 @@ class Query
// 执行操作 // 执行操作
$result = '' == $sql ? 0 : $this->execute($sql, $bind); $result = '' == $sql ? 0 : $this->execute($sql, $bind);
if ($result) { if ($result) {
if (isset($where[$pk])) {
$data[$pk] = $where[$pk];
} elseif (is_string($pk) && isset($key) && strpos($key, '|')) {
list($a, $val) = explode('|', $key);
$data[$pk] = $val;
}
$options['data'] = $data;
$this->trigger('after_update', $options); $this->trigger('after_update', $options);
} }
return $result; return $result;
@ -2279,6 +2285,8 @@ class Query
// 获取实际执行的SQL语句 // 获取实际执行的SQL语句
return $this->connection->getRealSql($sql, $bind); return $this->connection->getRealSql($sql, $bind);
} }
$options['data'] = $data;
if ($resultSet = $this->trigger('before_select', $options)) { if ($resultSet = $this->trigger('before_select', $options)) {
} else { } else {
// 执行查询操作 // 执行查询操作
@ -2292,11 +2300,7 @@ class Query
if (isset($cache)) { if (isset($cache)) {
// 缓存数据集 // 缓存数据集
if (isset($cache['tag'])) { $this->cacheData($key, $resultSet, $cache);
Cache::tag($cache['tag'])->set($key, $resultSet, $cache['expire']);
} else {
Cache::set($key, $resultSet, $cache['expire']);
}
} }
} }
@ -2340,6 +2344,40 @@ class Query
return $resultSet; return $resultSet;
} }
/**
* 缓存数据
* @access public
* @param string $key 缓存标识
* @param mixed $data 缓存数据
* @param array $config 缓存参数
*/
protected function cacheData($key, $data, $config = [])
{
if (isset($config['tag'])) {
Cache::tag($config['tag'])->set($key, $data, $config['expire']);
} else {
Cache::set($key, $data, $config['expire']);
}
}
/**
* 生成缓存标识
* @access public
* @param mixed $value 缓存数据
* @param array $options 缓存参数
*/
protected function getCacheKey($value, $options)
{
if (is_scalar($value)) {
$data = $value;
} elseif (is_array($value) && 'eq' == strtolower($value[0])) {
$data = $value[1];
}
if (isset($data)) {
return 'think:' . $options['table'] . '|' . $data;
}
}
/** /**
* 查找单条记录 * 查找单条记录
* @access public * @access public
@ -2359,10 +2397,12 @@ class Query
} }
// 分析查询表达式 // 分析查询表达式
$options = $this->parseExpress(); $options = $this->parseExpress();
$pk = $this->getPk($options);
if (!is_null($data)) { if (!is_null($data)) {
// AR模式分析主键条件 // AR模式分析主键条件
$this->parsePkWhere($data, $options); $this->parsePkWhere($data, $options);
} elseif (!empty($options['cache']) && true === $options['cache']['key'] && is_string($pk) && isset($options['where']['AND'][$pk])) {
$key = $this->getCacheKey($options['where']['AND'][$pk], $options);
} }
$options['limit'] = 1; $options['limit'] = 1;
@ -2372,12 +2412,12 @@ class Query
$cache = $options['cache']; $cache = $options['cache'];
if (true === $cache['key'] && !is_null($data) && !is_array($data)) { if (true === $cache['key'] && !is_null($data) && !is_array($data)) {
$key = 'think:' . (is_array($options['table']) ? key($options['table']) : $options['table']) . '|' . $data; $key = 'think:' . (is_array($options['table']) ? key($options['table']) : $options['table']) . '|' . $data;
} else { } elseif (!isset($key)) {
$key = is_string($cache['key']) ? $cache['key'] : md5(serialize($options)); $key = is_string($cache['key']) ? $cache['key'] : md5(serialize($options));
} }
$result = Cache::get($key); $result = Cache::get($key);
} }
if (!$result) { if (false === $result) {
// 生成查询SQL // 生成查询SQL
$sql = $this->builder->select($options); $sql = $this->builder->select($options);
// 获取参数绑定 // 获取参数绑定
@ -2386,56 +2426,61 @@ class Query
// 获取实际执行的SQL语句 // 获取实际执行的SQL语句
return $this->connection->getRealSql($sql, $bind); return $this->connection->getRealSql($sql, $bind);
} }
if (is_string($pk)) {
if (!is_array($data)) {
if (isset($key) && strpos($key, '|')) {
list($a, $val) = explode('|', $key);
$item[$pk] = $val;
} else {
$item[$pk] = $data;
}
$data = $item;
}
}
$options['data'] = $data;
// 事件回调 // 事件回调
if ($result = $this->trigger('before_find', $options)) { if ($result = $this->trigger('before_find', $options)) {
} else { } else {
// 执行查询 // 执行查询
$result = $this->query($sql, $bind, $options['master'], $options['fetch_pdo']); $resultSet = $this->query($sql, $bind, $options['master'], $options['fetch_pdo']);
if ($result instanceof \PDOStatement) { if ($resultSet instanceof \PDOStatement) {
// 返回PDOStatement对象 // 返回PDOStatement对象
return $result; return $resultSet;
} }
$result = isset($resultSet[0]) ? $resultSet[0] : null;
} }
if (isset($cache)) { if (isset($cache)) {
// 缓存数据 // 缓存数据
if (isset($cache['tag'])) { $this->cacheData($key, $result, $cache);
Cache::tag($cache['tag'])->set($key, $result, $cache['expire']);
} else {
Cache::set($key, $result, $cache['expire']);
}
} }
} }
// 数据处理 // 数据处理
if (!empty($result[0])) { if (!empty($result)) {
$data = $result[0];
if (!empty($this->model)) { if (!empty($this->model)) {
// 返回模型对象 // 返回模型对象
$model = $this->model; $model = $this->model;
$data = new $model($data); $result = new $model($result);
$data->isUpdate(true, isset($options['where']['AND']) ? $options['where']['AND'] : null); $result->isUpdate(true, isset($options['where']['AND']) ? $options['where']['AND'] : null);
// 关联查询 // 关联查询
if (!empty($options['relation'])) { if (!empty($options['relation'])) {
$data->relationQuery($options['relation']); $result->relationQuery($options['relation']);
} }
// 预载入查询 // 预载入查询
if (!empty($options['with'])) { if (!empty($options['with'])) {
$data->eagerlyResult($data, $options['with']); $result->eagerlyResult($result, $options['with']);
} }
// 关联统计 // 关联统计
if (!empty($options['with_count'])) { if (!empty($options['with_count'])) {
$data->relationCount($data, $options['with_count']); $result->relationCount($result, $options['with_count']);
} }
} }
} elseif (!empty($options['fail'])) { } elseif (!empty($options['fail'])) {
$this->throwNotFound($options); $this->throwNotFound($options);
} else {
$data = null;
} }
return $data; return $result;
} }
/** /**
@ -2566,8 +2611,9 @@ class Query
{ {
// 分析查询表达式 // 分析查询表达式
$options = $this->parseExpress(); $options = $this->parseExpress();
if (isset($options['cache']) && is_string($options['cache'])) { $pk = $this->getPk($options);
$key = $options['cache']; if (isset($options['cache']) && is_string($options['cache']['key'])) {
$key = $options['cache']['key'];
} }
if (!is_null($data) && true !== $data) { if (!is_null($data) && true !== $data) {
@ -2577,6 +2623,8 @@ class Query
} }
// AR模式分析主键条件 // AR模式分析主键条件
$this->parsePkWhere($data, $options); $this->parsePkWhere($data, $options);
} elseif (!isset($key) && is_string($pk) && isset($options['where']['AND'][$pk])) {
$key = $this->getCacheKey($options['where']['AND'][$pk], $options);
} }
if (true !== $data && empty($options['where'])) { if (true !== $data && empty($options['where'])) {
@ -2600,6 +2648,12 @@ class Query
// 执行操作 // 执行操作
$result = $this->execute($sql, $bind); $result = $this->execute($sql, $bind);
if ($result) { if ($result) {
if (!is_array($data) && is_string($pk) && isset($key) && strpos($key, '|')) {
list($a, $val) = explode('|', $key);
$item[$pk] = $val;
$data = $item;
}
$options['data'] = $data;
$this->trigger('after_delete', $options); $this->trigger('after_delete', $options);
} }
return $result; return $result;
@ -2712,15 +2766,15 @@ class Query
* 触发事件 * 触发事件
* @access protected * @access protected
* @param string $event 事件名 * @param string $event 事件名
* @param mixed $options 当前查询参数 * @param mixed $params 额外参数
* @return bool * @return bool
*/ */
protected function trigger($event, $options = []) protected function trigger($event, $params = [])
{ {
$result = false; $result = false;
if (isset(self::$event[$event])) { if (isset(self::$event[$event])) {
$callback = self::$event[$event]; $callback = self::$event[$event];
$result = call_user_func_array($callback, [$options, $this]); $result = call_user_func_array($callback, [$params, $this]);
} }
return $result; return $result;
} }

View File

@ -21,6 +21,8 @@ use think\Log;
class Mysql extends Connection class Mysql extends Connection
{ {
protected $builder = '\\think\\db\\builder\\Mysql';
/** /**
* 解析pdo连接的dsn信息 * 解析pdo连接的dsn信息
* @access protected * @access protected
@ -127,4 +129,18 @@ class Mysql extends Connection
{ {
return true; return true;
} }
/**
* 是否断线
* @access protected
* @param \PDOException $e 异常对象
* @return bool
*/
protected function isBreak($e)
{
if (false !== stripos($e->getMessage(), 'server has gone away')) {
return true;
}
return false;
}
} }

View File

@ -19,6 +19,7 @@ use think\db\Connection;
*/ */
class Pgsql extends Connection class Pgsql extends Connection
{ {
protected $builder = '\\think\\db\\builder\\Pgsql';
/** /**
* 解析pdo连接的dsn信息 * 解析pdo连接的dsn信息

View File

@ -20,6 +20,8 @@ use think\db\Connection;
class Sqlite extends Connection class Sqlite extends Connection
{ {
protected $builder = '\\think\\db\\builder\\Sqlite';
/** /**
* 解析pdo连接的dsn信息 * 解析pdo连接的dsn信息
* @access protected * @access protected

View File

@ -25,7 +25,7 @@ class Sqlsrv extends Connection
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_STRINGIFY_FETCHES => false, PDO::ATTR_STRINGIFY_FETCHES => false,
]; ];
protected $builder = '\\think\\db\\builder\\Sqlsrv';
/** /**
* 解析pdo连接的dsn信息 * 解析pdo连接的dsn信息
* @access protected * @access protected

View File

@ -54,7 +54,7 @@ class BelongsToMany extends Relation
$localKey = $this->localKey; $localKey = $this->localKey;
$middle = $this->middle; $middle = $this->middle;
if ($closure) { if ($closure) {
call_user_func_array($closure, [& $this->query]); call_user_func_array($closure, [ & $this->query]);
} }
// 关联查询 // 关联查询
$pk = $this->parent->getPk(); $pk = $this->parent->getPk();
@ -174,8 +174,8 @@ class BelongsToMany extends Relation
return $this->belongsToManyQuery($this->middle, $this->foreignKey, $this->localKey, [ return $this->belongsToManyQuery($this->middle, $this->foreignKey, $this->localKey, [
'pivot.' . $this->localKey => [ 'pivot.' . $this->localKey => [
'exp', 'exp',
'=' . $this->parent->getTable() . '.' . $this->parent->getPk() '=' . $this->parent->getTable() . '.' . $this->parent->getPk(),
] ],
])->fetchSql()->count(); ])->fetchSql()->count();
} }
@ -271,7 +271,7 @@ class BelongsToMany extends Relation
* @access public * @access public
* @param mixed $data 数据 可以使用数组、关联模型对象 或者 关联对象的主键 * @param mixed $data 数据 可以使用数组、关联模型对象 或者 关联对象的主键
* @param array $pivot 中间表额外数据 * @param array $pivot 中间表额外数据
* @return int * @return array|Pivot
* @throws Exception * @throws Exception
*/ */
public function attach($data, $pivot = []) public function attach($data, $pivot = [])
@ -301,7 +301,12 @@ class BelongsToMany extends Relation
$ids = (array) $id; $ids = (array) $id;
foreach ($ids as $id) { foreach ($ids as $id) {
$pivot[$this->foreignKey] = $id; $pivot[$this->foreignKey] = $id;
$result = $this->query->table($this->middle)->insert($pivot, true); $this->query->table($this->middle)->insert($pivot, true);
$result[] = new Pivot($pivot, $this->middle);
}
if (count($result) == 1) {
// 返回中间表模型对象
$result = $result[0];
} }
return $result; return $result;
} else { } else {

View File

@ -45,7 +45,7 @@ class HasMany extends Relation
public function getRelation($subRelation = '', $closure = null) public function getRelation($subRelation = '', $closure = null)
{ {
if ($closure) { if ($closure) {
call_user_func_array($closure, [& $this->query]); call_user_func_array($closure, [ & $this->query]);
} }
return $this->relation($subRelation)->select(); return $this->relation($subRelation)->select();
} }
@ -125,7 +125,7 @@ class HasMany extends Relation
$count = 0; $count = 0;
if (isset($result->$localKey)) { if (isset($result->$localKey)) {
if ($closure) { if ($closure) {
call_user_func_array($closure, [& $this->query]); call_user_func_array($closure, [ & $this->query]);
} }
$count = $this->query->where([$this->foreignKey => $result->$localKey])->count(); $count = $this->query->where([$this->foreignKey => $result->$localKey])->count();
} }
@ -141,14 +141,14 @@ class HasMany extends Relation
public function getRelationCountQuery($closure) public function getRelationCountQuery($closure)
{ {
if ($closure) { if ($closure) {
call_user_func_array($closure, [& $this->query]); call_user_func_array($closure, [ & $this->query]);
} }
return $this->query->where([ return $this->query->where([
$this->foreignKey => [ $this->foreignKey => [
'exp', 'exp',
'=' . $this->parent->getTable() . '.' . $this->parent->getPk() '=' . $this->parent->getTable() . '.' . $this->parent->getPk(),
] ],
])->fetchSql()->count(); ])->fetchSql()->count();
} }
@ -167,7 +167,7 @@ class HasMany extends Relation
$foreignKey = $this->foreignKey; $foreignKey = $this->foreignKey;
// 预载入关联查询 支持嵌套预载入 // 预载入关联查询 支持嵌套预载入
if ($closure) { if ($closure) {
call_user_func_array($closure, [& $model]); call_user_func_array($closure, [ & $model]);
} }
$list = $model->where($where)->with($subRelation)->select(); $list = $model->where($where)->with($subRelation)->select();
@ -217,13 +217,14 @@ class HasMany extends Relation
* @param string $operator 比较操作符 * @param string $operator 比较操作符
* @param integer $count 个数 * @param integer $count 个数
* @param string $id 关联表的统计字段 * @param string $id 关联表的统计字段
* @param string $joinType JOIN类型
* @return Query * @return Query
*/ */
public function has($operator = '>=', $count = 1, $id = '*') public function has($operator = '>=', $count = 1, $id = '*', $joinType = 'INNER')
{ {
$table = $this->query->getTable(); $table = $this->query->getTable();
return $this->parent->db()->alias('a') return $this->parent->db()->alias('a')
->join($table . ' b', 'a.' . $this->localKey . '=b.' . $this->foreignKey, $this->joinType) ->join($table . ' b', 'a.' . $this->localKey . '=b.' . $this->foreignKey, $joinType)
->group('b.' . $this->foreignKey) ->group('b.' . $this->foreignKey)
->having('count(' . $id . ')' . $operator . $count); ->having('count(' . $id . ')' . $operator . $count);
} }

View File

@ -131,16 +131,17 @@ trait Jump
* @param string $url 跳转的URL表达式 * @param string $url 跳转的URL表达式
* @param array|integer $params 其它URL参数 * @param array|integer $params 其它URL参数
* @param integer $code http code * @param integer $code http code
* @param array $with 隐式传参
* @return void * @return void
*/ */
protected function redirect($url, $params = [], $code = 302) protected function redirect($url, $params = [], $code = 302, $with = [])
{ {
$response = new Redirect($url); $response = new Redirect($url);
if (is_integer($params)) { if (is_integer($params)) {
$code = $params; $code = $params;
$params = []; $params = [];
} }
$response->code($code)->params($params); $response->code($code)->params($params)->with($with);
throw new HttpResponseException($response); throw new HttpResponseException($response);
} }

View File

@ -42,7 +42,7 @@ trait SoftDelete
{ {
$model = new static(); $model = new static();
$field = $model->getDeleteTimeField(true); $field = $model->getDeleteTimeField(true);
return $model->db(false)->where($field, 'exp', 'is not null'); return $model->db(false)->whereNotNull($field);
} }
/** /**
@ -129,7 +129,7 @@ trait SoftDelete
protected function base($query) protected function base($query)
{ {
$field = $this->getDeleteTimeField(true); $field = $this->getDeleteTimeField(true);
$query->where($field, 'null'); $query->whereNull($field);
} }
/** /**

2
vendor/autoload.php vendored
View File

@ -4,4 +4,4 @@
require_once __DIR__ . '/composer/autoload_real.php'; require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit9e22b278b1b4ad2907e604cae5a45125::getLoader(); return ComposerAutoloaderInit5a34d2cf88418439a1e7fb45047b8e5a::getLoader();

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer // autoload_real.php @generated by Composer
class ComposerAutoloaderInit9e22b278b1b4ad2907e604cae5a45125 class ComposerAutoloaderInit5a34d2cf88418439a1e7fb45047b8e5a
{ {
private static $loader; private static $loader;
@ -19,15 +19,15 @@ class ComposerAutoloaderInit9e22b278b1b4ad2907e604cae5a45125
return self::$loader; return self::$loader;
} }
spl_autoload_register(array('ComposerAutoloaderInit9e22b278b1b4ad2907e604cae5a45125', 'loadClassLoader'), true, true); spl_autoload_register(array('ComposerAutoloaderInit5a34d2cf88418439a1e7fb45047b8e5a', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(); self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit9e22b278b1b4ad2907e604cae5a45125', 'loadClassLoader')); spl_autoload_unregister(array('ComposerAutoloaderInit5a34d2cf88418439a1e7fb45047b8e5a', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION'); $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION');
if ($useStaticLoader) { if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php'; require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit9e22b278b1b4ad2907e604cae5a45125::getInitializer($loader)); call_user_func(\Composer\Autoload\ComposerStaticInit5a34d2cf88418439a1e7fb45047b8e5a::getInitializer($loader));
} else { } else {
$map = require __DIR__ . '/autoload_namespaces.php'; $map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) { foreach ($map as $namespace => $path) {
@ -48,19 +48,19 @@ class ComposerAutoloaderInit9e22b278b1b4ad2907e604cae5a45125
$loader->register(true); $loader->register(true);
if ($useStaticLoader) { if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInit9e22b278b1b4ad2907e604cae5a45125::$files; $includeFiles = Composer\Autoload\ComposerStaticInit5a34d2cf88418439a1e7fb45047b8e5a::$files;
} else { } else {
$includeFiles = require __DIR__ . '/autoload_files.php'; $includeFiles = require __DIR__ . '/autoload_files.php';
} }
foreach ($includeFiles as $fileIdentifier => $file) { foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire9e22b278b1b4ad2907e604cae5a45125($fileIdentifier, $file); composerRequire5a34d2cf88418439a1e7fb45047b8e5a($fileIdentifier, $file);
} }
return $loader; return $loader;
} }
} }
function composerRequire9e22b278b1b4ad2907e604cae5a45125($fileIdentifier, $file) function composerRequire5a34d2cf88418439a1e7fb45047b8e5a($fileIdentifier, $file)
{ {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file; require $file;

View File

@ -4,7 +4,7 @@
namespace Composer\Autoload; namespace Composer\Autoload;
class ComposerStaticInit9e22b278b1b4ad2907e604cae5a45125 class ComposerStaticInit5a34d2cf88418439a1e7fb45047b8e5a
{ {
public static $files = array ( public static $files = array (
'9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php', '9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php',
@ -337,10 +337,10 @@ class ComposerStaticInit9e22b278b1b4ad2907e604cae5a45125
public static function getInitializer(ClassLoader $loader) public static function getInitializer(ClassLoader $loader)
{ {
return \Closure::bind(function () use ($loader) { return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit9e22b278b1b4ad2907e604cae5a45125::$prefixLengthsPsr4; $loader->prefixLengthsPsr4 = ComposerStaticInit5a34d2cf88418439a1e7fb45047b8e5a::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit9e22b278b1b4ad2907e604cae5a45125::$prefixDirsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInit5a34d2cf88418439a1e7fb45047b8e5a::$prefixDirsPsr4;
$loader->prefixesPsr0 = ComposerStaticInit9e22b278b1b4ad2907e604cae5a45125::$prefixesPsr0; $loader->prefixesPsr0 = ComposerStaticInit5a34d2cf88418439a1e7fb45047b8e5a::$prefixesPsr0;
$loader->classMap = ComposerStaticInit9e22b278b1b4ad2907e604cae5a45125::$classMap; $loader->classMap = ComposerStaticInit5a34d2cf88418439a1e7fb45047b8e5a::$classMap;
}, null, ClassLoader::class); }, null, ClassLoader::class);
} }

View File

@ -218,17 +218,17 @@
}, },
{ {
"name": "topthink/framework", "name": "topthink/framework",
"version": "v5.0.5", "version": "v5.0.6",
"version_normalized": "5.0.5.0", "version_normalized": "5.0.6.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/top-think/framework.git", "url": "https://github.com/top-think/framework.git",
"reference": "86cc9378a0c46e66dabed6681f8b8de758585ae1" "reference": "a3a37e6cfad132d5b02ffff8f23a4abc565f7928"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://packagist.phpcomposer.com/files/top-think/framework/86cc9378a0c46e66dabed6681f8b8de758585ae1.zip", "url": "https://packagist.phpcomposer.com/files/top-think/framework/a3a37e6cfad132d5b02ffff8f23a4abc565f7928.zip",
"reference": "86cc9378a0c46e66dabed6681f8b8de758585ae1", "reference": "a3a37e6cfad132d5b02ffff8f23a4abc565f7928",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -243,7 +243,7 @@
"phpunit/phpunit": "4.8.*", "phpunit/phpunit": "4.8.*",
"sebastian/phpcpd": "2.*" "sebastian/phpcpd": "2.*"
}, },
"time": "2017-01-23 05:59:21", "time": "2017-02-07 09:39:59",
"type": "think-framework", "type": "think-framework",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
@ -345,17 +345,17 @@
}, },
{ {
"name": "workerman/workerman", "name": "workerman/workerman",
"version": "v3.3.7", "version": "v3.3.8",
"version_normalized": "3.3.7.0", "version_normalized": "3.3.8.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/walkor/Workerman.git", "url": "https://github.com/walkor/Workerman.git",
"reference": "d466c0f4b37c6cfb4f27c69b158175c7e7ccc24c" "reference": "bbcfd9169cf6acd9d9866e17ed2f2189ee6d7f91"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://packagist.phpcomposer.com/files/walkor/Workerman/d466c0f4b37c6cfb4f27c69b158175c7e7ccc24c.zip", "url": "https://packagist.phpcomposer.com/files/walkor/Workerman/bbcfd9169cf6acd9d9866e17ed2f2189ee6d7f91.zip",
"reference": "d466c0f4b37c6cfb4f27c69b158175c7e7ccc24c", "reference": "bbcfd9169cf6acd9d9866e17ed2f2189ee6d7f91",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -364,7 +364,7 @@
"suggest": { "suggest": {
"ext-event": "For better performance." "ext-event": "For better performance."
}, },
"time": "2017-02-02 02:52:58", "time": "2017-02-09 08:07:55",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {

View File

@ -25,6 +25,16 @@ class React implements LoopInterface
*/ */
protected $_loop = null; protected $_loop = null;
/**
* @var array
*/
protected $_timerIdMap = array();
/**
* @var int
*/
protected $_timerIdIndex = 0;
/** /**
* React constructor. * React constructor.
*/ */
@ -58,13 +68,17 @@ class React implements LoopInterface
case EventInterface::EV_SIGNAL: case EventInterface::EV_SIGNAL:
return $this->_loop->addSignal($fd, $func); return $this->_loop->addSignal($fd, $func);
case EventInterface::EV_TIMER: case EventInterface::EV_TIMER:
return $this->_loop->addPeriodicTimer($fd, function() use ($func, $args) { $timer_obj = $this->_loop->addPeriodicTimer($fd, function() use ($func, $args) {
call_user_func_array($func, $args); call_user_func_array($func, $args);
}); });
$this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj;
return $this->_timerIdIndex;
case EventInterface::EV_TIMER_ONCE: case EventInterface::EV_TIMER_ONCE:
return $this->_loop->addTimer($fd, function() use ($func, $args) { $timer_obj = $this->_loop->addTimer($fd, function() use ($func, $args) {
call_user_func_array($func, $args); call_user_func_array($func, $args);
}); });
$this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj;
return $this->_timerIdIndex;
} }
return false; return false;
} }
@ -87,8 +101,11 @@ class React implements LoopInterface
return $this->_loop->removeSignal($fd); return $this->_loop->removeSignal($fd);
case EventInterface::EV_TIMER: case EventInterface::EV_TIMER:
case EventInterface::EV_TIMER_ONCE; case EventInterface::EV_TIMER_ONCE;
if ($fd !== null){ if (isset($this->_timerIdMap[$fd])){
return $this->_loop->cancelTimer($fd); $timer_obj = $this->_timerIdMap[$fd];
unset($this->_timerIdMap[$fd]);
$this->_loop->cancelTimer($timer_obj);
return true;
} }
} }
return false; return false;

View File

@ -78,7 +78,7 @@ class Timer
* @param callback $func * @param callback $func
* @param mixed $args * @param mixed $args
* @param bool $persistent * @param bool $persistent
* @return bool * @return int/false
*/ */
public static function add($time_interval, $func, $args = array(), $persistent = true) public static function add($time_interval, $func, $args = array(), $persistent = true)
{ {
@ -107,7 +107,7 @@ class Timer
self::$_tasks[$run_time] = array(); self::$_tasks[$run_time] = array();
} }
self::$_tasks[$run_time][] = array($func, (array)$args, $persistent, $time_interval); self::$_tasks[$run_time][] = array($func, (array)$args, $persistent, $time_interval);
return true; return 1;
} }

View File

@ -33,7 +33,7 @@ class Worker
* *
* @var string * @var string
*/ */
const VERSION = '3.3.7'; const VERSION = '3.3.8';
/** /**
* Status starting. * Status starting.
@ -934,6 +934,8 @@ class Worker
$worker->setUserAndGroup(); $worker->setUserAndGroup();
$worker->id = $id; $worker->id = $id;
$worker->run(); $worker->run();
$err = new Exception('event-loop exited');
self::log($err);
exit(250); exit(250);
} else { } else {
throw new Exception("forkOneWorker fail"); throw new Exception("forkOneWorker fail");