作者 何书鹏

three commit

正在显示 50 个修改的文件 包含 4359 行增加90 行删除

要显示太多修改。

为保证性能只显示 50 of 50+ 个文件。

... ... @@ -271,17 +271,17 @@
<el-tabs v-if="tabsData.length>0" v-model="activeName" @tab-click="handleClick">
<el-tab-pane :name="tab.name" v-for="tab in tabsData">
<span slot="label">{{tab.name}}
<img v-if="tab.id==activeId" class="tab-icons" src="/assets/addons/shopro/img/category/edit.png"
@click.stop="operation('editCategory',tab.id)">
<!-- <img v-if="tab.id==activeId" class="tab-icons" src="/assets/addons/shopro/img/category/edit.png"-->
<!-- @click.stop="operation('editCategory',tab.id)">-->
</span>
</el-tab-pane>
</el-tabs>
<div class="add-category flex-1 display-flex">
<div class="display-flex" @click="operation('addCategory')" style="width: 60px;">
<i class="el-icon-plus"></i>
<span style="line-height: 13px;">添加</span>
</div>
</div>
<!-- <div class="add-category flex-1 display-flex">-->
<!-- <div class="display-flex" @click="operation('addCategory')" style="width: 60px;">-->
<!-- <i class="el-icon-plus"></i>-->
<!-- <span style="line-height: 13px;">添加</span>-->
<!-- </div>-->
<!-- </div>-->
</div>
<div class="custom-tabs-line"></div>
... ...
<?php
namespace addons\shopro\controller;
namespace app\api\controller;
/**
* 拼团开的团
*
*/
class ActivityGroupon extends Base
... ... @@ -14,7 +13,15 @@ class ActivityGroupon extends Base
/**
* 根据商品 id 获取正在拼的团
* @ApiWeigh (99)
* @ApiTitle (根据商品 id 获取正在拼的团)
* @ApiSummary (根据商品 id 获取正在拼的团)
* @ApiMethod (GET)
*
* @ApiParams (name=goods_id, type=inter, required=false, description="商品ID")
* @ApiParams (name=activity_id, type=inter, required=false, description="活动ID")
*
* @ApiReturn()
*/
public function index() {
$params = $this->request->get();
... ... @@ -22,14 +29,33 @@ class ActivityGroupon extends Base
$this->success('团列表', \addons\shopro\model\ActivityGroupon::getActivityGroupon($params));
}
/**
* @ApiWeigh (97)
* @ApiTitle (团详情)
* @ApiSummary (团详情)
* @ApiMethod (GET)
*
* @ApiParams (name=id, type=inter, required=false, description="团ID")
*
* @ApiReturn()
*/
public function detail () {
$id = $this->request->get('id');
$this->success('团详情', \addons\shopro\model\ActivityGroupon::getActivityGrouponDetail($id));
}
/**
* @ApiWeigh (95)
* @ApiTitle (我的拼团)
* @ApiSummary (我的拼团)
* @ApiMethod (GET)
*
* @ApiHeaders (name=token, type=string, required=false, description="请求的Token")
* @ApiParams (name=type, type=string, required=true, description="类型:all=全部,invalid=已过期,ing=进行中,finish=已成团")
*
* @ApiReturn()
*/
public function myGroupon () {
$type = $this->request->get('type', 'all');
$user = $this->auth->getUserInfo();
... ...
... ... @@ -6,6 +6,9 @@ use addons\shopro\exception\Exception;
use addons\shopro\model\UserAddress;
use addons\shopro\model\Area;
/**
* 我的地址接口
*/
class Address extends Base
{
... ... @@ -20,7 +23,27 @@ class Address extends Base
*
* @ApiHeaders (name=token, type=string, required=true, description="请求的Token")
*
* @ApiReturn()
* @ApiReturn({
"code": 1,
"msg": "收货地址",
"time": "1607673708",
"data": [{
"id": 1, //地址ID
"is_default": "1", //是否为默认地址:0=否,1=是
"user_id": 1, //用户ID
"consignee": "何先生", //姓名
"phone": "15133120361", //电话
"province_name": "北京市", //省份名称
"city_name": "北京市", //城市名称
"area_name": "东城区", //区县名称
"address": "测试地址", //详细地址
"province_id": 110000, //省份ID
"city_id": 110100, //城市ID
"area_id": 110101, //区县ID
"latitude": null,
"longitude": null
}]
})
*/
public function index()
{
... ... @@ -35,7 +58,27 @@ class Address extends Base
*
* @ApiHeaders (name=token, type=string, required=true, description="请求的Token")
*
* @ApiReturn()
* @ApiReturn({
"code": 1,
"msg": "默认收货地址",
"time": "1607673249",
"data": {
"id": 1, //地址ID
"is_default": "0", //是否为默认地址:0=否,1=是
"user_id": 1, //用户ID
"consignee": "何先生", //姓名
"phone": "15133120361", //电话
"province_name": "北京市", //省份名称
"city_name": "北京市", //城市名称
"area_name": "东城区", //地区名称
"address": "测试地址", //详细地址
"province_id": 110000, //省份ID
"city_id": 110100, //城市ID
"area_id": 110101, //地区ID
"latitude": null,
"longitude": null
}
})
*/
public function defaults()
{
... ... @@ -48,7 +91,37 @@ class Address extends Base
* @ApiSummary (省市区)
* @ApiMethod (GET)
*
* @ApiReturn()
* @ApiReturn({
"code": 1,
"msg": "省市区",
"time": "1607672048",
"data": {
"provinceData": [{ //省份数据
"value": 110000,
"label": "北京市",
"pid": 0,
"level": 1
}],
"cityData": [ //城市数据
[{
"value": 110100,
"label": "北京市",
"pid": 110000,
"level": 2
}]
],
"areaData": [ //区县数据
[
[{
"value": 110101,
"label": "东城区",
"pid": 110100,
"level": 3
}]
]
]
}
})
*/
public function area()
{
... ... @@ -76,8 +149,29 @@ class Address extends Base
* @ApiParams (name=consignee, type=string, required=true, description="收货人")
* @ApiParams (name=phone, type=string, required=true, description="联系电话")
* @ApiParams (name=address, type=string, required=true, description="详细地址")
* @ApiParams (name=is_default, type=string, required=false, description="是否默认地址:0=否,1=是")
*
* @ApiReturn()
* @ApiReturn({
"code": 1,
"msg": "编辑地址",
"time": "1607673078",
"data": {
"consignee": "何先生", //姓名
"phone": "15133120361", //电话
"province_id": 110000, //省份ID
"province_name": "北京市", //省份名称
"city_id": 110100, //城市ID
"city_name": "北京市", //城市名称
"area_id": 110101, //区县ID
"area_name": "东城区", //区县名称
"is_default": "0", //是否为默认地址:0=否,1=是
"latitude": null,
"longitude": null,
"user_id": 1, //用户ID
"address": "测试地址", //详细地址
"id": "1" //地址ID
}
})
*/
public function edit()
{
... ... @@ -98,7 +192,27 @@ class Address extends Base
* @ApiHeaders (name=token, type=string, required=true, description="请求的Token")
* @ApiParams (name=id, type=inter, required=true, description="收货地址ID")
*
* @ApiReturn()
* @ApiReturn({
"code": 1,
"msg": "地址详情",
"time": "1607673249",
"data": {
"id": 1, //地址ID
"is_default": "0", //是否为默认地址:0=否,1=是
"user_id": 1, //用户ID
"consignee": "何先生", //姓名
"phone": "15133120361", //电话
"province_name": "北京市", //省份名称
"city_name": "北京市", //城市名称
"area_name": "东城区", //地区名称
"address": "测试地址", //详细地址
"province_id": 110000, //省份ID
"city_id": 110100, //城市ID
"area_id": 110101, //地区ID
"latitude": null,
"longitude": null
}
})
*/
public function info()
{
... ... @@ -115,7 +229,12 @@ class Address extends Base
* @ApiHeaders (name=token, type=string, required=true, description="请求的Token")
* @ApiParams (name=id, type=inter, required=true, description="收货地址ID")
*
* @ApiReturn()
* @ApiReturn({
"code": 1,
"msg": "删除地址",
"time": "1607673249",
"data": null
})
*/
public function del()
{
... ...
<?php
namespace addons\shopro\controller;
namespace app\api\controller;
use addons\shopro\model\Category as CategoryModel;
use addons\shopro\model\Goods;
... ... @@ -17,15 +17,57 @@ class Category extends Base
protected $noNeedLogin = ['*'];
protected $noNeedRight = ['*'];
/**
* @ApiWeigh (99)
* @ApiTitle (商城分类)
* @ApiSummary (商城分类)
* @ApiMethod (GET)
*
* @ApiReturn({
"code": 1,
"msg": "商城分类",
"time": "1607653266",
"data": {
"id": 1, //不用管
"name": "商品分类", //不用管
"type": "3", //不用管
"image": null, //不用管
"pid": 0, //不用管
"weigh": 0, //不用管
"description": "", //不用管
"children": [{
"id": 2, //一级分类ID
"name": "一级分类", 一级分类名称
"type": "",
"image": null, //一级分类图片
"pid": 1,
"weigh": 0,
"description": "",
"children": [{
"id": 3, //二级分类ID
"name": "二级分类", //二级分类名称
"type": "",
"image": null, //二级分类图片
"pid": 2,
"weigh": 0,
"description": "",
"children": [] //不用管
}]
}]
}
})
*/
public function index()
{
$id = $this->request->get('id');
$id = $this->request->get('id',1);
$data = CategoryModel::getCategoryList($id);
$this->success('商城分类', $data);
}
/**
* @ApiInternal
*/
public function goods() {
$params = $this->request->get();
$category_id = $params['category_id'];
... ...
... ... @@ -4,6 +4,9 @@ namespace app\api\controller;
use addons\shopro\exception\Exception;
/**
* 商品接口
*/
class Goods extends Base
{
... ... @@ -122,6 +125,7 @@ class Goods extends Base
/**
* @ApiInternal
* 获取商品支持的 自提点
*/
public function store()
... ... @@ -166,7 +170,10 @@ class Goods extends Base
$this->success('拼团商品列表', \addons\shopro\model\Goods::getGrouponGoodsList($params));
}
/**
* @ApiInternal
* 活动列表
*/
public function activity()
{
$activity_id = $this->request->get('activity_id');
... ... @@ -181,6 +188,10 @@ class Goods extends Base
$this->success('活动列表', $activity);
}
/**
* @ApiInternal
* 收藏或取消收藏
*/
public function favorite()
{
$params = $this->request->post();
... ... @@ -188,13 +199,20 @@ class Goods extends Base
$this->success($result ? '收藏成功' : '取消收藏', $result);
}
/**
* @ApiInternal
* 商品收藏列表
*/
public function favoriteList()
{
$data = \addons\shopro\model\UserFavorite::getGoodsList();
$this->success('商品收藏列表', $data);
}
/**
* @ApiInternal
* 浏览记录删除
*/
public function viewDelete()
{
$params = $this->request->post();
... ... @@ -202,7 +220,10 @@ class Goods extends Base
$this->success('删除成功', $result);
}
/**
* @ApiInternal
* 浏览记录列表
*/
public function viewList()
{
$data = \addons\shopro\model\UserView::getGoodsList();
... ...
... ... @@ -36,36 +36,33 @@ class User extends Base
* @ApiReturn({
"code": 1,
"msg": "用户信息",
"time": "1607398760",
"time": "1607588102",
"data": {
"id": 1, //用户ID
"group_id": 1,
"username": "admin", //
"nickname": "123",
"mobile": "13888888888",
"avatar": "shuoshenme",
"birthday": "2017-04-15",
"money": "0.00",
"score": 0,
"token": "1419ae8b-dd47-4ab5-9c10-c88d42dc4cb3",
"user_id": 1,
"createtime": 1607397247,
"expiretime": 1609989247,
"expires_in": 2590487,
"group": {
"name": "默认组",
"image": "http://www.ant.top"
"group_id": 1, //分组ID
"nickname": "123", //昵称
"avatar": "shuoshenme", //头像
"money": "0.00", //余额
"score": 0, //积分
"token": "1419ae8b-dd47-4ab5-9c10-c88d42dc4cb3", //token
"user_id": 1, // 用户ID
"createtime": 1607397247, //注册时间
"expiretime": 1609989247, //token过期时间
"expires_in": 2401145, //过期时间段
"group": { //分组
"name": "默认组", //分组名称
"image": "http://www.ant.top" //分组图片
},
"coupons_num": 0,
"is_store": 0,
"store_id": 0
"coupons_num": 0, //优惠券数量
"is_store": 0, //是否是店铺管理员:0=否,1=是
"store_id": 0 //店铺ID
}
})
*/
public function index()
{
$auth = \app\common\library\Auth::instance();
$auth->setAllowFields(['id', 'nickname', 'avatar', 'score', 'money']);
$auth->setAllowFields(['id', 'nickname', 'avatar', 'score', 'money','group_id']);
$data = $auth->getUserinfo();
if (!isset($data['group'])) {
$data['group'] = \addons\shopro\model\UserGroup::get($data['group_id']);
... ... @@ -122,7 +119,15 @@ class User extends Base
*
* @ApiParams (name=code, type=string, required=true, description="加密code")
*
* @ApiReturn()
* @ApiReturn({
"code": 1,
"msg": "用户信息",
"time": "1607588102",
"data": {
"openid": 123456, //openid
"session_key": 123456, //session_key
}
})
*/
public function getWxMiniProgramSessionKey()
{
... ... @@ -142,7 +147,13 @@ class User extends Base
* @ApiParams (name=iv, type=string, required=true, description="iv")
* @ApiParams (name=encryptedData, type=string, required=true, description="encryptedData")
*
* @ApiReturn()
* @ApiReturn({
'code':'1',
'msg':'返回成功',
"data": {
"token": "9e4648c7-c640-4e41-b758-dd1a8ef7a7ae",
}
})
*/
public function wxMiniProgramLogin()
{
... ... @@ -277,8 +288,8 @@ class User extends Base
/**
* @ApiWeigh (97)
* @ApiTitle (微信小程序登录)
* @ApiSummary (微信小程序登录)
* @ApiTitle (修改会员个人信息)
* @ApiSummary (修改会员个人信息)
* @ApiMethod (POST)
*
* @ApiParams (name=nickname, type=string, required=true, description="昵称")
... ...
<?php
namespace app\api\validate;
use think\Validate;
class Address extends Validate
{
/**
* 验证规则
*/
protected $rule = [
'consignee' => 'require',
'phone' => 'require|regex:^1\d{10}$',
'area_id' => 'require',
'address' => 'require',
];
/**
* 提示消息
*/
protected $message = [
'consignee.require' => '收货人必须填写',
'phone.require' => '手机号必须填写',
'phone.regex' => '手机号格式不正确',
'area_id.require' => '省市区必须选择',
'address.require' => '详细地址必须填写',
];
/**
* 字段描述
*/
protected $field = [
];
/**
* 验证场景
*/
protected $scene = [
'edit' => ['consignee', 'phone', 'area_id', 'address'],
];
}
... ...
<?php
namespace addons\shopro\validate;
use think\Validate;
class Cart extends Validate
{
/**
* 验证规则
*/
protected $rule = [
'goods_list' => 'require|array',
'cart_list' => 'require|array',
'act' => 'require'
];
/**
* 提示消息
*/
protected $message = [
'goods_list.require' => '请选择商品',
'goods_list.array' => '请选择商品',
'cart_list.require' => '请选择购物车商品',
'cart_list.array' => '请选择购物车商品',
'act.require' => '参数错误',
];
/**
* 字段描述
*/
protected $field = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => ['goods_list'],
'edit' => ['cart_list', 'act'],
];
}
... ...
<?php
namespace addons\shopro\validate;
use think\Validate;
class Decorate extends Validate
{
/**
* 验证规则
*/
protected $rule = [
'id' => 'require',
'image' => 'require',
];
/**
* 提示消息
*/
protected $message = [
'id.require' => '缺少参数',
'image.require' => '缺少图片地址',
];
/**
* 字段描述
*/
protected $field = [
];
/**
* 验证场景
*/
protected $scene = [
'saveImg' => ['id', 'image'],
];
}
... ...
<?php
namespace addons\shopro\validate;
use think\Validate;
class Feedback extends Validate
{
/**
* 验证规则
*/
protected $rule = [
'type' => 'require',
'content' => 'require',
'images' => 'array',
'phone' => 'regex:^1\d{10}$'
];
/**
* 提示消息
*/
protected $message = [
'type.require' => '反馈类型必须选择',
'content.require' => '反馈内容必须填写',
'images.array' => '图片不正确',
'phone.regex' => '手机号格式不正确',
];
/**
* 字段描述
*/
protected $field = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => ['type', 'content', 'images', 'phone']
];
}
... ...
<?php
namespace addons\shopro\validate;
use think\Validate;
class Order extends Validate
{
/**
* 验证规则
*/
protected $rule = [
'id' => 'require',
'order_item_id' => 'require',
'level' => 'require|number|between:1,5',
'content' => 'require',
'images' => 'array',
'goods_list' => 'require|array|min:1'
];
/**
* 提示消息
*/
protected $message = [
'id.require' => '缺少参数',
'order_item_id.require' => '缺少订单商品参数',
// 评价
'level.require' => '描述相符必须选择',
'level.number' => '描述相符必须选择',
'level.between' => '描述相符必须选择',
'content.require' => '评价内容必须填写',
'images.array' => '图片不正确',
// 添加订单
"goods_list" => '请选择要购买的商品',
];
/**
* 字段描述
*/
protected $field = [
];
/**
* 验证场景
*/
protected $scene = [
'cancel' => ['id'],
'delete' => ['id'],
'confirm' => ['id', 'order_item_id'],
'aftersale' => ['id', 'order_item_id'],
'refund' => ['id', 'order_item_id'],
'comment' => ['id', 'order_item_id', 'level', 'content', 'images'],
'pre' => ['goods_list'],
'createOrder' => ['goods_list'],
'coupons' => ['goods_list']
];
}
... ...
<?php
namespace addons\shopro\validate;
use think\Validate;
class OrderAftersale extends Validate
{
/**
* 验证规则
*/
protected $rule = [
'id' => 'require',
'order_id' => 'require',
'order_item_id' => 'require',
'type' => 'require',
'phone' => 'require',
'reason' => 'require',
'images' => 'array',
];
/**
* 提示消息
*/
protected $message = [
'id.require' => '缺少参数',
'type.require' => '请选择售后类型',
'order_id.require' => '缺少参数',
'order_item_id.require' => '缺少订单商品参数',
'phone.require' => '联系方式必须填写',
'reason.require' => '售后原因必须选择',
'images.array' => '图片不正确',
];
/**
* 字段描述
*/
protected $field = [
];
/**
* 验证场景
*/
protected $scene = [
'detail' => ['id'],
'cancel' => ['id'],
'delete' => ['id'],
'aftersale' => ['type', 'order_id', 'order_item_id', 'phone', 'reason', 'images'],
];
}
... ...
<?php
namespace addons\shopro\validate;
use think\Validate;
class UserBank extends Validate
{
/**
* 验证规则
*/
protected $rule = [
'real_name' => 'require',
'bank_name' => 'require',
'card_no' => 'require',
];
/**
* 提示消息
*/
protected $message = [
'real_name.require' => '真实姓名必须填写',
'bank_name.require' => '银行必须填写',
'card_no.require' => '银行卡号必须填写',
];
/**
* 字段描述
*/
protected $field = [
];
/**
* 验证场景
*/
protected $scene = [
'edit' => ['real_name', 'bank_name', 'card_no'],
];
}
... ...
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
return [
'connector' => 'Sync'
];
... ...
... ... @@ -27,7 +27,8 @@
"symfony/var-exporter": "^4.4.13",
"ext-json": "*",
"ext-curl": "*",
"ext-pdo": "*"
"ext-pdo": "*",
"topthink/think-queue": "v1.1.6"
},
"config": {
"preferred-install": "dist"
... ...
此 diff 太大无法显示。
... ... @@ -29,7 +29,7 @@ private static $installed = array (
'aliases' =>
array (
),
'reference' => '8af7f5653ad04b0a43d7cf4afaff2e31aec923c4',
'reference' => '1907524334aef6c232dc16b8fd0cec852244fe97',
'name' => 'karsonzhang/fastadmin',
),
'versions' =>
... ... @@ -77,7 +77,7 @@ private static $installed = array (
'aliases' =>
array (
),
'reference' => '8af7f5653ad04b0a43d7cf4afaff2e31aec923c4',
'reference' => '1907524334aef6c232dc16b8fd0cec852244fe97',
),
'karsonzhang/fastadmin-addons' =>
array (
... ... @@ -434,6 +434,15 @@ private static $installed = array (
),
'reference' => '1d64363c814c92f6086c4fa5e3223fe7e23db09d',
),
'topthink/think-helper' =>
array (
'pretty_version' => 'v3.1.4',
'version' => '3.1.4.0',
'aliases' =>
array (
),
'reference' => 'c28d37743bda4a0455286ca85b17b5791d626e10',
),
'topthink/think-installer' =>
array (
'pretty_version' => 'v1.0.13',
... ... @@ -443,6 +452,15 @@ private static $installed = array (
),
'reference' => '532dc02efb3d8332b36fd8f63fc4f56aeb1987e7',
),
'topthink/think-queue' =>
array (
'pretty_version' => 'v1.1.6',
'version' => '1.1.6.0',
'aliases' =>
array (
),
'reference' => '250650eb0e8ea5af4cfdc7ae46f3f4e0a24ac245',
),
),
);
... ...
... ... @@ -7,29 +7,13 @@ $baseDir = dirname($vendorDir);
return array(
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
'9d8e013a5160a09477beb8e44f8ae97b' => $vendorDir . '/markbaker/matrix/classes/src/functions/adjoint.php',
'6e78d1bdea6248d6aa117229efae50f2' => $vendorDir . '/markbaker/matrix/classes/src/functions/antidiagonal.php',
'4623d87924d94f5412fe5afbf1cef31d' => $vendorDir . '/markbaker/matrix/classes/src/functions/cofactors.php',
'901fd1f6950a637ca85f66b701a45e13' => $vendorDir . '/markbaker/matrix/classes/src/functions/determinant.php',
'83057abc0e4acc99ba80154ee5d02a49' => $vendorDir . '/markbaker/matrix/classes/src/functions/diagonal.php',
'07b7fd7a434451149b4fd477fca0ce06' => $vendorDir . '/markbaker/matrix/classes/src/functions/identity.php',
'c8d43b340583e07ae89f2a3baef2cf89' => $vendorDir . '/markbaker/matrix/classes/src/functions/inverse.php',
'499bb10ed7a3aee2ba4c09a31a85e8d1' => $vendorDir . '/markbaker/matrix/classes/src/functions/minors.php',
'1cad2e6414d652e8b1c64e8967f6f37d' => $vendorDir . '/markbaker/matrix/classes/src/functions/trace.php',
'95a7f134ac17161d07def442b3b737e8' => $vendorDir . '/markbaker/matrix/classes/src/functions/transpose.php',
'b3a6bc628377118d4b4b8ba08d1eb949' => $vendorDir . '/markbaker/matrix/classes/src/operations/add.php',
'5fef6d0e407f3f8887266dfa4a6c534c' => $vendorDir . '/markbaker/matrix/classes/src/operations/directsum.php',
'684ba247e1385946e3babdaa054119de' => $vendorDir . '/markbaker/matrix/classes/src/operations/subtract.php',
'aa53dcba601214d17ad405b7c291b7e8' => $vendorDir . '/markbaker/matrix/classes/src/operations/multiply.php',
'75c79eb1b25749b05a47976f32b0d8a2' => $vendorDir . '/markbaker/matrix/classes/src/operations/divideby.php',
'6ab8ad87a734f276a6bcd5a0fe1289be' => $vendorDir . '/markbaker/matrix/classes/src/operations/divideinto.php',
'abede361264e2ae69ec1eee813a101af' => $vendorDir . '/markbaker/complex/classes/src/functions/abs.php',
'21a5860fbef5be28db5ddfbc3cca67c4' => $vendorDir . '/markbaker/complex/classes/src/functions/acos.php',
'1546e3f9d127f2a9bb2d1b6c31c26ef1' => $vendorDir . '/markbaker/complex/classes/src/functions/acosh.php',
... ... @@ -72,8 +56,26 @@ return array(
'883af48563631547925fa4c3b48ead07' => $vendorDir . '/markbaker/complex/classes/src/operations/multiply.php',
'f190e3308e6ca23234a2875edc985c03' => $vendorDir . '/markbaker/complex/classes/src/operations/divideby.php',
'ac9e33ce6841aa5bf5d16d465a2f03a7' => $vendorDir . '/markbaker/complex/classes/src/operations/divideinto.php',
'9d8e013a5160a09477beb8e44f8ae97b' => $vendorDir . '/markbaker/matrix/classes/src/functions/adjoint.php',
'6e78d1bdea6248d6aa117229efae50f2' => $vendorDir . '/markbaker/matrix/classes/src/functions/antidiagonal.php',
'4623d87924d94f5412fe5afbf1cef31d' => $vendorDir . '/markbaker/matrix/classes/src/functions/cofactors.php',
'901fd1f6950a637ca85f66b701a45e13' => $vendorDir . '/markbaker/matrix/classes/src/functions/determinant.php',
'83057abc0e4acc99ba80154ee5d02a49' => $vendorDir . '/markbaker/matrix/classes/src/functions/diagonal.php',
'07b7fd7a434451149b4fd477fca0ce06' => $vendorDir . '/markbaker/matrix/classes/src/functions/identity.php',
'c8d43b340583e07ae89f2a3baef2cf89' => $vendorDir . '/markbaker/matrix/classes/src/functions/inverse.php',
'499bb10ed7a3aee2ba4c09a31a85e8d1' => $vendorDir . '/markbaker/matrix/classes/src/functions/minors.php',
'1cad2e6414d652e8b1c64e8967f6f37d' => $vendorDir . '/markbaker/matrix/classes/src/functions/trace.php',
'95a7f134ac17161d07def442b3b737e8' => $vendorDir . '/markbaker/matrix/classes/src/functions/transpose.php',
'b3a6bc628377118d4b4b8ba08d1eb949' => $vendorDir . '/markbaker/matrix/classes/src/operations/add.php',
'5fef6d0e407f3f8887266dfa4a6c534c' => $vendorDir . '/markbaker/matrix/classes/src/operations/directsum.php',
'684ba247e1385946e3babdaa054119de' => $vendorDir . '/markbaker/matrix/classes/src/operations/subtract.php',
'aa53dcba601214d17ad405b7c291b7e8' => $vendorDir . '/markbaker/matrix/classes/src/operations/multiply.php',
'75c79eb1b25749b05a47976f32b0d8a2' => $vendorDir . '/markbaker/matrix/classes/src/operations/divideby.php',
'6ab8ad87a734f276a6bcd5a0fe1289be' => $vendorDir . '/markbaker/matrix/classes/src/operations/divideinto.php',
'9b552a3cc426e3287cc811caefa3cf53' => $vendorDir . '/topthink/think-helper/src/helper.php',
'488987c28e9b5e95a1ce6b6bcb94606c' => $vendorDir . '/karsonzhang/fastadmin-addons/src/common.php',
'f0e7e63bbb278a92db02393536748c5f' => $vendorDir . '/overtrue/wechat/src/Kernel/Support/Helpers.php',
'6747f579ad6817f318cc3a7e7a0abb93' => $vendorDir . '/overtrue/wechat/src/Kernel/Helpers.php',
'1cfd2761b63b0a29ed23657ea394cb2d' => $vendorDir . '/topthink/think-captcha/src/helper.php',
'cc56288302d9df745d97c934d6a6e5f0' => $vendorDir . '/topthink/think-queue/src/common.php',
);
... ...
... ... @@ -8,7 +8,7 @@ $baseDir = dirname($vendorDir);
return array(
'think\\composer\\' => array($vendorDir . '/topthink/think-installer/src'),
'think\\captcha\\' => array($vendorDir . '/topthink/think-captcha/src'),
'think\\' => array($vendorDir . '/karsonzhang/fastadmin-addons/src', $baseDir . '/thinkphp/library/think'),
'think\\' => array($vendorDir . '/karsonzhang/fastadmin-addons/src', $baseDir . '/thinkphp/library/think', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-queue/src'),
'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'),
... ...
... ... @@ -8,29 +8,13 @@ class ComposerStaticInit85e84021e2781f5f99c143befcc82f3d
{
public static $files = array (
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php',
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
'9d8e013a5160a09477beb8e44f8ae97b' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/adjoint.php',
'6e78d1bdea6248d6aa117229efae50f2' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/antidiagonal.php',
'4623d87924d94f5412fe5afbf1cef31d' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/cofactors.php',
'901fd1f6950a637ca85f66b701a45e13' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/determinant.php',
'83057abc0e4acc99ba80154ee5d02a49' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/diagonal.php',
'07b7fd7a434451149b4fd477fca0ce06' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/identity.php',
'c8d43b340583e07ae89f2a3baef2cf89' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/inverse.php',
'499bb10ed7a3aee2ba4c09a31a85e8d1' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/minors.php',
'1cad2e6414d652e8b1c64e8967f6f37d' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/trace.php',
'95a7f134ac17161d07def442b3b737e8' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/transpose.php',
'b3a6bc628377118d4b4b8ba08d1eb949' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/add.php',
'5fef6d0e407f3f8887266dfa4a6c534c' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/directsum.php',
'684ba247e1385946e3babdaa054119de' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/subtract.php',
'aa53dcba601214d17ad405b7c291b7e8' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/multiply.php',
'75c79eb1b25749b05a47976f32b0d8a2' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/divideby.php',
'6ab8ad87a734f276a6bcd5a0fe1289be' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/divideinto.php',
'abede361264e2ae69ec1eee813a101af' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/abs.php',
'21a5860fbef5be28db5ddfbc3cca67c4' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/acos.php',
'1546e3f9d127f2a9bb2d1b6c31c26ef1' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/acosh.php',
... ... @@ -73,10 +57,28 @@ class ComposerStaticInit85e84021e2781f5f99c143befcc82f3d
'883af48563631547925fa4c3b48ead07' => __DIR__ . '/..' . '/markbaker/complex/classes/src/operations/multiply.php',
'f190e3308e6ca23234a2875edc985c03' => __DIR__ . '/..' . '/markbaker/complex/classes/src/operations/divideby.php',
'ac9e33ce6841aa5bf5d16d465a2f03a7' => __DIR__ . '/..' . '/markbaker/complex/classes/src/operations/divideinto.php',
'9d8e013a5160a09477beb8e44f8ae97b' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/adjoint.php',
'6e78d1bdea6248d6aa117229efae50f2' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/antidiagonal.php',
'4623d87924d94f5412fe5afbf1cef31d' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/cofactors.php',
'901fd1f6950a637ca85f66b701a45e13' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/determinant.php',
'83057abc0e4acc99ba80154ee5d02a49' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/diagonal.php',
'07b7fd7a434451149b4fd477fca0ce06' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/identity.php',
'c8d43b340583e07ae89f2a3baef2cf89' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/inverse.php',
'499bb10ed7a3aee2ba4c09a31a85e8d1' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/minors.php',
'1cad2e6414d652e8b1c64e8967f6f37d' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/trace.php',
'95a7f134ac17161d07def442b3b737e8' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/transpose.php',
'b3a6bc628377118d4b4b8ba08d1eb949' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/add.php',
'5fef6d0e407f3f8887266dfa4a6c534c' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/directsum.php',
'684ba247e1385946e3babdaa054119de' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/subtract.php',
'aa53dcba601214d17ad405b7c291b7e8' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/multiply.php',
'75c79eb1b25749b05a47976f32b0d8a2' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/divideby.php',
'6ab8ad87a734f276a6bcd5a0fe1289be' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/divideinto.php',
'9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php',
'488987c28e9b5e95a1ce6b6bcb94606c' => __DIR__ . '/..' . '/karsonzhang/fastadmin-addons/src/common.php',
'f0e7e63bbb278a92db02393536748c5f' => __DIR__ . '/..' . '/overtrue/wechat/src/Kernel/Support/Helpers.php',
'6747f579ad6817f318cc3a7e7a0abb93' => __DIR__ . '/..' . '/overtrue/wechat/src/Kernel/Helpers.php',
'1cfd2761b63b0a29ed23657ea394cb2d' => __DIR__ . '/..' . '/topthink/think-captcha/src/helper.php',
'cc56288302d9df745d97c934d6a6e5f0' => __DIR__ . '/..' . '/topthink/think-queue/src/common.php',
);
public static $prefixLengthsPsr4 = array (
... ... @@ -154,6 +156,8 @@ class ComposerStaticInit85e84021e2781f5f99c143befcc82f3d
array (
0 => __DIR__ . '/..' . '/karsonzhang/fastadmin-addons/src',
1 => __DIR__ . '/../..' . '/thinkphp/library/think',
2 => __DIR__ . '/..' . '/topthink/think-helper/src',
3 => __DIR__ . '/..' . '/topthink/think-queue/src',
),
'Symfony\\Polyfill\\Php72\\' =>
array (
... ...
... ... @@ -2919,6 +2919,52 @@
"install-path": "../topthink/think-captcha"
},
{
"name": "topthink/think-helper",
"version": "v3.1.4",
"version_normalized": "3.1.4.0",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-helper.git",
"reference": "c28d37743bda4a0455286ca85b17b5791d626e10"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-helper/zipball/c28d37743bda4a0455286ca85b17b5791d626e10",
"reference": "c28d37743bda4a0455286ca85b17b5791d626e10",
"shasum": ""
},
"require": {
"php": ">=7.1.0"
},
"time": "2019-11-08T08:01:10+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"think\\": "src"
},
"files": [
"src/helper.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "yunwuxin",
"email": "448901948@qq.com"
}
],
"description": "The ThinkPHP6 Helper Package",
"support": {
"issues": "https://github.com/top-think/think-helper/issues",
"source": "https://github.com/top-think/think-helper/tree/3.0"
},
"install-path": "../topthink/think-helper"
},
{
"name": "topthink/think-installer",
"version": "v1.0.13",
"version_normalized": "1.0.13.0",
... ... @@ -2971,6 +3017,61 @@
"source": "https://github.com/top-think/think-installer/tree/v1.0.13"
},
"install-path": "../topthink/think-installer"
},
{
"name": "topthink/think-queue",
"version": "v1.1.6",
"version_normalized": "1.1.6.0",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-queue.git",
"reference": "250650eb0e8ea5af4cfdc7ae46f3f4e0a24ac245"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-queue/zipball/250650eb0e8ea5af4cfdc7ae46f3f4e0a24ac245",
"reference": "250650eb0e8ea5af4cfdc7ae46f3f4e0a24ac245",
"shasum": ""
},
"require": {
"topthink/think-helper": ">=1.0.4",
"topthink/think-installer": ">=1.0.10"
},
"require-dev": {
"topthink/framework": "~5.0.0"
},
"time": "2018-10-15T10:16:55+00:00",
"type": "think-extend",
"extra": {
"think-config": {
"queue": "src/config.php"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"think\\": "src"
},
"files": [
"src/common.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "yunwuxin",
"email": "448901948@qq.com"
}
],
"description": "The ThinkPHP5 Queue Package",
"support": {
"issues": "https://github.com/top-think/think-queue/issues",
"source": "https://github.com/top-think/think-queue/tree/master"
},
"install-path": "../topthink/think-queue"
}
],
"dev": true,
... ...
... ... @@ -6,7 +6,7 @@
'aliases' =>
array (
),
'reference' => '8af7f5653ad04b0a43d7cf4afaff2e31aec923c4',
'reference' => '1907524334aef6c232dc16b8fd0cec852244fe97',
'name' => 'karsonzhang/fastadmin',
),
'versions' =>
... ... @@ -54,7 +54,7 @@
'aliases' =>
array (
),
'reference' => '8af7f5653ad04b0a43d7cf4afaff2e31aec923c4',
'reference' => '1907524334aef6c232dc16b8fd0cec852244fe97',
),
'karsonzhang/fastadmin-addons' =>
array (
... ... @@ -411,6 +411,15 @@
),
'reference' => '1d64363c814c92f6086c4fa5e3223fe7e23db09d',
),
'topthink/think-helper' =>
array (
'pretty_version' => 'v3.1.4',
'version' => '3.1.4.0',
'aliases' =>
array (
),
'reference' => 'c28d37743bda4a0455286ca85b17b5791d626e10',
),
'topthink/think-installer' =>
array (
'pretty_version' => 'v1.0.13',
... ... @@ -420,5 +429,14 @@
),
'reference' => '532dc02efb3d8332b36fd8f63fc4f56aeb1987e7',
),
'topthink/think-queue' =>
array (
'pretty_version' => 'v1.1.6',
'version' => '1.1.6.0',
'aliases' =>
array (
),
'reference' => '250650eb0e8ea5af4cfdc7ae46f3f4e0a24ac245',
),
),
);
... ...
/vendor/
/.idea/
composer.lock
\ No newline at end of file
... ...
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
... ...
# thinkphp6 常用的一些扩展类库
基于PHP7.1+
> 以下类库都在`\\think\\helper`命名空间下
## Str
> 字符串操作
```
// 检查字符串中是否包含某些字符串
Str::contains($haystack, $needles)
// 检查字符串是否以某些字符串结尾
Str::endsWith($haystack, $needles)
// 获取指定长度的随机字母数字组合的字符串
Str::random($length = 16)
// 字符串转小写
Str::lower($value)
// 字符串转大写
Str::upper($value)
// 获取字符串的长度
Str::length($value)
// 截取字符串
Str::substr($string, $start, $length = null)
```
\ No newline at end of file
... ...
{
"name": "topthink/think-helper",
"description": "The ThinkPHP6 Helper Package",
"license": "Apache-2.0",
"authors": [
{
"name": "yunwuxin",
"email": "448901948@qq.com"
}
],
"require": {
"php": ">=7.1.0"
},
"autoload": {
"psr-4": {
"think\\": "src"
},
"files": [
"src/helper.php"
]
}
}
... ...
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: zhangyajun <448901948@qq.com>
// +----------------------------------------------------------------------
declare (strict_types = 1);
namespace think;
use ArrayAccess;
use ArrayIterator;
use Countable;
use IteratorAggregate;
use JsonSerializable;
use think\contract\Arrayable;
use think\contract\Jsonable;
use think\helper\Arr;
/**
* 数据集管理类
*/
class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable, Arrayable, Jsonable
{
/**
* 数据集数据
* @var array
*/
protected $items = [];
public function __construct($items = [])
{
$this->items = $this->convertToArray($items);
}
public static function make($items = [])
{
return new static($items);
}
/**
* 是否为空
* @access public
* @return bool
*/
public function isEmpty(): bool
{
return empty($this->items);
}
public function toArray(): array
{
return array_map(function ($value) {
return $value instanceof Arrayable ? $value->toArray() : $value;
}, $this->items);
}
public function all(): array
{
return $this->items;
}
/**
* 合并数组
*
* @access public
* @param mixed $items 数据
* @return static
*/
public function merge($items)
{
return new static(array_merge($this->items, $this->convertToArray($items)));
}
/**
* 按指定键整理数据
*
* @access public
* @param mixed $items 数据
* @param string $indexKey 键名
* @return array
*/
public function dictionary($items = null, string &$indexKey = null)
{
if ($items instanceof self) {
$items = $items->all();
}
$items = is_null($items) ? $this->items : $items;
if ($items && empty($indexKey)) {
$indexKey = is_array($items[0]) ? 'id' : $items[0]->getPk();
}
if (isset($indexKey) && is_string($indexKey)) {
return array_column($items, null, $indexKey);
}
return $items;
}
/**
* 比较数组,返回差集
*
* @access public
* @param mixed $items 数据
* @param string $indexKey 指定比较的键名
* @return static
*/
public function diff($items, string $indexKey = null)
{
if ($this->isEmpty() || is_scalar($this->items[0])) {
return new static(array_diff($this->items, $this->convertToArray($items)));
}
$diff = [];
$dictionary = $this->dictionary($items, $indexKey);
if (is_string($indexKey)) {
foreach ($this->items as $item) {
if (!isset($dictionary[$item[$indexKey]])) {
$diff[] = $item;
}
}
}
return new static($diff);
}
/**
* 比较数组,返回交集
*
* @access public
* @param mixed $items 数据
* @param string $indexKey 指定比较的键名
* @return static
*/
public function intersect($items, string $indexKey = null)
{
if ($this->isEmpty() || is_scalar($this->items[0])) {
return new static(array_diff($this->items, $this->convertToArray($items)));
}
$intersect = [];
$dictionary = $this->dictionary($items, $indexKey);
if (is_string($indexKey)) {
foreach ($this->items as $item) {
if (isset($dictionary[$item[$indexKey]])) {
$intersect[] = $item;
}
}
}
return new static($intersect);
}
/**
* 交换数组中的键和值
*
* @access public
* @return static
*/
public function flip()
{
return new static(array_flip($this->items));
}
/**
* 返回数组中所有的键名
*
* @access public
* @return static
*/
public function keys()
{
return new static(array_keys($this->items));
}
/**
* 返回数组中所有的值组成的新 Collection 实例
* @access public
* @return static
*/
public function values()
{
return new static(array_values($this->items));
}
/**
* 删除数组的最后一个元素(出栈)
*
* @access public
* @return mixed
*/
public function pop()
{
return array_pop($this->items);
}
/**
* 通过使用用户自定义函数,以字符串返回数组
*
* @access public
* @param callable $callback 调用方法
* @param mixed $initial
* @return mixed
*/
public function reduce(callable $callback, $initial = null)
{
return array_reduce($this->items, $callback, $initial);
}
/**
* 以相反的顺序返回数组。
*
* @access public
* @return static
*/
public function reverse()
{
return new static(array_reverse($this->items));
}
/**
* 删除数组中首个元素,并返回被删除元素的值
*
* @access public
* @return mixed
*/
public function shift()
{
return array_shift($this->items);
}
/**
* 在数组结尾插入一个元素
* @access public
* @param mixed $value 元素
* @param string $key KEY
* @return void
*/
public function push($value, string $key = null): void
{
if (is_null($key)) {
$this->items[] = $value;
} else {
$this->items[$key] = $value;
}
}
/**
* 把一个数组分割为新的数组块.
*
* @access public
* @param int $size 块大小
* @param bool $preserveKeys
* @return static
*/
public function chunk(int $size, bool $preserveKeys = false)
{
$chunks = [];
foreach (array_chunk($this->items, $size, $preserveKeys) as $chunk) {
$chunks[] = new static($chunk);
}
return new static($chunks);
}
/**
* 在数组开头插入一个元素
* @access public
* @param mixed $value 元素
* @param string $key KEY
* @return void
*/
public function unshift($value, string $key = null): void
{
if (is_null($key)) {
array_unshift($this->items, $value);
} else {
$this->items = [$key => $value] + $this->items;
}
}
/**
* 给每个元素执行个回调
*
* @access public
* @param callable $callback 回调
* @return $this
*/
public function each(callable $callback)
{
foreach ($this->items as $key => $item) {
$result = $callback($item, $key);
if (false === $result) {
break;
} elseif (!is_object($item)) {
$this->items[$key] = $result;
}
}
return $this;
}
/**
* 用回调函数处理数组中的元素
* @access public
* @param callable|null $callback 回调
* @return static
*/
public function map(callable $callback)
{
return new static(array_map($callback, $this->items));
}
/**
* 用回调函数过滤数组中的元素
* @access public
* @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));
}
/**
* 根据字段条件过滤数组中的元素
* @access public
* @param string $field 字段名
* @param mixed $operator 操作符
* @param mixed $value 数据
* @return static
*/
public function where(string $field, $operator, $value = null)
{
if (is_null($value)) {
$value = $operator;
$operator = '=';
}
return $this->filter(function ($data) use ($field, $operator, $value) {
if (strpos($field, '.')) {
[$field, $relation] = explode('.', $field);
$result = $data[$field][$relation] ?? null;
} else {
$result = $data[$field] ?? null;
}
switch (strtolower($operator)) {
case '===':
return $result === $value;
case '!==':
return $result !== $value;
case '!=':
case '<>':
return $result != $value;
case '>':
return $result > $value;
case '>=':
return $result >= $value;
case '<':
return $result < $value;
case '<=':
return $result <= $value;
case 'like':
return is_string($result) && false !== strpos($result, $value);
case 'not like':
return is_string($result) && false === strpos($result, $value);
case 'in':
return is_scalar($result) && in_array($result, $value, true);
case 'not in':
return is_scalar($result) && !in_array($result, $value, true);
case 'between':
[$min, $max] = is_string($value) ? explode(',', $value) : $value;
return is_scalar($result) && $result >= $min && $result <= $max;
case 'not between':
[$min, $max] = is_string($value) ? explode(',', $value) : $value;
return is_scalar($result) && $result > $max || $result < $min;
case '==':
case '=':
default:
return $result == $value;
}
});
}
/**
* LIKE过滤
* @access public
* @param string $field 字段名
* @param string $value 数据
* @return static
*/
public function whereLike(string $field, string $value)
{
return $this->where($field, 'like', $value);
}
/**
* NOT LIKE过滤
* @access public
* @param string $field 字段名
* @param string $value 数据
* @return static
*/
public function whereNotLike(string $field, string $value)
{
return $this->where($field, 'not like', $value);
}
/**
* IN过滤
* @access public
* @param string $field 字段名
* @param array $value 数据
* @return static
*/
public function whereIn(string $field, array $value)
{
return $this->where($field, 'in', $value);
}
/**
* NOT IN过滤
* @access public
* @param string $field 字段名
* @param array $value 数据
* @return static
*/
public function whereNotIn(string $field, array $value)
{
return $this->where($field, 'not in', $value);
}
/**
* BETWEEN 过滤
* @access public
* @param string $field 字段名
* @param mixed $value 数据
* @return static
*/
public function whereBetween(string $field, $value)
{
return $this->where($field, 'between', $value);
}
/**
* NOT BETWEEN 过滤
* @access public
* @param string $field 字段名
* @param mixed $value 数据
* @return static
*/
public function whereNotBetween(string $field, $value)
{
return $this->where($field, 'not between', $value);
}
/**
* 返回数据中指定的一列
* @access public
* @param string|null $columnKey 键名
* @param string|null $indexKey 作为索引值的列
* @return array
*/
public function column(?string $columnKey, string $indexKey = null)
{
return array_column($this->items, $columnKey, $indexKey);
}
/**
* 对数组排序
*
* @access public
* @param callable|null $callback 回调
* @return static
*/
public function sort(callable $callback = null)
{
$items = $this->items;
$callback = $callback ?: function ($a, $b) {
return $a == $b ? 0 : (($a < $b) ? -1 : 1);
};
uasort($items, $callback);
return new static($items);
}
/**
* 指定字段排序
* @access public
* @param string $field 排序字段
* @param string $order 排序
* @return $this
*/
public function order(string $field, string $order = 'asc')
{
return $this->sort(function ($a, $b) use ($field, $order) {
$fieldA = $a[$field] ?? null;
$fieldB = $b[$field] ?? null;
return 'desc' == strtolower($order) ? $fieldB > $fieldA : $fieldA > $fieldB;
});
}
/**
* 将数组打乱
*
* @access public
* @return static
*/
public function shuffle()
{
$items = $this->items;
shuffle($items);
return new static($items);
}
/**
* 获取最第一个单元数据
*
* @access public
* @param callable|null $callback
* @param null $default
* @return mixed
*/
public function first(callable $callback = null, $default = null)
{
return Arr::first($this->items, $callback, $default);
}
/**
* 获取最后一个单元数据
*
* @access public
* @param callable|null $callback
* @param null $default
* @return mixed
*/
public function last(callable $callback = null, $default = null)
{
return Arr::last($this->items, $callback, $default);
}
/**
* 截取数组
*
* @access public
* @param int $offset 起始位置
* @param int $length 截取长度
* @param bool $preserveKeys preserveKeys
* @return static
*/
public function slice(int $offset, int $length = null, bool $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(int $options = JSON_UNESCAPED_UNICODE): string
{
return json_encode($this->toArray(), $options);
}
public function __toString()
{
return $this->toJson();
}
/**
* 转换成数组
*
* @access public
* @param mixed $items 数据
* @return array
*/
protected function convertToArray($items): array
{
if ($items instanceof self) {
return $items->all();
}
return (array) $items;
}
}
... ...
<?php
namespace think\contract;
interface Arrayable
{
public function toArray(): array;
}
... ...
<?php
namespace think\contract;
interface Jsonable
{
public function toJson(int $options = JSON_UNESCAPED_UNICODE): string;
}
... ...
<?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>
// +----------------------------------------------------------------------
use think\Collection;
use think\helper\Arr;
if (!function_exists('throw_if')) {
/**
* 按条件抛异常
*
* @param mixed $condition
* @param Throwable|string $exception
* @param array ...$parameters
* @return mixed
*
* @throws Throwable
*/
function throw_if($condition, $exception, ...$parameters)
{
if ($condition) {
throw (is_string($exception) ? new $exception(...$parameters) : $exception);
}
return $condition;
}
}
if (!function_exists('throw_unless')) {
/**
* 按条件抛异常
*
* @param mixed $condition
* @param Throwable|string $exception
* @param array ...$parameters
* @return mixed
* @throws Throwable
*/
function throw_unless($condition, $exception, ...$parameters)
{
if (!$condition) {
throw (is_string($exception) ? new $exception(...$parameters) : $exception);
}
return $condition;
}
}
if (!function_exists('tap')) {
/**
* 对一个值调用给定的闭包,然后返回该值
*
* @param mixed $value
* @param callable|null $callback
* @return mixed
*/
function tap($value, $callback = null)
{
if (is_null($callback)) {
return $value;
}
$callback($value);
return $value;
}
}
if (!function_exists('value')) {
/**
* Return the default value of the given value.
*
* @param mixed $value
* @return mixed
*/
function value($value)
{
return $value instanceof Closure ? $value() : $value;
}
}
if (!function_exists('collect')) {
/**
* Create a collection from the given value.
*
* @param mixed $value
* @return Collection
*/
function collect($value = null)
{
return new Collection($value);
}
}
if (!function_exists('data_fill')) {
/**
* Fill in data where it's missing.
*
* @param mixed $target
* @param string|array $key
* @param mixed $value
* @return mixed
*/
function data_fill(&$target, $key, $value)
{
return data_set($target, $key, $value, false);
}
}
if (!function_exists('data_get')) {
/**
* Get an item from an array or object using "dot" notation.
*
* @param mixed $target
* @param string|array|int $key
* @param mixed $default
* @return mixed
*/
function data_get($target, $key, $default = null)
{
if (is_null($key)) {
return $target;
}
$key = is_array($key) ? $key : explode('.', $key);
while (!is_null($segment = array_shift($key))) {
if ('*' === $segment) {
if ($target instanceof Collection) {
$target = $target->all();
} elseif (!is_array($target)) {
return value($default);
}
$result = [];
foreach ($target as $item) {
$result[] = data_get($item, $key);
}
return in_array('*', $key) ? Arr::collapse($result) : $result;
}
if (Arr::accessible($target) && Arr::exists($target, $segment)) {
$target = $target[$segment];
} elseif (is_object($target) && isset($target->{$segment})) {
$target = $target->{$segment};
} else {
return value($default);
}
}
return $target;
}
}
if (!function_exists('data_set')) {
/**
* Set an item on an array or object using dot notation.
*
* @param mixed $target
* @param string|array $key
* @param mixed $value
* @param bool $overwrite
* @return mixed
*/
function data_set(&$target, $key, $value, $overwrite = true)
{
$segments = is_array($key) ? $key : explode('.', $key);
if (($segment = array_shift($segments)) === '*') {
if (!Arr::accessible($target)) {
$target = [];
}
if ($segments) {
foreach ($target as &$inner) {
data_set($inner, $segments, $value, $overwrite);
}
} elseif ($overwrite) {
foreach ($target as &$inner) {
$inner = $value;
}
}
} elseif (Arr::accessible($target)) {
if ($segments) {
if (!Arr::exists($target, $segment)) {
$target[$segment] = [];
}
data_set($target[$segment], $segments, $value, $overwrite);
} elseif ($overwrite || !Arr::exists($target, $segment)) {
$target[$segment] = $value;
}
} elseif (is_object($target)) {
if ($segments) {
if (!isset($target->{$segment})) {
$target->{$segment} = [];
}
data_set($target->{$segment}, $segments, $value, $overwrite);
} elseif ($overwrite || !isset($target->{$segment})) {
$target->{$segment} = $value;
}
} else {
$target = [];
if ($segments) {
data_set($target[$segment], $segments, $value, $overwrite);
} elseif ($overwrite) {
$target[$segment] = $value;
}
}
return $target;
}
}
if (!function_exists('trait_uses_recursive')) {
/**
* 获取一个trait里所有引用到的trait
*
* @param string $trait Trait
* @return array
*/
function trait_uses_recursive(string $trait): array
{
$traits = class_uses($trait);
foreach ($traits as $trait) {
$traits += trait_uses_recursive($trait);
}
return $traits;
}
}
if (!function_exists('class_basename')) {
/**
* 获取类名(不包含命名空间)
*
* @param mixed $class 类名
* @return string
*/
function class_basename($class): string
{
$class = is_object($class) ? get_class($class) : $class;
return basename(str_replace('\\', '/', $class));
}
}
if (!function_exists('class_uses_recursive')) {
/**
*获取一个类里所有用到的trait,包括父类的
*
* @param mixed $class 类名
* @return array
*/
function class_uses_recursive($class): array
{
if (is_object($class)) {
$class = get_class($class);
}
$results = [];
$classes = array_merge([$class => $class], class_parents($class));
foreach ($classes as $class) {
$results += trait_uses_recursive($class);
}
return array_unique($results);
}
}
... ...
<?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\helper;
use ArrayAccess;
use InvalidArgumentException;
use think\Collection;
class Arr
{
/**
* Determine whether the given value is array accessible.
*
* @param mixed $value
* @return bool
*/
public static function accessible($value)
{
return is_array($value) || $value instanceof ArrayAccess;
}
/**
* Add an element to an array using "dot" notation if it doesn't exist.
*
* @param array $array
* @param string $key
* @param mixed $value
* @return array
*/
public static function add($array, $key, $value)
{
if (is_null(static::get($array, $key))) {
static::set($array, $key, $value);
}
return $array;
}
/**
* Collapse an array of arrays into a single array.
*
* @param array $array
* @return array
*/
public static function collapse($array)
{
$results = [];
foreach ($array as $values) {
if ($values instanceof Collection) {
$values = $values->all();
} elseif (!is_array($values)) {
continue;
}
$results = array_merge($results, $values);
}
return $results;
}
/**
* Cross join the given arrays, returning all possible permutations.
*
* @param array ...$arrays
* @return array
*/
public static function crossJoin(...$arrays)
{
$results = [[]];
foreach ($arrays as $index => $array) {
$append = [];
foreach ($results as $product) {
foreach ($array as $item) {
$product[$index] = $item;
$append[] = $product;
}
}
$results = $append;
}
return $results;
}
/**
* Divide an array into two arrays. One with keys and the other with values.
*
* @param array $array
* @return array
*/
public static function divide($array)
{
return [array_keys($array), array_values($array)];
}
/**
* Flatten a multi-dimensional associative array with dots.
*
* @param array $array
* @param string $prepend
* @return array
*/
public static function dot($array, $prepend = '')
{
$results = [];
foreach ($array as $key => $value) {
if (is_array($value) && !empty($value)) {
$results = array_merge($results, static::dot($value, $prepend . $key . '.'));
} else {
$results[$prepend . $key] = $value;
}
}
return $results;
}
/**
* Get all of the given array except for a specified array of keys.
*
* @param array $array
* @param array|string $keys
* @return array
*/
public static function except($array, $keys)
{
static::forget($array, $keys);
return $array;
}
/**
* Determine if the given key exists in the provided array.
*
* @param \ArrayAccess|array $array
* @param string|int $key
* @return bool
*/
public static function exists($array, $key)
{
if ($array instanceof ArrayAccess) {
return $array->offsetExists($key);
}
return array_key_exists($key, $array);
}
/**
* Return the first element in an array passing a given truth test.
*
* @param array $array
* @param callable|null $callback
* @param mixed $default
* @return mixed
*/
public static function first($array, callable $callback = null, $default = null)
{
if (is_null($callback)) {
if (empty($array)) {
return value($default);
}
foreach ($array as $item) {
return $item;
}
}
foreach ($array as $key => $value) {
if (call_user_func($callback, $value, $key)) {
return $value;
}
}
return value($default);
}
/**
* Return the last element in an array passing a given truth test.
*
* @param array $array
* @param callable|null $callback
* @param mixed $default
* @return mixed
*/
public static function last($array, callable $callback = null, $default = null)
{
if (is_null($callback)) {
return empty($array) ? value($default) : end($array);
}
return static::first(array_reverse($array, true), $callback, $default);
}
/**
* Flatten a multi-dimensional array into a single level.
*
* @param array $array
* @param int $depth
* @return array
*/
public static function flatten($array, $depth = INF)
{
$result = [];
foreach ($array as $item) {
$item = $item instanceof Collection ? $item->all() : $item;
if (!is_array($item)) {
$result[] = $item;
} elseif ($depth === 1) {
$result = array_merge($result, array_values($item));
} else {
$result = array_merge($result, static::flatten($item, $depth - 1));
}
}
return $result;
}
/**
* Remove one or many array items from a given array using "dot" notation.
*
* @param array $array
* @param array|string $keys
* @return void
*/
public static function forget(&$array, $keys)
{
$original = &$array;
$keys = (array) $keys;
if (count($keys) === 0) {
return;
}
foreach ($keys as $key) {
// if the exact key exists in the top-level, remove it
if (static::exists($array, $key)) {
unset($array[$key]);
continue;
}
$parts = explode('.', $key);
// clean up before each pass
$array = &$original;
while (count($parts) > 1) {
$part = array_shift($parts);
if (isset($array[$part]) && is_array($array[$part])) {
$array = &$array[$part];
} else {
continue 2;
}
}
unset($array[array_shift($parts)]);
}
}
/**
* Get an item from an array using "dot" notation.
*
* @param \ArrayAccess|array $array
* @param string $key
* @param mixed $default
* @return mixed
*/
public static function get($array, $key, $default = null)
{
if (!static::accessible($array)) {
return value($default);
}
if (is_null($key)) {
return $array;
}
if (static::exists($array, $key)) {
return $array[$key];
}
if (strpos($key, '.') === false) {
return $array[$key] ?? value($default);
}
foreach (explode('.', $key) as $segment) {
if (static::accessible($array) && static::exists($array, $segment)) {
$array = $array[$segment];
} else {
return value($default);
}
}
return $array;
}
/**
* Check if an item or items exist in an array using "dot" notation.
*
* @param \ArrayAccess|array $array
* @param string|array $keys
* @return bool
*/
public static function has($array, $keys)
{
$keys = (array) $keys;
if (!$array || $keys === []) {
return false;
}
foreach ($keys as $key) {
$subKeyArray = $array;
if (static::exists($array, $key)) {
continue;
}
foreach (explode('.', $key) as $segment) {
if (static::accessible($subKeyArray) && static::exists($subKeyArray, $segment)) {
$subKeyArray = $subKeyArray[$segment];
} else {
return false;
}
}
}
return true;
}
/**
* Determines if an array is associative.
*
* An array is "associative" if it doesn't have sequential numerical keys beginning with zero.
*
* @param array $array
* @return bool
*/
public static function isAssoc(array $array)
{
$keys = array_keys($array);
return array_keys($keys) !== $keys;
}
/**
* Get a subset of the items from the given array.
*
* @param array $array
* @param array|string $keys
* @return array
*/
public static function only($array, $keys)
{
return array_intersect_key($array, array_flip((array) $keys));
}
/**
* Pluck an array of values from an array.
*
* @param array $array
* @param string|array $value
* @param string|array|null $key
* @return array
*/
public static function pluck($array, $value, $key = null)
{
$results = [];
[$value, $key] = static::explodePluckParameters($value, $key);
foreach ($array as $item) {
$itemValue = data_get($item, $value);
// If the key is "null", we will just append the value to the array and keep
// looping. Otherwise we will key the array using the value of the key we
// received from the developer. Then we'll return the final array form.
if (is_null($key)) {
$results[] = $itemValue;
} else {
$itemKey = data_get($item, $key);
if (is_object($itemKey) && method_exists($itemKey, '__toString')) {
$itemKey = (string) $itemKey;
}
$results[$itemKey] = $itemValue;
}
}
return $results;
}
/**
* Explode the "value" and "key" arguments passed to "pluck".
*
* @param string|array $value
* @param string|array|null $key
* @return array
*/
protected static function explodePluckParameters($value, $key)
{
$value = is_string($value) ? explode('.', $value) : $value;
$key = is_null($key) || is_array($key) ? $key : explode('.', $key);
return [$value, $key];
}
/**
* Push an item onto the beginning of an array.
*
* @param array $array
* @param mixed $value
* @param mixed $key
* @return array
*/
public static function prepend($array, $value, $key = null)
{
if (is_null($key)) {
array_unshift($array, $value);
} else {
$array = [$key => $value] + $array;
}
return $array;
}
/**
* Get a value from the array, and remove it.
*
* @param array $array
* @param string $key
* @param mixed $default
* @return mixed
*/
public static function pull(&$array, $key, $default = null)
{
$value = static::get($array, $key, $default);
static::forget($array, $key);
return $value;
}
/**
* Get one or a specified number of random values from an array.
*
* @param array $array
* @param int|null $number
* @return mixed
*
* @throws \InvalidArgumentException
*/
public static function random($array, $number = null)
{
$requested = is_null($number) ? 1 : $number;
$count = count($array);
if ($requested > $count) {
throw new InvalidArgumentException(
"You requested {$requested} items, but there are only {$count} items available."
);
}
if (is_null($number)) {
return $array[array_rand($array)];
}
if ((int) $number === 0) {
return [];
}
$keys = array_rand($array, $number);
$results = [];
foreach ((array) $keys as $key) {
$results[] = $array[$key];
}
return $results;
}
/**
* Set an array item to a given value using "dot" notation.
*
* If no key is given to the method, the entire array will be replaced.
*
* @param array $array
* @param string $key
* @param mixed $value
* @return array
*/
public static function set(&$array, $key, $value)
{
if (is_null($key)) {
return $array = $value;
}
$keys = explode('.', $key);
while (count($keys) > 1) {
$key = array_shift($keys);
// If the key doesn't exist at this depth, we will just create an empty array
// to hold the next value, allowing us to create the arrays to hold final
// values at the correct depth. Then we'll keep digging into the array.
if (!isset($array[$key]) || !is_array($array[$key])) {
$array[$key] = [];
}
$array = &$array[$key];
}
$array[array_shift($keys)] = $value;
return $array;
}
/**
* Shuffle the given array and return the result.
*
* @param array $array
* @param int|null $seed
* @return array
*/
public static function shuffle($array, $seed = null)
{
if (is_null($seed)) {
shuffle($array);
} else {
srand($seed);
usort($array, function () {
return rand(-1, 1);
});
}
return $array;
}
/**
* Sort the array using the given callback or "dot" notation.
*
* @param array $array
* @param callable|string|null $callback
* @return array
*/
public static function sort($array, $callback = null)
{
return Collection::make($array)->sort($callback)->all();
}
/**
* Recursively sort an array by keys and values.
*
* @param array $array
* @return array
*/
public static function sortRecursive($array)
{
foreach ($array as &$value) {
if (is_array($value)) {
$value = static::sortRecursive($value);
}
}
if (static::isAssoc($array)) {
ksort($array);
} else {
sort($array);
}
return $array;
}
/**
* Convert the array into a query string.
*
* @param array $array
* @return string
*/
public static function query($array)
{
return http_build_query($array, null, '&', PHP_QUERY_RFC3986);
}
/**
* Filter the array using the given callback.
*
* @param array $array
* @param callable $callback
* @return array
*/
public static function where($array, callable $callback)
{
return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
}
/**
* If the given value is not an array and not null, wrap it in one.
*
* @param mixed $value
* @return array
*/
public static function wrap($value)
{
if (is_null($value)) {
return [];
}
return is_array($value) ? $value : [$value];
}
}
\ No newline at end of file
... ...
<?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\helper;
class Str
{
protected static $snakeCache = [];
protected static $camelCache = [];
protected static $studlyCache = [];
/**
* 检查字符串中是否包含某些字符串
* @param string $haystack
* @param string|array $needles
* @return bool
*/
public static function contains(string $haystack, $needles): bool
{
foreach ((array) $needles as $needle) {
if ('' != $needle && mb_strpos($haystack, $needle) !== false) {
return true;
}
}
return false;
}
/**
* 检查字符串是否以某些字符串结尾
*
* @param string $haystack
* @param string|array $needles
* @return bool
*/
public static function endsWith(string $haystack, $needles): bool
{
foreach ((array) $needles as $needle) {
if ((string) $needle === static::substr($haystack, -static::length($needle))) {
return true;
}
}
return false;
}
/**
* 检查字符串是否以某些字符串开头
*
* @param string $haystack
* @param string|array $needles
* @return bool
*/
public static function startsWith(string $haystack, $needles): bool
{
foreach ((array) $needles as $needle) {
if ('' != $needle && mb_strpos($haystack, $needle) === 0) {
return true;
}
}
return false;
}
/**
* 获取指定长度的随机字母数字组合的字符串
*
* @param int $length
* @param int $type
* @param string $addChars
* @return string
*/
public static function random(int $length = 6, int $type = null, string $addChars = ''): string
{
$str = '';
switch ($type) {
case 0:
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' . $addChars;
break;
case 1:
$chars = str_repeat('0123456789', 3);
break;
case 2:
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' . $addChars;
break;
case 3:
$chars = 'abcdefghijklmnopqrstuvwxyz' . $addChars;
break;
case 4:
$chars = "们以我到他会作时要动国产的一是工就年阶义发成部民可出能方进在了不和有大这主中人上为来分生对于学下级地个用同行面说种过命度革而多子后自社加小机也经力线本电高量长党得实家定深法表着水理化争现所二起政三好十战无农使性前等反体合斗路图把结第里正新开论之物从当两些还天资事队批点育重其思与间内去因件日利相由压员气业代全组数果期导平各基或月毛然如应形想制心样干都向变关问比展那它最及外没看治提五解系林者米群头意只明四道马认次文通但条较克又公孔领军流入接席位情运器并飞原油放立题质指建区验活众很教决特此常石强极土少已根共直团统式转别造切九你取西持总料连任志观调七么山程百报更见必真保热委手改管处己将修支识病象几先老光专什六型具示复安带每东增则完风回南广劳轮科北打积车计给节做务被整联步类集号列温装即毫知轴研单色坚据速防史拉世设达尔场织历花受求传口断况采精金界品判参层止边清至万确究书" . $addChars;
break;
default:
$chars = 'ABCDEFGHIJKMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789' . $addChars;
break;
}
if ($length > 10) {
$chars = $type == 1 ? str_repeat($chars, $length) : str_repeat($chars, 5);
}
if ($type != 4) {
$chars = str_shuffle($chars);
$str = substr($chars, 0, $length);
} else {
for ($i = 0; $i < $length; $i++) {
$str .= mb_substr($chars, floor(mt_rand(0, mb_strlen($chars, 'utf-8') - 1)), 1);
}
}
return $str;
}
/**
* 字符串转小写
*
* @param string $value
* @return string
*/
public static function lower(string $value): string
{
return mb_strtolower($value, 'UTF-8');
}
/**
* 字符串转大写
*
* @param string $value
* @return string
*/
public static function upper(string $value): string
{
return mb_strtoupper($value, 'UTF-8');
}
/**
* 获取字符串的长度
*
* @param string $value
* @return int
*/
public static function length(string $value): int
{
return mb_strlen($value);
}
/**
* 截取字符串
*
* @param string $string
* @param int $start
* @param int|null $length
* @return string
*/
public static function substr(string $string, int $start, int $length = null): string
{
return mb_substr($string, $start, $length, 'UTF-8');
}
/**
* 驼峰转下划线
*
* @param string $value
* @param string $delimiter
* @return string
*/
public static function snake(string $value, string $delimiter = '_'): string
{
$key = $value;
if (isset(static::$snakeCache[$key][$delimiter])) {
return static::$snakeCache[$key][$delimiter];
}
if (!ctype_lower($value)) {
$value = preg_replace('/\s+/u', '', $value);
$value = static::lower(preg_replace('/(.)(?=[A-Z])/u', '$1' . $delimiter, $value));
}
return static::$snakeCache[$key][$delimiter] = $value;
}
/**
* 下划线转驼峰(首字母小写)
*
* @param string $value
* @return string
*/
public static function camel(string $value): string
{
if (isset(static::$camelCache[$value])) {
return static::$camelCache[$value];
}
return static::$camelCache[$value] = lcfirst(static::studly($value));
}
/**
* 下划线转驼峰(首字母大写)
*
* @param string $value
* @return string
*/
public static function studly(string $value): string
{
$key = $value;
if (isset(static::$studlyCache[$key])) {
return static::$studlyCache[$key];
}
$value = ucwords(str_replace(['-', '_'], ' ', $value));
return static::$studlyCache[$key] = str_replace(' ', '', $value);
}
/**
* 转为首字母大写的标题格式
*
* @param string $value
* @return string
*/
public static function title(string $value): string
{
return mb_convert_case($value, MB_CASE_TITLE, 'UTF-8');
}
}
... ...
/vendor/
/.idea/
/composer.lock
/thinkphp/
... ...
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
... ...
# think-queue
## 安装
> composer require topthink/think-queue
## 配置
> 配置文件位于 `application/extra/queue.php`
### 公共配置
```
[
'connector'=>'sync' //驱动类型,可选择 sync(默认):同步执行,database:数据库驱动,redis:Redis驱动,topthink:Topthink驱动
//或其他自定义的完整的类名
]
```
### 驱动配置
> 各个驱动的具体可用配置项在`think\queue\connector`目录下各个驱动类里的`options`属性中,写在上面的`queue`配置里即可覆盖
## 使用 Database
> 创建如下数据表
```
CREATE TABLE `prefix_jobs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`queue` varchar(255) NOT NULL,
`payload` longtext NOT NULL,
`attempts` tinyint(3) unsigned NOT NULL,
`reserved` tinyint(3) unsigned NOT NULL,
`reserved_at` int(10) unsigned DEFAULT NULL,
`available_at` int(10) unsigned NOT NULL,
`created_at` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
```
## 创建任务类
> 单模块项目推荐使用 `app\job` 作为任务类的命名空间
> 多模块项目可用使用 `app\module\job` 作为任务类的命名空间
> 也可以放在任意可以自动加载到的地方
任务类不需继承任何类,如果这个类只有一个任务,那么就只需要提供一个`fire`方法就可以了,如果有多个小任务,就写多个方法,下面发布任务的时候会有区别
每个方法会传入两个参数 `think\queue\Job $job`(当前的任务对象) 和 `$data`(发布任务时自定义的数据)
还有个可选的任务失败执行的方法 `failed` 传入的参数为`$data`(发布任务时自定义的数据)
### 下面写两个例子
```
namespace app\job;
use think\queue\Job;
class Job1{
public function fire(Job $job, $data){
//....这里执行具体的任务
if ($job->attempts() > 3) {
//通过这个方法可以检查这个任务已经重试了几次了
}
//如果任务执行成功后 记得删除任务,不然这个任务会重复执行,直到达到最大重试次数后失败后,执行failed方法
$job->delete();
// 也可以重新发布这个任务
$job->release($delay); //$delay为延迟时间
}
public function failed($data){
// ...任务达到最大重试次数后,失败了
}
}
```
```
namespace app\lib\job;
use think\queue\Job;
class Job2{
public function task1(Job $job, $data){
}
public function task2(Job $job, $data){
}
public function failed($data){
}
}
```
## 发布任务
> `think\Queue::push($job, $data = '', $queue = null)` 和 `think\Queue::later($delay, $job, $data = '', $queue = null)` 两个方法,前者是立即执行,后者是在`$delay`秒后执行
`$job` 是任务名
单模块的,且命名空间是`app\job`的,比如上面的例子一,写`Job1`类名即可
多模块的,且命名空间是`app\module\job`的,写`model/Job1`即可
其他的需要些完整的类名,比如上面的例子二,需要写完整的类名`app\lib\job\Job2`
如果一个任务类里有多个小任务的话,如上面的例子二,需要用@+方法名`app\lib\job\Job2@task1`、`app\lib\job\Job2@task2`
`$data` 是你要传到任务里的参数
`$queue` 队列名,指定这个任务是在哪个队列上执行,同下面监控队列的时候指定的队列名,可不填
## 监听任务并执行
> php think queue:listen
> php think queue:work --daemon(不加--daemon为执行单个任务)
两种,具体的可选参数可以输入命令加 --help 查看
>可配合supervisor使用,保证进程常驻
... ...
{
"name": "topthink/think-queue",
"description": "The ThinkPHP5 Queue Package",
"type": "think-extend",
"authors": [
{
"name": "yunwuxin",
"email": "448901948@qq.com"
}
],
"license": "Apache-2.0",
"autoload": {
"psr-4": {
"think\\": "src"
},
"files": [
"src/common.php"
]
},
"require": {
"topthink/think-helper": ">=1.0.4",
"topthink/think-installer": ">=1.0.10"
},
"require-dev": {
"topthink/framework": "~5.0.0"
},
"extra": {
"think-config": {
"queue": "src/config.php"
}
}
}
... ...
<?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;
use think\helper\Str;
use think\queue\Connector;
/**
* Class Queue
* @package think\queue
*
* @method static push($job, $data = '', $queue = null)
* @method static later($delay, $job, $data = '', $queue = null)
* @method static pop($queue = null)
* @method static marshal()
*/
class Queue
{
/** @var Connector */
protected static $connector;
private static function buildConnector()
{
$options = Config::get('queue');
$type = !empty($options['connector']) ? $options['connector'] : 'Sync';
if (!isset(self::$connector)) {
$class = false !== strpos($type, '\\') ? $type : '\\think\\queue\\connector\\' . Str::studly($type);
self::$connector = new $class($options);
}
return self::$connector;
}
public static function __callStatic($name, $arguments)
{
return call_user_func_array([self::buildConnector(), $name], $arguments);
}
}
... ...
<?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>
// +----------------------------------------------------------------------
\think\Console::addDefaultCommands([
"think\\queue\\command\\Work",
"think\\queue\\command\\Restart",
"think\\queue\\command\\Listen",
"think\\queue\\command\\Subscribe"
]);
if (!function_exists('queue')) {
/**
* 添加到队列
* @param $job
* @param string $data
* @param int $delay
* @param null $queue
*/
function queue($job, $data = '', $delay = 0, $queue = null)
{
if ($delay > 0) {
\think\Queue::later($delay, $job, $data, $queue);
} else {
\think\Queue::push($job, $data, $queue);
}
}
}
... ...
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
return [
'connector' => 'Sync'
];
... ...
<?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\queue;
class CallQueuedHandler
{
public function call(Job $job, array $data)
{
$command = unserialize($data['command']);
call_user_func([$command, 'handle']);
if (!$job->isDeletedOrReleased()) {
$job->delete();
}
}
public function failed(array $data)
{
$command = unserialize($data['command']);
if (method_exists($command, 'failed')) {
$command->failed();
}
}
}
... ...
<?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\queue;
use InvalidArgumentException;
abstract class Connector
{
protected $options = [];
abstract public function push($job, $data = '', $queue = null);
abstract public function later($delay, $job, $data = '', $queue = null);
abstract public function pop($queue = null);
public function marshal()
{
throw new \RuntimeException('pop queues not support for this type');
}
protected function createPayload($job, $data = '', $queue = null)
{
if (is_object($job)) {
$payload = json_encode([
'job' => 'think\queue\CallQueuedHandler@call',
'data' => [
'commandName' => get_class($job),
'command' => serialize(clone $job),
],
]);
} else {
$payload = json_encode($this->createPlainPayload($job, $data));
}
if (JSON_ERROR_NONE !== json_last_error()) {
throw new InvalidArgumentException('Unable to create payload: ' . json_last_error_msg());
}
return $payload;
}
protected function createPlainPayload($job, $data)
{
return ['job' => $job, 'data' => $data];
}
protected function setMeta($payload, $key, $value)
{
$payload = json_decode($payload, true);
$payload[$key] = $value;
$payload = json_encode($payload);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new InvalidArgumentException('Unable to create payload: ' . json_last_error_msg());
}
return $payload;
}
}
... ...
<?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\queue;
use DateTime;
use think\App;
abstract class Job
{
/**
* The job handler instance.
* @var mixed
*/
protected $instance;
/**
* The name of the queue the job belongs to.
* @var string
*/
protected $queue;
/**
* Indicates if the job has been deleted.
* @var bool
*/
protected $deleted = false;
/**
* Indicates if the job has been released.
* @var bool
*/
protected $released = false;
/**
* Fire the job.
* @return void
*/
abstract public function fire();
/**
* Delete the job from the queue.
* @return void
*/
public function delete()
{
$this->deleted = true;
}
/**
* Determine if the job has been deleted.
* @return bool
*/
public function isDeleted()
{
return $this->deleted;
}
/**
* Release the job back into the queue.
* @param int $delay
* @return void
*/
public function release($delay = 0)
{
$this->released = true;
}
/**
* Determine if the job was released back into the queue.
* @return bool
*/
public function isReleased()
{
return $this->released;
}
/**
* Determine if the job has been deleted or released.
* @return bool
*/
public function isDeletedOrReleased()
{
return $this->isDeleted() || $this->isReleased();
}
/**
* Get the number of times the job has been attempted.
* @return int
*/
abstract public function attempts();
/**
* Get the raw body string for the job.
* @return string
*/
abstract public function getRawBody();
/**
* Resolve and fire the job handler method.
* @param array $payload
* @return void
*/
protected function resolveAndFire(array $payload)
{
list($class, $method) = $this->parseJob($payload['job']);
$this->instance = $this->resolve($class);
if ($this->instance) {
$this->instance->{$method}($this, $payload['data']);
}
}
/**
* Parse the job declaration into class and method.
* @param string $job
* @return array
*/
protected function parseJob($job)
{
$segments = explode('@', $job);
return count($segments) > 1 ? $segments : [$segments[0], 'fire'];
}
/**
* Resolve the given job handler.
* @param string $name
* @return mixed
*/
protected function resolve($name)
{
if (strpos($name, '\\') === false) {
if (strpos($name, '/') === false) {
$module = '';
} else {
list($module, $name) = explode('/', $name, 2);
}
$name = App::$namespace . ($module ? '\\' . strtolower($module) : '') . '\\job\\' . $name;
}
if (class_exists($name)) {
return new $name();
}
}
/**
* Call the failed method on the job instance.
* @return void
*/
public function failed()
{
$payload = json_decode($this->getRawBody(), true);
list($class, $method) = $this->parseJob($payload['job']);
$this->instance = $this->resolve($class);
if ($this->instance && method_exists($this->instance, 'failed')) {
$this->instance->failed($payload['data']);
}
}
/**
* Calculate the number of seconds with the given delay.
* @param \DateTime|int $delay
* @return int
*/
protected function getSeconds($delay)
{
if ($delay instanceof DateTime) {
return max(0, $delay->getTimestamp() - $this->getTime());
}
return (int) $delay;
}
/**
* Get the current system time.
* @return int
*/
protected function getTime()
{
return time();
}
/**
* Get the name of the queued job class.
* @return string
*/
public function getName()
{
return json_decode($this->getRawBody(), true)['job'];
}
/**
* Get the name of the queue the job belongs to.
* @return string
*/
public function getQueue()
{
return $this->queue;
}
}
... ...
<?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\queue;
use Closure;
use think\Process;
class Listener
{
/**
* @var string
*/
protected $commandPath;
/**
* @var int
*/
protected $sleep = 3;
/**
* @var int
*/
protected $maxTries = 0;
/**
* @var string
*/
protected $workerCommand;
/**
* @var \Closure|null
*/
protected $outputHandler;
/**
* @param string $commandPath
*/
public function __construct($commandPath)
{
$this->commandPath = $commandPath;
$this->workerCommand =
'"' . PHP_BINARY . '" think queue:work --queue="%s" --delay=%s --memory=%s --sleep=%s --tries=%s';
}
/**
* @param string $queue
* @param string $delay
* @param string $memory
* @param int $timeout
* @return void
*/
public function listen($queue, $delay, $memory, $timeout = 60)
{
$process = $this->makeProcess($queue, $delay, $memory, $timeout);
while (true) {
$this->runProcess($process, $memory);
}
}
/**
* @param \Think\Process $process
* @param int $memory
*/
public function runProcess(Process $process, $memory)
{
$process->run(function ($type, $line) {
$this->handleWorkerOutput($type, $line);
});
if ($this->memoryExceeded($memory)) {
$this->stop();
}
}
/**
* @param string $queue
* @param int $delay
* @param int $memory
* @param int $timeout
* @return \think\Process
*/
public function makeProcess($queue, $delay, $memory, $timeout)
{
$string = $this->workerCommand;
$command = sprintf($string, $queue, $delay, $memory, $this->sleep, $this->maxTries);
return new Process($command, $this->commandPath, null, null, $timeout);
}
/**
* @param int $type
* @param string $line
* @return void
*/
protected function handleWorkerOutput($type, $line)
{
if (isset($this->outputHandler)) {
call_user_func($this->outputHandler, $type, $line);
}
}
/**
* @param int $memoryLimit
* @return bool
*/
public function memoryExceeded($memoryLimit)
{
return (memory_get_usage() / 1024 / 1024) >= $memoryLimit;
}
/**
* @return void
*/
public function stop()
{
die;
}
/**
* @param \Closure $outputHandler
* @return void
*/
public function setOutputHandler(Closure $outputHandler)
{
$this->outputHandler = $outputHandler;
}
/**
* @return int
*/
public function getSleep()
{
return $this->sleep;
}
/**
* @param int $sleep
* @return void
*/
public function setSleep($sleep)
{
$this->sleep = $sleep;
}
/**
* @param int $tries
* @return void
*/
public function setMaxTries($tries)
{
$this->maxTries = $tries;
}
}
... ...
<?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\queue;
trait Queueable
{
/** @var string 队列名称 */
public $queue;
/** @var integer 延迟时间 */
public $delay;
/**
* 设置队列名
* @param $queue
* @return $this
*/
public function queue($queue)
{
$this->queue = $queue;
return $this;
}
/**
* 设置延迟时间
* @param $delay
* @return $this
*/
public function delay($delay)
{
$this->delay = $delay;
return $this;
}
}
... ...
<?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\queue;
interface ShouldQueue
{
}
... ...
<?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\queue;
use Exception;
use think\Hook;
use think\Queue;
class Worker
{
/**
* 执行下个任务
* @param string $queue
* @param int $delay
* @param int $sleep
* @param int $maxTries
* @return array
*/
public function pop($queue = null, $delay = 0, $sleep = 3, $maxTries = 0)
{
$job = $this->getNextJob($queue);
if (!is_null($job)) {
Hook::listen('worker_before_process', $queue);
return $this->process($job, $maxTries, $delay);
}
Hook::listen('worker_before_sleep', $queue);
$this->sleep($sleep);
return ['job' => null, 'failed' => false];
}
/**
* 获取下个任务
* @param string $queue
* @return Job
*/
protected function getNextJob($queue)
{
if (is_null($queue)) {
return Queue::pop();
}
foreach (explode(',', $queue) as $queue) {
if (!is_null($job = Queue::pop($queue))) {
return $job;
}
}
}
/**
* Process a given job from the queue.
* @param \think\queue\Job $job
* @param int $maxTries
* @param int $delay
* @return array
* @throws Exception
*/
public function process(Job $job, $maxTries = 0, $delay = 0)
{
if ($maxTries > 0 && $job->attempts() > $maxTries) {
return $this->logFailedJob($job);
}
try {
$job->fire();
return ['job' => $job, 'failed' => false];
} catch (Exception $e) {
if (!$job->isDeleted()) {
$job->release($delay);
}
throw $e;
}
}
/**
* Log a failed job into storage.
* @param \Think\Queue\Job $job
* @return array
*/
protected function logFailedJob(Job $job)
{
if (!$job->isDeleted()) {
try {
$job->delete();
$job->failed();
} finally {
Hook::listen('queue_failed', $job);
}
}
return ['job' => $job, 'failed' => true];
}
/**
* Sleep the script for a given number of seconds.
* @param int $seconds
* @return void
*/
public function sleep($seconds)
{
sleep($seconds);
}
}
... ...
<?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\queue\command;
use think\console\Command;
use think\console\Input;
use think\console\input\Option;
use think\console\Output;
use think\queue\Listener;
class Listen extends Command
{
/** @var Listener */
protected $listener;
public function configure()
{
$this->setName('queue:listen')
->addOption('queue', null, Option::VALUE_OPTIONAL, 'The queue to listen on', null)
->addOption('delay', null, Option::VALUE_OPTIONAL, 'Amount of time to delay failed jobs', 0)
->addOption('memory', null, Option::VALUE_OPTIONAL, 'The memory limit in megabytes', 128)
->addOption('timeout', null, Option::VALUE_OPTIONAL, 'Seconds a job may run before timing out', 60)
->addOption('sleep', null, Option::VALUE_OPTIONAL, 'Seconds to wait before checking queue for jobs', 3)
->addOption('tries', null, Option::VALUE_OPTIONAL, 'Number of times to attempt a job before logging it failed', 0)
->setDescription('Listen to a given queue');
}
public function initialize(Input $input, Output $output)
{
$this->listener = new Listener($this->findCommandPath());
$this->listener->setSleep($input->getOption('sleep'));
$this->listener->setMaxTries($input->getOption('tries'));
$this->listener->setOutputHandler(function ($type, $line) use ($output) {
$output->write($line);
});
}
public function execute(Input $input, Output $output)
{
$delay = $input->getOption('delay');
$memory = $input->getOption('memory');
$timeout = $input->getOption('timeout');
$queue = $input->getOption('queue') ?: 'default';
$this->listener->listen($queue, $delay, $memory, $timeout);
}
protected function findCommandPath()
{
return defined('ROOT_PATH') ? ROOT_PATH : dirname($_SERVER['argv'][0]);
}
}
... ...
<?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\queue\command;
use think\Cache;
use think\console\Command;
use think\console\Input;
use think\console\Output;
class Restart extends Command
{
public function configure()
{
$this->setName('queue:restart')->setDescription('Restart queue worker daemons after their current job');
}
public function execute(Input $input, Output $output)
{
Cache::set('think:queue:restart', time());
$output->writeln("<info>Broadcasting queue restart signal.</info>");
}
}
... ...
<?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\queue\command;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\Queue;
use think\Url;
class Subscribe extends Command
{
public function configure()
{
$this->setName('queue:subscribe')
->setDescription('Subscribe a URL to an push queue')
->addArgument('name', Argument::REQUIRED, 'name')
->addArgument('url', Argument::REQUIRED, 'The URL to be subscribed.')
->addArgument('queue', Argument::OPTIONAL, 'The URL to be subscribed.')
->addOption('option', null, Option::VALUE_IS_ARRAY | Option::VALUE_OPTIONAL, 'the options');
}
public function execute(Input $input, Output $output)
{
$url = $input->getArgument('url');
if (!preg_match('/^https?:\/\//', $url)) {
$url = Url::build($url);
}
Queue::subscribe($input->getArgument('name'), $url, $input->getArgument('queue'), $input->getOption('option'));
$output->write('<info>Queue subscriber added:</info> <comment>' . $input->getArgument('url') . '</comment>');
}
}
... ...
<?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\queue\command;
use think\Config;
use think\console\Command;
use think\console\Input;
use think\console\input\Option;
use think\console\Output;
use think\Hook;
use think\queue\Job;
use think\queue\Worker;
use Exception;
use Throwable;
use think\Cache;
use think\exception\Handle;
use think\exception\ThrowableError;
class Work extends Command
{
/**
* The queue worker instance.
* @var \think\queue\Worker
*/
protected $worker;
protected function initialize(Input $input, Output $output)
{
$this->worker = new Worker();
}
protected function configure()
{
$this->setName('queue:work')
->addOption('queue', null, Option::VALUE_OPTIONAL, 'The queue to listen on')
->addOption('daemon', null, Option::VALUE_NONE, 'Run the worker in daemon mode')
->addOption('delay', null, Option::VALUE_OPTIONAL, 'Amount of time to delay failed jobs', 0)
->addOption('force', null, Option::VALUE_NONE, 'Force the worker to run even in maintenance mode')
->addOption('memory', null, Option::VALUE_OPTIONAL, 'The memory limit in megabytes', 128)
->addOption('sleep', null, Option::VALUE_OPTIONAL, 'Number of seconds to sleep when no job is available', 3)
->addOption('tries', null, Option::VALUE_OPTIONAL, 'Number of times to attempt a job before logging it failed', 0)
->setDescription('Process the next job on a queue');
}
/**
* Execute the console command.
* @param Input $input
* @param Output $output
* @return int|null|void
*/
public function execute(Input $input, Output $output)
{
$queue = $input->getOption('queue');
$delay = $input->getOption('delay');
$memory = $input->getOption('memory');
if ($input->getOption('daemon')) {
Hook::listen('worker_daemon_start', $queue);
$this->daemon(
$queue, $delay, $memory,
$input->getOption('sleep'), $input->getOption('tries')
);
} else {
$response = $this->worker->pop($queue, $delay, $input->getOption('sleep'), $input->getOption('tries'));
$this->output($response);
}
}
protected function output($response)
{
if (!is_null($response['job'])) {
/** @var Job $job */
$job = $response['job'];
if ($response['failed']) {
$this->output->writeln('<error>Failed:</error> ' . $job->getName());
} else {
$this->output->writeln('<info>Processed:</info> ' . $job->getName());
}
}
}
/**
* 启动一个守护进程执行任务.
*
* @param string $queue
* @param int $delay
* @param int $memory
* @param int $sleep
* @param int $maxTries
* @return array
*/
protected function daemon($queue = null, $delay = 0, $memory = 128, $sleep = 3, $maxTries = 0)
{
$lastRestart = $this->getTimestampOfLastQueueRestart();
while (true) {
$this->runNextJobForDaemon(
$queue, $delay, $sleep, $maxTries
);
if ( $this->memoryExceeded($memory) ) {
Hook::listen('worker_memory_exceeded', $queue);
$this->stop();
}
if ( $this->queueShouldRestart($lastRestart) ) {
Hook::listen('worker_queue_restart', $queue);
$this->stop();
}
}
}
/**
* 以守护进程的方式执行下个任务.
*
* @param string $queue
* @param int $delay
* @param int $sleep
* @param int $maxTries
* @return void
*/
protected function runNextJobForDaemon($queue, $delay, $sleep, $maxTries)
{
try {
$response = $this->worker->pop($queue, $delay, $sleep, $maxTries);
$this->output($response);
} catch (Exception $e) {
$this->getExceptionHandler()->report($e);
} catch (Throwable $e) {
$this->getExceptionHandler()->report(new ThrowableError($e));
}
}
/**
* 获取上次重启守护进程的时间
*
* @return int|null
*/
protected function getTimestampOfLastQueueRestart()
{
return Cache::get('think:queue:restart');
}
/**
* 检查是否要重启守护进程
*
* @param int|null $lastRestart
* @return bool
*/
protected function queueShouldRestart($lastRestart)
{
return $this->getTimestampOfLastQueueRestart() != $lastRestart;
}
/**
* 检查内存是否超出
* @param int $memoryLimit
* @return bool
*/
protected function memoryExceeded($memoryLimit)
{
return (memory_get_usage() / 1024 / 1024) >= $memoryLimit;
}
/**
* 获取异常处理实例
*
* @return \think\exception\Handle
*/
protected function getExceptionHandler()
{
static $handle;
if (!$handle) {
if ($class = Config::get('exception_handle')) {
if (class_exists($class) && is_subclass_of($class, "\\think\\exception\\Handle")) {
$handle = new $class;
}
}
if (!$handle) {
$handle = new Handle();
}
}
return $handle;
}
/**
* 停止执行任务的守护进程.
* @return void
*/
public function stop()
{
die;
}
}
... ...