作者 邓超

优化数据库,mysql链接

@@ -115,7 +115,7 @@ class SendJob { @@ -115,7 +115,7 @@ class SendJob {
115 // 查询邮箱 115 // 查询邮箱
116 $email = db()->first(\Model\emailSql::first($data['email_id'])); 116 $email = db()->first(\Model\emailSql::first($data['email_id']));
117 // 更新状态 117 // 更新状态
118 - $upStatus = \Model\sendJobsSql::upStatus($data['id'],1,db()); 118 + $upStatus = \Model\sendJobsSql::upStatus($data['id'],1);
119 _echo('更新任务状态 '.$data['id'].' ==> '.$upStatus); 119 _echo('更新任务状态 '.$data['id'].' ==> '.$upStatus);
120 // 是否是单发送 120 // 是否是单发送
121 if($data['maildata']['massSuit']??0){ 121 if($data['maildata']['massSuit']??0){
@@ -225,12 +225,9 @@ class SendJob { @@ -225,12 +225,9 @@ class SendJob {
225 // 写入日志 225 // 写入日志
226 \Lib\Log::getInstance()->write(); 226 \Lib\Log::getInstance()->write();
227 227
228 - // 结束后要关闭数据库链接,不然链接一直暂用  
229 - db()->close();  
230 // 删除占用 228 // 删除占用
231 redis()->delete('send_job_run_id_'.$data['id']); 229 redis()->delete('send_job_run_id_'.$data['id']);
232 230
233 - redis()->close();  
234 231
235 _echo('执行任务完成'.$data['id']); 232 _echo('执行任务完成'.$data['id']);
236 233
@@ -111,11 +111,6 @@ function start(){ @@ -111,11 +111,6 @@ function start(){
111 // 写入日志 111 // 写入日志
112 \Lib\Log::getInstance()->write(); 112 \Lib\Log::getInstance()->write();
113 113
114 - // 关闭数据库链接  
115 - db()->close();  
116 - // 关闭redis链接  
117 - redis()->close();  
118 -  
119 }); 114 });
120 115
121 }); 116 });
@@ -189,10 +184,6 @@ function start(){ @@ -189,10 +184,6 @@ function start(){
189 // 写入日志 184 // 写入日志
190 \Lib\Log::getInstance()->write(); 185 \Lib\Log::getInstance()->write();
191 186
192 - // 关闭数据库链接  
193 - db()->close();  
194 - // 关闭redis链接  
195 - redis()->close();  
196 187
197 }); 188 });
198 189
@@ -14,34 +14,42 @@ function posix_pid(){ @@ -14,34 +14,42 @@ function posix_pid(){
14 return $pid ? $pid : 0; 14 return $pid ? $pid : 0;
15 } 15 }
16 16
  17 +
17 /** 18 /**
18 * redis 驱动 19 * redis 驱动
19 - * @return \Lib\RedisPool 20 + * @return \Lib\RedisPool|\Lib\Redis
20 * @author:dc 21 * @author:dc
21 * @time 2023/2/13 9:44 22 * @time 2023/2/13 9:44
22 */ 23 */
23 -function redis():\Lib\RedisPool { 24 +function redis():\Lib\RedisPool|\Lib\Redis {
  25 +
  26 + if(co::getCid()){
  27 + return new \Lib\RedisPool();
  28 + }
24 29
25 - return \Lib\RedisPool::instance(posix_pid().'_'.co::getCid()); 30 + return \Lib\Redis::instance();
26 31
27 } 32 }
28 33
29 34
30 /** 35 /**
31 * 操作db 36 * 操作db
32 - * @return \Lib\DbPool 37 + * @return \Lib\Db|\Lib\DbPool
33 * @author:dc 38 * @author:dc
34 * @time 2023/2/13 14:15 39 * @time 2023/2/13 14:15
35 */ 40 */
36 -function db():\Lib\DbPool{  
37 -  
38 - return \Lib\DbPool::instance(posix_pid().'_'.co::getCid()); 41 +function db():\Lib\Db|\Lib\DbPool{
  42 + // 池子
  43 + if(co::getCid()){
  44 + return new \Lib\DbPool();
  45 + }
  46 + // 非池子
  47 + return \Lib\Db::instance();
39 } 48 }
40 49
41 50
42 51
43 52
44 -  
45 /** 53 /**
46 * 记录日志 54 * 记录日志
47 * @param $message 55 * @param $message
  1 +<?php
  2 +
  3 +namespace Lib;
  4 +
  5 +/**
  6 + * db
  7 + * @author:dc
  8 + * @time 2023/2/13 15:03
  9 + * Class Db
  10 + * @package Lib
  11 + */
  12 +class Db {
  13 +
  14 + use DbQuery;
  15 +
  16 + /**
  17 + * @var \Lib\Db
  18 + */
  19 + static $instance;
  20 +
  21 +
  22 + /**
  23 + * @return mixed
  24 + * @author:dc
  25 + * @time 2023/2/13 9:12
  26 + */
  27 + public function getClient(){
  28 + if(!$this->client){
  29 + $this->connect();
  30 + }
  31 +
  32 + try {
  33 + // 判断是否链接中
  34 + if($this->client->getAttribute(\PDO::ATTR_CONNECTION_STATUS)===false){
  35 + $this->connect();
  36 + }
  37 + }catch (\Throwable $e){
  38 + $this->connect();
  39 + }
  40 +
  41 + return $this->client;
  42 + }
  43 +
  44 +
  45 + public function __construct()
  46 + {
  47 +
  48 + $this->connect();
  49 +
  50 + }
  51 +
  52 + /**
  53 + * 连接sql
  54 + * @author:dc
  55 + * @time 2023/3/23 9:14
  56 + */
  57 + public function connect(){
  58 +
  59 + $tryNum = 0;
  60 +
  61 + DBPOOLCONNECTFOR:
  62 + try {
  63 + $this->client = new \PDO(
  64 + 'mysql:charset=utf8mb4;dbname='.DB_DATABASE.';host='.DB_HOST.';port='.DB_PORT,
  65 + DB_USER,
  66 + DB_PASSWORD,
  67 + [
  68 + \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
  69 + \PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8mb4'",
  70 + \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
  71 + ]
  72 + );
  73 + }catch (\Throwable $e){
  74 + // 重新链接3次
  75 + if($tryNum < 3){
  76 + $tryNum++;
  77 + goto DBPOOLCONNECTFOR;
  78 + }
  79 +
  80 + logs($e->getMessage().$e->getTraceAsString());
  81 + }
  82 +
  83 +
  84 +
  85 + }
  86 +
  87 +
  88 +
  89 +
  90 + /**
  91 + * @return Db
  92 + * @author:dc
  93 + * @time 2023/2/13 9:39
  94 + */
  95 + public static function instance(){
  96 + if(empty(static::$instance)){
  97 + static::$instance = new Db();
  98 + }
  99 +
  100 + if(!static::$instance->ping()){
  101 + static::$instance->close();
  102 +
  103 + static::$instance = new Db();
  104 + }
  105 +
  106 + return static::$instance;
  107 + }
  108 +
  109 +
  110 + /**
  111 + * 结束
  112 + */
  113 + public function __destruct(){
  114 + $this->close();
  115 + }
  116 +
  117 +
  118 + public function close(){
  119 + $this->client = null;
  120 + }
  121 +
  122 +
  123 +
  124 +}
