Files
kiri-core/Database/Pagination.php
T

207 lines
3.6 KiB
PHP
Raw Normal View History

2020-08-31 12:38:32 +08:00
<?php
2020-10-29 18:17:25 +08:00
declare(strict_types=1);
2020-08-31 12:38:32 +08:00
namespace Database;
use Snowflake\Abstracts\Component;
use Closure;
use Exception;
2020-09-18 17:19:05 +08:00
use Snowflake\Event;
2020-09-14 10:58:40 +08:00
use Snowflake\Snowflake;
use Swoole\Coroutine;
2020-08-31 12:38:32 +08:00
/**
* Class Pagination
* @package Database
*/
class Pagination extends Component
{
/** @var ActiveQuery */
2020-10-29 18:17:25 +08:00
private ActiveQuery $activeQuery;
2020-08-31 12:38:32 +08:00
/** @var int 从第几个开始查 */
2020-10-29 18:17:25 +08:00
private int $_offset = 0;
2020-08-31 12:38:32 +08:00
/** @var int 每页数量 */
2020-10-29 18:17:25 +08:00
private int $_limit = 100;
2020-08-31 12:38:32 +08:00
/** @var int 最大查询数量 */
2020-10-29 18:17:25 +08:00
private int $_max = 0;
2020-08-31 12:38:32 +08:00
/** @var int 当前已查询数量 */
2020-10-29 18:17:25 +08:00
private int $_length = 0;
2020-08-31 12:38:32 +08:00
/** @var Closure */
2020-10-29 18:17:25 +08:00
private Closure $_callback;
2020-09-14 11:05:49 +08:00
2020-09-18 16:18:23 +08:00
/** @var Coroutine\WaitGroup */
2020-10-29 18:17:25 +08:00
private Coroutine\WaitGroup $_group;
2020-09-18 16:18:23 +08:00
2020-08-31 12:38:32 +08:00
/**
* PaginationIteration constructor.
* @param ActiveQuery $activeQuery
* @param array $config
*/
public function __construct(ActiveQuery $activeQuery, array $config = [])
{
parent::__construct($config);
$this->activeQuery = $activeQuery;
}
/**
2020-12-17 14:09:14 +08:00
* @param array|Closure $callback
2020-08-31 12:38:32 +08:00
* @throws Exception
*/
2020-12-17 14:09:14 +08:00
public function setCallback(array|Closure $callback)
2020-08-31 12:38:32 +08:00
{
if (!is_callable($callback, true)) {
throw new Exception('非法回调函数~');
}
$this->_callback = $callback;
}
/**
* @param int $number
2020-09-14 10:44:45 +08:00
* @return Pagination
2020-08-31 12:38:32 +08:00
*/
2020-12-17 14:09:14 +08:00
public function setOffset(int $number): static
2020-08-31 12:38:32 +08:00
{
if ($number < 0) {
$number = 0;
}
$this->_offset = $number;
2020-09-14 10:44:45 +08:00
return $this;
2020-08-31 12:38:32 +08:00
}
/**
* @param int $number
2020-09-14 10:44:45 +08:00
* @return Pagination
2020-08-31 12:38:32 +08:00
*/
2020-12-17 14:09:14 +08:00
public function setLimit(int $number): static
2020-08-31 12:38:32 +08:00
{
if ($number < 1) {
$number = 100;
} else if ($number > 5000) {
$number = 5000;
}
$this->_limit = $number;
2020-09-14 10:44:45 +08:00
return $this;
2020-08-31 12:38:32 +08:00
}
/**
* @param int $number
2020-12-17 14:09:14 +08:00
* @return Pagination
2020-08-31 12:38:32 +08:00
*/
2020-12-17 14:09:14 +08:00
public function setMax(int $number): static
2020-08-31 12:38:32 +08:00
{
if ($number < 0) {
2020-09-14 10:44:45 +08:00
return $this;
2020-08-31 12:38:32 +08:00
}
$this->_max = $number;
2020-09-14 10:44:45 +08:00
return $this;
2020-08-31 12:38:32 +08:00
}
/**
* @param array $param
2020-09-18 16:18:23 +08:00
* @return void
2020-08-31 12:38:32 +08:00
*/
2020-09-14 10:43:02 +08:00
public function plunk($param = [])
2020-09-18 16:18:23 +08:00
{
$this->_group = new Coroutine\WaitGroup();
2020-09-18 16:55:09 +08:00
Coroutine::create([$this, 'loop'], $param);
2020-09-18 16:18:23 +08:00
$this->_group->wait();
}
/**
* 轮训
* @param $param
* @return array
*/
2020-12-17 14:09:14 +08:00
public function loop($param): array
2020-08-31 12:38:32 +08:00
{
2020-09-14 10:53:11 +08:00
if ($this->_max > 0 && $this->_length >= $this->_max) {
2020-09-14 11:05:49 +08:00
return $this->output();
2020-08-31 12:38:32 +08:00
}
2020-09-14 10:43:02 +08:00
[$length, $data] = $this->get();
2020-09-14 10:58:40 +08:00
$this->runner($data, $param);
2020-08-31 12:38:32 +08:00
unset($data);
if ($length < $this->_limit) {
2020-09-14 11:05:49 +08:00
return $this->output();
2020-08-31 12:38:32 +08:00
}
2020-09-18 16:18:23 +08:00
return $this->loop($param);
2020-09-14 11:05:49 +08:00
}
/**
* @return array
*/
2020-12-17 14:09:14 +08:00
public function output(): array
2020-09-14 11:05:49 +08:00
{
return [];
2020-08-31 12:38:32 +08:00
}
2020-09-14 10:58:40 +08:00
/**
* @param $data
* @param $param
*/
private function runner($data, $param)
{
if (Snowflake::inCoroutine()) {
2020-09-18 16:18:23 +08:00
$this->executed($this->_callback, $data, $param);
2020-09-14 10:58:40 +08:00
} else {
2020-09-14 10:59:07 +08:00
call_user_func($this->_callback, $data, $param);
2020-09-14 10:58:40 +08:00
}
}
2020-09-18 16:18:23 +08:00
/**
* @param $callback
* @param $data
* @param $param
* 解释器
2020-09-18 16:55:26 +08:00
* @return mixed
2020-09-18 16:18:23 +08:00
*/
2020-12-17 14:09:14 +08:00
private function executed($callback, $data, $param): mixed
2020-09-18 16:18:23 +08:00
{
$this->_group->add(1);
2020-09-18 17:27:08 +08:00
return Coroutine::create(function ($callback, $data, $param): void {
2020-09-18 17:19:05 +08:00
try {
call_user_func($callback, $data, $param);
} catch (\Throwable $exception) {
2021-02-20 15:45:48 +08:00
$this->addError($exception);
2020-09-18 17:19:05 +08:00
} finally {
$event = Snowflake::app()->getEvent();
2021-02-20 15:21:42 +08:00
$event->trigger(Event::SYSTEM_RESOURCE_RELEASES);
2020-09-18 17:27:08 +08:00
$this->_group->done();
2020-09-18 17:19:05 +08:00
}
}, $callback, $data, $param);
2020-09-18 16:18:23 +08:00
}
2020-08-31 12:38:32 +08:00
/**
* @return array|Collection
*/
2020-12-17 14:09:14 +08:00
private function get(): Collection|array
2020-08-31 12:38:32 +08:00
{
if ($this->_length + $this->_limit > $this->_max) {
$this->_limit = $this->_length + $this->_limit - $this->_max;
}
$data = $this->activeQuery->limit($this->_offset, $this->_limit)->get();
$this->_offset += $this->_limit;
$this->_length += $data->size();
return [$data->size(), $data];
}
}