@@ -2,6 +2,9 @@ @@ -2,6 +2,9 @@
2 2
3 namespace Lib; 3 namespace Lib;
4 4
  5 +use Swoole\Database\PDOConfig;
  6 +use Swoole\Database\PDOPool;
  7 +
5 /** 8 /**
6 * db 池 9 * db 池
7 * @author:dc 10 * @author:dc
@@ -11,384 +14,43 @@ namespace Lib; @@ -11,384 +14,43 @@ namespace Lib;
11 */ 14 */
12 class DbPool { 15 class DbPool {
13 16
14 - /**  
15 - * @var \Lib\DbPool[]  
16 - */  
17 - static $instance = [];  
18 - 17 + use DbQuery;
19 18
20 /** 19 /**
21 - * @var \PDO 20 + * @var \Swoole\Database\PDOPool
22 */ 21 */
23 - private $client; 22 + static $pool = null;
24 23
25 - /**  
26 - * @var  
27 - */  
28 - private $cid;  
29 -  
30 - public $lastTimer;  
31 24
32 /** 25 /**
33 - * @return mixed  
34 - * @author:dc  
35 - * @time 2023/2/13 9:12 26 + * 实例
  27 + * DbPool constructor.
36 */ 28 */
37 - public function getClient(){  
38 - if(!$this->client){  
39 - $this->connect();  
40 - }  
41 -  
42 - try {  
43 - // 判断是否链接中  
44 - if($this->client->getAttribute(\PDO::ATTR_CONNECTION_STATUS)===false){  
45 - $this->connect();  
46 - }  
47 - }catch (\Throwable $e){  
48 - $this->connect();  
49 - }  
50 -  
51 - $this->lastTimer = time();  
52 - return $this->client;  
53 - }  
54 -  
55 -  
56 - public function __construct($cid) 29 + public function __construct()
57 { 30 {
58 - $this->cid = $cid;  
59 31
60 - $this->connect();  
61 -  
62 - }  
63 -  
64 - /**  
65 - * 连接sql  
66 - * @author:dc  
67 - * @time 2023/3/23 9:14  
68 - */  
69 - public function connect(){  
70 - $this->lastTimer = time();  
71 - $tryNum = 0;  
72 -  
73 - DBPOOLCONNECTFOR:  
74 - try {  
75 - $this->client = new \PDO(  
76 - 'mysql:charset=utf8mb4;dbname='.DB_DATABASE.';host='.DB_HOST.';port='.DB_PORT,  
77 - DB_USER,  
78 - DB_PASSWORD,  
79 - [ 32 + if(!static::$pool){
  33 + $pdoconfig = (new PDOConfig)
  34 + ->withHost(DB_HOST)
  35 + ->withPort(DB_PORT)
  36 + ->withDbName(DB_DATABASE)
  37 + ->withCharset('utf8mb4')
  38 + ->withUsername(DB_USER)
  39 + ->withPassword(DB_PASSWORD)
  40 + ->withOptions([
80 \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC, 41 \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
81 \PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8mb4'", 42 \PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8mb4'",
82 \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, 43 \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
83 - ]  
84 - );  
85 - }catch (\Throwable $e){  
86 - // 重新链接3次  
87 - if($tryNum < 3){  
88 - $tryNum++;  
89 - goto DBPOOLCONNECTFOR;  
90 - }  
91 -  
92 - logs($e->getMessage().$e->getTraceAsString());  
93 - }  
94 -  
95 -  
96 -  
97 - }  
98 -  
99 -  
100 - /**  
101 - * 查询  
102 - * @param string|array $sql  
103 - * @return false|\PDOStatement  
104 - * @author:dc  
105 - * @time 2023/2/17 10:01  
106 - */  
107 - private function query(string|array $sql){  
108 - if(is_array($sql)){  
109 - list($sql,$params) = $sql;  
110 - }else{  
111 - $params = null;  
112 - }  
113 -  
114 - if(APP_DEBUG) {  
115 - $timer = microtime(true);  
116 - }  
117 -  
118 -  
119 - try {  
120 - $query = $this->getClient()->prepare($sql);  
121 - $ret = $query->execute($params);  
122 - }catch (\Throwable $e){  
123 - logs([  
124 - $sql,$params,  
125 - $e->getMessage(),  
126 - $e->getTraceAsString()  
127 - ],  
128 - LOG_PATH.'/'.date('Y-m-d').'-sql.error.log'  
129 - );  
130 - $ret = false;  
131 - }  
132 -  
133 -  
134 - if(APP_DEBUG){  
135 - $timer2 = microtime(true);  
136 -  
137 - // todo:: 记录日志,生产请注释  
138 - $sql = '['.substr(($timer2-$timer)*1000,0,6).'ms] '.$sql;  
139 - logs(  
140 - $params ? [$sql,$params] : $sql,  
141 - LOG_PATH.'/'.date('Y-m-d').'.sql.log'  
142 - );  
143 - }  
144 -  
145 - if($ret){  
146 - return $query;  
147 - }  
148 -  
149 - return false;  
150 - }  
151 -  
152 -  
153 - /**  
154 - * 更新数据  
155 - * @param string $table  
156 - * @param array $data  
157 - * @param string $where  
158 - * @param bool $timeauto  
159 - * @return int  
160 - * @author:dc  
161 - * @time 2023/2/17 14:03  
162 - */  
163 - public function update(string $table, array $data, string $where, $timeauto = true):int {  
164 -  
165 - if($timeauto){  
166 - $data['updated_at'] = empty($data['updated_at']) ? date('Y-m-d H:i:s') : $data['updated_at'];  
167 - }  
168 -  
169 - $sql = "update `{$table}` set ".dbUpdate($data). " where ".$where;  
170 -  
171 - $data = $this->getData($data);  
172 -  
173 - $query = $this->query([$sql,$data]);  
174 - if($query){  
175 - return $query->rowCount();  
176 - }  
177 - return 0;  
178 - }  
179 -  
180 -  
181 - /**  
182 - * 在更新/插入时处理数据  
183 - * @param $data  
184 - * @return mixed  
185 - * @author:dc  
186 - * @time 2023/2/18 14:50  
187 - */  
188 - private function getData($data){  
189 - // 如果存储的值是数组,就json一次  
190 - foreach ($data as $k=>$datum){  
191 - if(is_array($datum)){  
192 - $data[$k] = json_encode($datum,JSON_UNESCAPED_UNICODE);  
193 - }elseif ($datum === null){  
194 - $data[$k] = '';  
195 - }  
196 - }  
197 - return $data;  
198 - }  
199 -  
200 -  
201 - /**  
202 - * 插入数据  
203 - * @param string $table  
204 - * @param array $data  
205 - * @param bool $timeauto  
206 - * @return int  
207 - * @author:dc  
208 - * @time 2023/2/17 14:04  
209 - */  
210 - public function insert(string $table, array $data, $timeauto = true):int {  
211 -  
212 - if($timeauto){  
213 - $data['created_at'] = empty($data['created_at']) ? date('Y-m-d H:i:s') : $data['created_at'];  
214 - }  
215 -  
216 - $sql = "insert into `{$table}` set ".dbUpdate($data);  
217 -  
218 - $data = $this->getData($data);  
219 -  
220 - $query = $this->query([$sql,$data]);  
221 -  
222 - if($query){  
223 - return $this->getClient()->lastInsertId();  
224 - } 44 + ]);
225 45
226 - return 0; 46 + static::$pool = new PDOPool($pdoconfig,1024);
227 } 47 }
228 48
229 - /**  
230 - * 删除语句 软删  
231 - * @param string $table  
232 - * @param array $where  
233 - * @param null $upFiled  
234 - * @return int  
235 - * @author:dc  
236 - * @time 2023/4/11 14:47  
237 - */  
238 - public function delete(string $table, array $where,$upFiled=null){ 49 + // 获取链接
  50 + $this->client = static::$pool->get();
239 51
240 - if($upFiled){  
241 - return $this->update($table,[$upFiled === true ? 'deleted_at' : $upFiled =>time()],$where);  
242 } 52 }
243 53
244 - $sql = "delete from `{$table}` where ".dbUpdate($where);  
245 -  
246 - $query = $this->query([$sql,$where]);  
247 -  
248 - if($query){  
249 - return $query->rowCount();  
250 - }  
251 -  
252 - return 0;  
253 - }  
254 -  
255 -  
256 - /**  
257 - * 统计数量  
258 - * @param string $sql  
259 - * @return int  
260 - * @author:dc  
261 - * @time 2023/2/14 16:19  
262 - */  
263 - public function count(string|array $sql):int{  
264 - $query = $this->query($sql);  
265 - if($query){  
266 - return $query->fetch(\PDO::FETCH_COLUMN);  
267 - }  
268 - return 0;  
269 - }  
270 -  
271 - /**  
272 - * 某个值  
273 - * @param string|array $sql  
274 - * @return mixed|null  
275 - * @author:dc  
276 - * @time 2023/2/17 11:03  
277 - */  
278 - public function value(string|array $sql){  
279 - $query = $this->query($sql);  
280 - if($query){  
281 - return $query->fetch(\PDO::FETCH_COLUMN);  
282 - }  
283 - return null;  
284 - }  
285 -  
286 -  
287 - /**  
288 - * 查询一条数据  
289 - * @param string|array $sql  
290 - * @return mixed|null  
291 - * @author:dc  
292 - * @time 2023/2/13 14:54  
293 - */  
294 - public function first(string|array $sql){  
295 -  
296 - $query = $this->query($sql);  
297 -  
298 - if($query){  
299 - return $query->fetch();  
300 - }  
301 -  
302 - return null;  
303 - }  
304 -  
305 - /**  
306 - * 查询列表  
307 - * @param string|array $sql  
308 - * @return mixed|null  
309 - * @author:dc  
310 - * @time 2023/2/13 14:54  
311 - */  
312 - public function all(string|array $sql){  
313 -  
314 - $query = $this->query($sql);  
315 -  
316 - if($query){  
317 - return $query->fetchAll();  
318 - }  
319 -  
320 - return null;  
321 - }  
322 -  
323 -  
324 - /**  
325 - * 事务开启  
326 - * @author:dc  
327 - * @time 2023/2/17 11:35  
328 - */  
329 - public function transaction(){  
330 - $this->getClient()->beginTransaction();  
331 - }  
332 -  
333 - /**  
334 - * 事务回滚  
335 - * @author:dc  
336 - * @time 2023/2/17 11:35  
337 - */  
338 - public function rollBack(){  
339 - $this->getClient()->rollBack();  
340 - }  
341 -  
342 - /**  
343 - * 事务提交  
344 - * @author:dc  
345 - * @time 2023/2/17 11:35  
346 - */  
347 - public function commit(){  
348 - $this->getClient()->commit();  
349 - }  
350 -  
351 -  
352 - /**  
353 - * 验证是否正常连接  
354 - * @return bool  
355 - * @author:dc  
356 - * @time 2024/4/10 10:09  
357 - */  
358 - public function ping(){  
359 - try {  
360 - $query = $this->getClient()->query("select 200;");  
361 - if($query->fetchColumn() == 200){  
362 - return true;  
363 - }  
364 - }catch (\Throwable $e){  
365 - return false;  
366 - }  
367 -  
368 - return false;  
369 - }  
370 -  
371 -  
372 -  
373 - /**  
374 - * @param $cid  
375 - * @return DbPool  
376 - * @author:dc  
377 - * @time 2023/2/13 9:39  
378 - */  
379 - public static function instance($cid=0){  
380 - if(empty(static::$instance[$cid])){  
381 - static::$instance[$cid] = new DbPool($cid);  
382 - }  
383 -  
384 - if(!static::$instance[$cid]->ping()){  
385 - static::$instance[$cid]->close();  
386 -  
387 - static::$instance[$cid] = new DbPool($cid);  
388 - }  
389 -  
390 - return static::$instance[$cid];  
391 - }  
392 54
393 55
394 /** 56 /**
@@ -398,10 +60,14 @@ class DbPool { @@ -398,10 +60,14 @@ class DbPool {
398 $this->close(); 60 $this->close();
399 } 61 }
400 62
401 - 63 + /**
  64 + * 关闭链接
  65 + * @author:dc
  66 + * @time 2024/5/30 10:30
  67 + */
402 public function close(){ 68 public function close(){
  69 + self::$pool->put($this->client);
403 $this->client = null; 70 $this->client = null;
404 - unset(static::$instance[$this->cid]);  
405 } 71 }
406 72
407 73
  1 +<?php
  2 +
  3 +namespace Lib;
  4 +
  5 +/**
  6 + * db 查询
  7 + * @author:dc
  8 + * @time 2023/2/13 15:03
  9 + * Class DbPool
  10 + * @package Lib
  11 + */
  12 +trait DbQuery {
  13 +
  14 + /**
  15 + * @var \PDO|null
  16 + */
  17 + protected $client;
  18 +
  19 +
  20 + public function getClient()
  21 + {
  22 + return $this->client;
  23 + }
  24 +
  25 +
  26 + /**
  27 + * 查询
  28 + * @param string|array $sql
  29 + * @return false|\PDOStatement
  30 + * @author:dc
  31 + * @time 2023/2/17 10:01
  32 + */
  33 + public function query(string|array $sql){
  34 + if(is_array($sql)){
  35 + list($sql,$params) = $sql;
  36 + }else{
  37 + $params = null;
  38 + }
  39 +
  40 + if(APP_DEBUG) {
  41 + $timer = microtime(true);
  42 + }
  43 +
  44 +
  45 + try {
  46 + $query = $this->getClient()->prepare($sql);
  47 + $ret = $query->execute($params);
  48 + }catch (\Throwable $e){
  49 + logs([
  50 + $sql,$params,
  51 + $e->getMessage(),
  52 + $e->getTraceAsString()
  53 + ],
  54 + LOG_PATH.'/'.date('Y-m-d').'-sql.error.log'
  55 + );
  56 + $ret = false;
  57 + }
  58 +
  59 +
  60 + if(APP_DEBUG){
  61 + $timer2 = microtime(true);
  62 +
  63 + // todo:: 记录日志,生产请注释
  64 + $sql = '['.substr(($timer2-$timer)*1000,0,6).'ms] '.$sql;
  65 + logs(
  66 + $params ? [$sql,$params] : $sql,
  67 + LOG_PATH.'/'.date('Y-m-d').'.sql.log'
  68 + );
  69 + }
  70 +
  71 + if($ret){
  72 + return $query;
  73 + }
  74 +
  75 + return false;
  76 + }
  77 +
  78 +
  79 + /**
  80 + * 更新数据
  81 + * @param string $table
  82 + * @param array $data
  83 + * @param string $where
  84 + * @param bool $timeauto
  85 + * @return int
  86 + * @author:dc
  87 + * @time 2023/2/17 14:03
  88 + */
  89 + public function update(string $table, array $data, string $where, $timeauto = true):int {
  90 +
  91 + if($timeauto){
  92 + $data['updated_at'] = empty($data['updated_at']) ? date('Y-m-d H:i:s') : $data['updated_at'];
  93 + }
  94 +
  95 + $sql = "update `{$table}` set ".dbUpdate($data). " where ".$where;
  96 +
  97 + $data = $this->getData($data);
  98 +
  99 + $query = $this->query([$sql,$data]);
  100 + if($query){
  101 + return $query->rowCount();
  102 + }
  103 + return 0;
  104 + }
  105 +
  106 +
  107 + /**
  108 + * 在更新/插入时处理数据
  109 + * @param $data
  110 + * @return mixed
  111 + * @author:dc
  112 + * @time 2023/2/18 14:50
  113 + */
  114 + public function getData($data){
  115 + // 如果存储的值是数组,就json一次
  116 + foreach ($data as $k=>$datum){
  117 + if(is_array($datum)){
  118 + $data[$k] = json_encode($datum,JSON_UNESCAPED_UNICODE);
  119 + }elseif ($datum === null){
  120 + $data[$k] = '';
  121 + }
  122 + }
  123 + return $data;
  124 + }
  125 +
  126 +
  127 + /**
  128 + * 插入数据
  129 + * @param string $table
  130 + * @param array $data
  131 + * @param bool $timeauto
  132 + * @return int
  133 + * @author:dc
  134 + * @time 2023/2/17 14:04
  135 + */
  136 + public function insert(string $table, array $data, $timeauto = true):int {
  137 +
  138 + if($timeauto){
  139 + $data['created_at'] = empty($data['created_at']) ? date('Y-m-d H:i:s') : $data['created_at'];
  140 + }
  141 +
  142 + $sql = "insert into `{$table}` set ".dbUpdate($data);
  143 +
  144 + $data = $this->getData($data);
  145 +
  146 + $query = $this->query([$sql,$data]);
  147 +
  148 + if($query){
  149 + return $this->getClient()->lastInsertId();
  150 + }
  151 +
  152 + return 0;
  153 + }
  154 +
  155 + /**
  156 + * 删除语句 软删
  157 + * @param string $table
  158 + * @param array $where
  159 + * @param null $upFiled
  160 + * @return int
  161 + * @author:dc
  162 + * @time 2023/4/11 14:47
  163 + */
  164 + public function delete(string $table, array $where,$upFiled=null){
  165 +
  166 + if($upFiled){
  167 + return $this->update($table,[$upFiled === true ? 'deleted_at' : $upFiled =>time()],$where);
  168 + }
  169 +
  170 + $sql = "delete from `{$table}` where ".dbUpdate($where);
  171 +
  172 + $query = $this->query([$sql,$where]);
  173 +
  174 + if($query){
  175 + return $query->rowCount();
  176 + }
  177 +
  178 + return 0;
  179 + }
  180 +
  181 +
  182 + /**
  183 + * 统计数量
  184 + * @param string $sql
  185 + * @return int
  186 + * @author:dc
  187 + * @time 2023/2/14 16:19
  188 + */
  189 + public function count(string|array $sql):int{
  190 + $query = $this->query($sql);
  191 + if($query){
  192 + return $query->fetch(\PDO::FETCH_COLUMN);
  193 + }
  194 + return 0;
  195 + }
  196 +
  197 + /**
  198 + * 某个值
  199 + * @param string|array $sql
  200 + * @return mixed|null
  201 + * @author:dc
  202 + * @time 2023/2/17 11:03
  203 + */
  204 + public function value(string|array $sql){
  205 + $query = $this->query($sql);
  206 + if($query){
  207 + return $query->fetch(\PDO::FETCH_COLUMN);
  208 + }
  209 + return null;
  210 + }
  211 +
  212 +
  213 + /**
  214 + * 查询一条数据
  215 + * @param string|array $sql
  216 + * @return mixed|null
  217 + * @author:dc
  218 + * @time 2023/2/13 14:54
  219 + */
  220 + public function first(string|array $sql){
  221 +
  222 + $query = $this->query($sql);
  223 +
  224 + if($query){
  225 + return $query->fetch();
  226 + }
  227 +
  228 + return null;
  229 + }
  230 +
  231 + /**
  232 + * 查询列表
  233 + * @param string|array $sql
  234 + * @return mixed|null
  235 + * @author:dc
  236 + * @time 2023/2/13 14:54
  237 + */
  238 + public function all(string|array $sql){
  239 +
  240 + $query = $this->query($sql);
  241 +
  242 + if($query){
  243 + return $query->fetchAll();
  244 + }
  245 +
  246 + return null;
  247 + }
  248 +
  249 +
  250 + /**
  251 + * 事务开启
  252 + * @author:dc
  253 + * @time 2023/2/17 11:35
  254 + */
  255 + public function transaction(){
  256 + $this->getClient()->beginTransaction();
  257 + }
  258 +
  259 + /**
  260 + * 事务回滚
  261 + * @author:dc
  262 + * @time 2023/2/17 11:35
  263 + */
  264 + public function rollBack(){
  265 + $this->getClient()->rollBack();
  266 + }
  267 +
  268 + /**
  269 + * 事务提交
  270 + * @author:dc
  271 + * @time 2023/2/17 11:35
  272 + */
  273 + public function commit(){
  274 + $this->getClient()->commit();
  275 + }
  276 +
  277 +
  278 + /**
  279 + * 验证是否正常连接
  280 + * @return bool
  281 + * @author:dc
  282 + * @time 2024/4/10 10:09
  283 + */
  284 + public function ping(){
  285 + try {
  286 + $query = $this->getClient()->query("select 200;");
  287 + if($query->fetchColumn() == 200){
  288 + return true;
  289 + }
  290 + }catch (\Throwable $e){
  291 + return false;
  292 + }
  293 +
  294 + return false;
  295 + }
  296 +
  297 +
  298 +}
  1 +<?php
  2 +
  3 +namespace Lib;
  4 +
  5 +/**
  6 + * redis 链接池 swoole内置了链接池,自能在协程中使用,所以单独写出来
  7 + * @author:dc
  8 + * @time 2023/2/10 17:04
  9 + * Class Redis
  10 + */
  11 +class Redis {
  12 +
  13 + use RedisQuery;
  14 +
  15 + /**
  16 + * @var \Lib\Redis
  17 + */
  18 + static $instance;
  19 +
  20 + /**
  21 + * Redis constructor.
  22 + */
  23 + public function __construct()
  24 + {
  25 + if(!$this->conn()){
  26 + $this->conn();
  27 + }
  28 + }
  29 +
  30 + /**
  31 + * @return \Redis
  32 + * @author:dc
  33 + * @time 2023/4/12 15:11
  34 + */
  35 + public function getClient(){
  36 + try {
  37 + if(!$this->client->ping()){
  38 + $this->conn();
  39 + }
  40 + }catch (\Throwable $e){
  41 + $this->conn();
  42 + }
  43 +
  44 + return $this->client;
  45 + }
  46 +
  47 +
  48 + /**
  49 + * 链接
  50 + * @author:dc
  51 + * @time 2023/4/12 15:10
  52 + */
  53 + private function conn(){
  54 +
  55 + $this->client = new \Redis();
  56 +
  57 + if($this->client->pconnect(REDIS_HOST,REDIS_PORT,2)){
  58 + // 密码
  59 + REDIS_PASSWORD && $this->client->auth(REDIS_PASSWORD);
  60 + // 用库4
  61 + $this->client->select(REDIS_DB);
  62 +
  63 + return true;
  64 + }
  65 +
  66 + return false;
  67 +
  68 + }
  69 +
  70 +
  71 +
  72 +
  73 + /**
  74 + *
  75 + */
  76 + public function __destruct()
  77 + {
  78 + $this->close();
  79 + }
  80 +
  81 +
  82 + /**
  83 + * @return \Lib\Redis
  84 + * @author:dc
  85 + * @time 2023/2/13 9:38
  86 + */
  87 + public static function instance(){
  88 +
  89 + if(empty(static::$instance)){
  90 + static::$instance = new \Lib\Redis();
  91 + }
  92 + try {
  93 + static::$instance->client->ping();
  94 + }catch (\Throwable $e){
  95 + static::$instance->close();
  96 +
  97 + static::$instance = new \Lib\Redis();
  98 + }
  99 +
  100 + return static::$instance;
  101 + }
  102 +
  103 +
  104 + /**
  105 + * 关闭
  106 + * @author:dc
  107 + * @time 2023/3/16 13:42
  108 + */
  109 + public function close(){
  110 + // TODO: Implement __destruct() method.
  111 + try {
  112 + $this->client->ping();
  113 + $this->client->close();
  114 + }catch (\Throwable $e){
  115 +
  116 + }
  117 +
  118 + $this->client = null;
  119 +
  120 + }
  121 +
  122 +
  123 +
  124 +
  125 +
  126 +
  127 +
  128 +}
@@ -2,291 +2,46 @@ @@ -2,291 +2,46 @@
2 2
3 namespace Lib; 3 namespace Lib;
4 4
  5 +use Swoole\Database\RedisConfig;
  6 +
5 /** 7 /**
6 - * redis 链接池 swoole内置了链接池,自能在协程中使用,所以单独写出来 8 + * redis 链接池
7 * @author:dc 9 * @author:dc
8 * @time 2023/2/10 17:04 10 * @time 2023/2/10 17:04
9 * Class RedisPool 11 * Class RedisPool
10 */ 12 */
11 class RedisPool { 13 class RedisPool {
12 14
13 - /**  
14 - * @var \Lib\RedisPool[]  
15 - */  
16 - static $instance = [];  
17 -  
18 - /**  
19 - * @var \Redis  
20 - */  
21 - private $client;  
22 -  
23 - /**  
24 - * @var  
25 - */  
26 - private $cid;  
27 -  
28 - /**  
29 - * 最后执行的时间  
30 - * @var int  
31 - */  
32 - public $lastTimer;  
33 -  
34 -  
35 - public function __construct($cid)  
36 - {  
37 - $this->cid = $cid;  
38 - $this->conn();  
39 - }  
40 -  
41 - /**  
42 - * 链接  
43 - * @author:dc  
44 - * @time 2023/4/12 15:10  
45 - */  
46 - private function conn(){  
47 - $this->lastTimer = time();  
48 - $this->client = new \Redis();  
49 -  
50 - $this->client->pconnect(REDIS_HOST,REDIS_PORT,2);  
51 - // 密码  
52 - REDIS_PASSWORD && $this->client->auth(REDIS_PASSWORD);  
53 - // 用库4  
54 - $this->client->select(REDIS_DB);  
55 - }  
56 -  
57 - 15 + use RedisQuery;
58 16
59 /** 17 /**
60 - * @param $key  
61 - * @return bool|int  
62 - * @author:dc  
63 - * @time 2023/2/10 18:06 18 + * @var \Swoole\Database\RedisPool
64 */ 19 */
65 - public function has($key)  
66 - {  
67 - return $this->getClient()->exists($key);  
68 - } 20 + static $pool = null;
69 21
70 22
71 /** 23 /**
72 - * @param $key  
73 - * @param null $default  
74 - * @return mixed|null  
75 - * @author:dc  
76 - * @time 2023/2/10 18:04 24 + * RedisPool constructor.
77 */ 25 */
78 - public function get($key, $default=null) 26 + public function __construct()
79 { 27 {
80 - $data = $this->getClient()->get($key);  
81 - if($data === null){  
82 - return $default;  
83 - }  
84 - return $this->unserialize($data);  
85 - }  
86 -  
87 - /**  
88 - * 获取原数据  
89 - * @param $key  
90 - * @return false|mixed|string  
91 - * @author:dc  
92 - * @time 2023/4/12 16:51  
93 - */  
94 - public function getOriginData($key){  
95 - return $this->getClient()->get($key);  
96 - }  
97 -  
98 - /**  
99 - * @param $key  
100 - * @param $val  
101 - * @param null $ttl  
102 - * @return bool  
103 - * @author:dc  
104 - * @time 2023/2/10 18:02  
105 - */  
106 - public function set($key,$val,$ttl=null) {  
107 - return $this->getClient()->set($key,$this->serialize($val),$ttl);  
108 - }  
109 -  
110 -  
111 - /**  
112 - * 如果有key返回false,没有则新增  
113 - * @param $key  
114 - * @param $val  
115 - * @param null $ttl  
116 - * @return mixed  
117 - * @author:dc  
118 - * @time 2023/2/10 17:53  
119 - */  
120 - public function add($key,$val,$ttl=null):mixed {  
121 - return $this->getClient()->eval(  
122 - "return redis.call('exists',KEYS[1])<1 and redis.call('setex',KEYS[1],ARGV[2],ARGV[1])",  
123 - [$key, $this->serialize($val), $ttl],  
124 - 1 28 + if(empty(static::$pool)){
  29 +
  30 + static::$pool = new \Swoole\Database\RedisPool((new RedisConfig)
  31 + ->withHost(REDIS_HOST)
  32 + ->withPort(REDIS_PORT)
  33 + ->withAuth(REDIS_PASSWORD)
  34 + ->withDbIndex(REDIS_DB)
  35 + ->withTimeout(1)
  36 + ,1024
125 ); 37 );
126 - }  
127 38
128 - /**  
129 - * @param $key  
130 - * @param $value  
131 - * @return false|int  
132 - * @author:dc  
133 - * @time 2023/2/13 9:07  
134 - */  
135 - public function lPush($key,$value){  
136 - return $this->getClient()->lPush($key,$this->serialize($value));  
137 } 39 }
138 40
139 - /**  
140 - * @param $key  
141 - * @param $value  
142 - * @return false|int  
143 - * @author:dc  
144 - * @time 2023/2/13 9:07  
145 - */  
146 - public function rPush($key,$value){  
147 - return $this->getClient()->rPush($key,$this->serialize($value)); 41 + // 获取一个连接,放入当前实例
  42 + $this->client = static::$pool->get();
148 } 43 }
149 44
150 - /**  
151 - * @param $key  
152 - * @return bool|mixed  
153 - * @author:dc  
154 - * @time 2023/2/13 9:08  
155 - */  
156 - public function lPop($key){  
157 - return $this->unserialize($this->getClient()->lPop($key));  
158 - }  
159 -  
160 - /**  
161 - * @param $key  
162 - * @return mixed|string  
163 - * @author:dc  
164 - * @time 2023/2/13 9:09  
165 - */  
166 - public function rPop($key){  
167 - return $this->unserialize($this->getClient()->rPop($key));  
168 - }  
169 -  
170 - /**  
171 - * 自增  
172 - * @param $key  
173 - * @param null $ttl  
174 - * @return int  
175 - * @author:dc  
176 - * @time 2023/2/17 15:29  
177 - */  
178 - public function incr($key, $ttl = null){  
179 - if($ttl){  
180 - return $this->getClient()->eval(  
181 - "  
182 -if redis.call('exists',KEYS[1]) == 0 then  
183 - local x = redis.call('incr',KEYS[1])  
184 - if x then  
185 - redis.call('expire',KEYS[1],ARGV[1])  
186 - end  
187 - return x  
188 -else  
189 - return redis.call('incr',KEYS[1])  
190 -end",  
191 - [$key, $ttl],  
192 - 1  
193 - );  
194 - }  
195 - return $this->getClient()->incr($key);  
196 - }  
197 -  
198 - /**  
199 - * 自减  
200 - * @param $key  
201 - * @param null $ttl  
202 - * @return int  
203 - * @author:dc  
204 - * @time 2023/3/16 11:19  
205 - */  
206 - public function decr($key,$ttl = null){  
207 - if($ttl){  
208 - return $this->getClient()->eval(  
209 - "  
210 -if redis.call('exists',KEYS[1]) == 0 then  
211 - local x = redis.call('decr',KEYS[1])  
212 - if x then  
213 - redis.call('expire',KEYS[1],ARGV[1])  
214 - end  
215 - return x  
216 -else  
217 - return redis.call('decr',KEYS[1])  
218 -end",  
219 - [$key, $ttl],  
220 - 1  
221 - );  
222 - }  
223 - return $this->getClient()->decr($key);  
224 - }  
225 -  
226 -  
227 - /**  
228 - * 删除  
229 - * @param $key  
230 - * @return int  
231 - * @author:dc  
232 - * @time 2023/2/14 14:04  
233 - */  
234 - public function delete(...$key):int {  
235 - return $this->getClient()->del(...$key);  
236 - }  
237 -  
238 - /**  
239 - * 获取值并删除  
240 - * @param $key  
241 - * @return mixed  
242 - * @author:dc  
243 - * @time 2023/3/16 11:36  
244 - */  
245 - public function getDel($key){  
246 - return $this->getClient()->eval(  
247 - "local x = redis.call('get',KEYS[1]);if x then redis.call('del',KEYS[1]) end return x",  
248 - [$key],  
249 - 1  
250 - );  
251 - }  
252 -  
253 -  
254 - /**  
255 - * @param $val  
256 - * @return string  
257 - * @author:dc  
258 - * @time 2023/2/10 17:57  
259 - */  
260 - private function serialize($val){  
261 - return $val ? serialize($val) : '';  
262 - }  
263 -  
264 - /**  
265 - * @param $val  
266 - * @return mixed  
267 - * @author:dc  
268 - * @time 2023/2/10 17:58  
269 - */  
270 - private function unserialize($val){  
271 - return $val ? unserialize($val) : '';  
272 - }  
273 -  
274 - /**  
275 - * @return \Redis  
276 - * @author:dc  
277 - * @time 2023/4/12 15:11  
278 - */  
279 - public function getClient(){  
280 - try {  
281 - if(!$this->client->ping()){  
282 - $this->conn();  
283 - }  
284 - }catch (\Throwable $e){  
285 - $this->conn();  
286 - }  
287 - $this->lastTimer = time();  
288 - return $this->client;  
289 - }  
290 45
291 46
292 47
@@ -297,43 +52,14 @@ end", @@ -297,43 +52,14 @@ end",
297 52
298 53
299 /** 54 /**
300 - * @param $cid  
301 - * @return \Lib\RedisPool  
302 - * @author:dc  
303 - * @time 2023/2/13 9:38  
304 - */  
305 - public static function instance($cid){  
306 -  
307 - if(empty(static::$instance[$cid])){  
308 - static::$instance[$cid] = new \Lib\RedisPool($cid);  
309 - }  
310 - try {  
311 - static::$instance[$cid]->client->ping();  
312 - }catch (\Throwable $e){  
313 - static::$instance[$cid]->close();  
314 -  
315 - static::$instance[$cid] = new \Lib\RedisPool($cid);  
316 - }  
317 -  
318 - return static::$instance[$cid];  
319 - }  
320 -  
321 -  
322 - /**  
323 * 关闭 55 * 关闭
324 * @author:dc 56 * @author:dc
325 * @time 2023/3/16 13:42 57 * @time 2023/3/16 13:42
326 */ 58 */
327 public function close(){ 59 public function close(){
328 - // TODO: Implement __destruct() method.  
329 - try {  
330 - $this->client->ping();  
331 - $this->client->close();  
332 - }catch (\Throwable $e){  
333 60
334 - } 61 + self::$pool->put($this->client);
335 62
336 - unset(static::$instance[$this->cid]);  
337 $this->client = null; 63 $this->client = null;
338 64
339 } 65 }
  1 +<?php
  2 +
  3 +namespace Lib;
  4 +
  5 +/**
  6 + * redis 的操作
  7 + * @author:dc
  8 + * @time 2024/5/30 10:50
  9 + * Class RedisQuery
  10 + * @package Lib
  11 + */
  12 +trait RedisQuery {
  13 +
  14 +
  15 + /**
  16 + * @var \Redis
  17 + */
  18 + protected $client;
  19 +
  20 +
  21 +
  22 + /**
  23 + * @param $key
  24 + * @return bool|int
  25 + * @author:dc
  26 + * @time 2023/2/10 18:06
  27 + */
  28 + public function has($key)
  29 + {
  30 + return $this->getClient()->exists($key);
  31 + }
  32 +
  33 +
  34 + /**
  35 + * @param $key
  36 + * @param null $default
  37 + * @return mixed|null
  38 + * @author:dc
  39 + * @time 2023/2/10 18:04
  40 + */
  41 + public function get($key, $default=null)
  42 + {
  43 + $data = $this->getClient()->get($key);
  44 + if($data === null){
  45 + return $default;
  46 + }
  47 + return $this->unserialize($data);
  48 + }
  49 +
  50 + /**
  51 + * 获取原数据
  52 + * @param $key
  53 + * @return false|mixed|string
  54 + * @author:dc
  55 + * @time 2023/4/12 16:51
  56 + */
  57 + public function getOriginData($key){
  58 + return $this->getClient()->get($key);
  59 + }
  60 +
  61 + /**
  62 + * @param $key
  63 + * @param $val
  64 + * @param null $ttl
  65 + * @return bool
  66 + * @author:dc
  67 + * @time 2023/2/10 18:02
  68 + */
  69 + public function set($key,$val,$ttl=null) {
  70 + return $this->getClient()->set($key,$this->serialize($val),$ttl);
  71 + }
  72 +
  73 +
  74 + /**
  75 + * 如果有key返回false,没有则新增
  76 + * @param $key
  77 + * @param $val
  78 + * @param null $ttl
  79 + * @return mixed
  80 + * @author:dc
  81 + * @time 2023/2/10 17:53
  82 + */
  83 + public function add($key,$val,$ttl=null):mixed {
  84 + return $this->getClient()->eval(
  85 + "return redis.call('exists',KEYS[1])<1 and redis.call('setex',KEYS[1],ARGV[2],ARGV[1])",
  86 + [$key, $this->serialize($val), $ttl],
  87 + 1
  88 + );
  89 + }
  90 +
  91 + /**
  92 + * @param $key
  93 + * @param $value
  94 + * @return false|int
  95 + * @author:dc
  96 + * @time 2023/2/13 9:07
  97 + */
  98 + public function lPush($key,$value){
  99 + return $this->getClient()->lPush($key,$this->serialize($value));
  100 + }
  101 +
  102 + /**
  103 + * @param $key
  104 + * @param $value
  105 + * @return false|int
  106 + * @author:dc
  107 + * @time 2023/2/13 9:07
  108 + */
  109 + public function rPush($key,$value){
  110 + return $this->getClient()->rPush($key,$this->serialize($value));
  111 + }
  112 +
  113 + /**
  114 + * @param $key
  115 + * @return bool|mixed
  116 + * @author:dc
  117 + * @time 2023/2/13 9:08
  118 + */
  119 + public function lPop($key){
  120 + return $this->unserialize($this->getClient()->lPop($key));
  121 + }
  122 +
  123 + /**
  124 + * @param $key
  125 + * @return mixed|string
  126 + * @author:dc
  127 + * @time 2023/2/13 9:09
  128 + */
  129 + public function rPop($key){
  130 + return $this->unserialize($this->getClient()->rPop($key));
  131 + }
  132 +
  133 + /**
  134 + * 自增
  135 + * @param $key
  136 + * @param null $ttl
  137 + * @return int
  138 + * @author:dc
  139 + * @time 2023/2/17 15:29
  140 + */
  141 + public function incr($key, $ttl = null){
  142 + if($ttl){
  143 + return $this->getClient()->eval(
  144 + "
  145 +if redis.call('exists',KEYS[1]) == 0 then
  146 + local x = redis.call('incr',KEYS[1])
  147 + if x then
  148 + redis.call('expire',KEYS[1],ARGV[1])
  149 + end
  150 + return x
  151 +else
  152 + return redis.call('incr',KEYS[1])
  153 +end",
  154 + [$key, $ttl],
  155 + 1
  156 + );
  157 + }
  158 + return $this->getClient()->incr($key);
  159 + }
  160 +
  161 + /**
  162 + * 自减
  163 + * @param $key
  164 + * @param null $ttl
  165 + * @return int
  166 + * @author:dc
  167 + * @time 2023/3/16 11:19
  168 + */
  169 + public function decr($key,$ttl = null){
  170 + if($ttl){
  171 + return $this->getClient()->eval(
  172 + "
  173 +if redis.call('exists',KEYS[1]) == 0 then
  174 + local x = redis.call('decr',KEYS[1])
  175 + if x then
  176 + redis.call('expire',KEYS[1],ARGV[1])
  177 + end
  178 + return x
  179 +else
  180 + return redis.call('decr',KEYS[1])
  181 +end",
  182 + [$key, $ttl],
  183 + 1
  184 + );
  185 + }
  186 + return $this->getClient()->decr($key);
  187 + }
  188 +
  189 +
  190 + /**
  191 + * 删除
  192 + * @param $key
  193 + * @return int
  194 + * @author:dc
  195 + * @time 2023/2/14 14:04
  196 + */
  197 + public function delete(...$key):int {
  198 + return $this->getClient()->del(...$key);
  199 + }
  200 +
  201 + /**
  202 + * 获取值并删除
  203 + * @param $key
  204 + * @return mixed
  205 + * @author:dc
  206 + * @time 2023/3/16 11:36
  207 + */
  208 + public function getDel($key){
  209 + return $this->getClient()->eval(
  210 + "local x = redis.call('get',KEYS[1]);if x then redis.call('del',KEYS[1]) end return x",
  211 + [$key],
  212 + 1
  213 + );
  214 + }
  215 +
  216 +
  217 + /**
  218 + * @param $val
  219 + * @return string
  220 + * @author:dc
  221 + * @time 2023/2/10 17:57
  222 + */
  223 + private function serialize($val){
  224 + return $val ? serialize($val) : '';
  225 + }
  226 +
  227 + /**
  228 + * @param $val
  229 + * @return mixed
  230 + * @author:dc
  231 + * @time 2023/2/10 17:58
  232 + */
  233 + private function unserialize($val){
  234 + return $val ? unserialize($val) : '';
  235 + }
  236 +
  237 + /**
  238 + * @return \Redis
  239 + * @author:dc
  240 + * @time 2023/4/12 15:11
  241 + */
  242 + public function getClient(){
  243 + return $this->client;
  244 + }
  245 +
  246 +
  247 +
  248 +}
@@ -74,10 +74,9 @@ class sendJobsSql { @@ -74,10 +74,9 @@ class sendJobsSql {
74 * @author:dc 74 * @author:dc
75 * @time 2023/4/11 16:06 75 * @time 2023/4/11 16:06
76 */ 76 */
77 - public static function upStatus(int $id, int $status, $db=null){  
78 - $db = $db?:db(); 77 + public static function upStatus(int $id, int $status){
79 // 更新状态 78 // 更新状态
80 - return $db->update(\Model\sendJobsSql::$table,[ 79 + return db()->update(\Model\sendJobsSql::$table,[
81 'status' => $status 80 'status' => $status
82 ],dbWhere([ 81 ],dbWhere([
83 'id' => $id 82 'id' => $id
@@ -4,11 +4,14 @@ @@ -4,11 +4,14 @@
4 * 邮件管理 4 * 邮件管理
5 * TODO::此项目是纯数据上的管理,不设计到界面。所以不允许返回任何非 json 类型 的数据/头部 5 * TODO::此项目是纯数据上的管理,不设计到界面。所以不允许返回任何非 json 类型 的数据/头部
6 */ 6 */
  7 +\Co\run(function (){
7 8
8 -require_once "../vendor/autoload.php"; 9 + require_once "../vendor/autoload.php";
9 10
  11 + \Lib\App::run();
  12 +
  13 +});
10 14
11 -\Lib\App::run();  
12 15
13 16
14 17