diff --git a/Database/Collection.php b/Database/Collection.php index 15339d2e..acfe4de1 100644 --- a/Database/Collection.php +++ b/Database/Collection.php @@ -80,7 +80,7 @@ class Collection extends AbstractCollection * * @return array */ - #[Pure] public function slice($start = 0, $length = 20): array + #[Pure] public function slice(int $start = 0, int $length = 20): array { if (empty($this->_item) || !is_array($this->_item)) { return []; @@ -98,7 +98,7 @@ class Collection extends AbstractCollection * * @return array|null */ - public function column($field, $setKey = ''): ?array + public function column(string $field, string $setKey = ''): ?array { $data = $this->toArray(); if (empty($data)) { @@ -112,11 +112,11 @@ class Collection extends AbstractCollection } /** - * @param $field + * @param string $field * * @return float|int|null */ - public function sum($field): float|int|null + public function sum(string $field): float|int|null { $array = $this->column($field); if (empty($array)) { @@ -173,7 +173,7 @@ class Collection extends AbstractCollection $ids[] = $id; } } - return $model::find()->in($model->getPrimary(), $ids)->delete(); + return $model::find()->whereIn($model->getPrimary(), $ids)->delete(); } /** diff --git a/Database/Traits/HasBase.php b/Database/Traits/HasBase.php index 935adcb6..cad3c092 100644 --- a/Database/Traits/HasBase.php +++ b/Database/Traits/HasBase.php @@ -56,7 +56,7 @@ abstract class HasBase } if (is_array($value)) { if (empty($value)) $value = []; - $_model = $model::find()->in($primaryId, $value); + $_model = $model::find()->whereIn($primaryId, $value); } else { $_model = $model::find()->where(['t1.' . $primaryId => $value]); } diff --git a/Gii/GiiController.php b/Gii/GiiController.php index 7fa19be1..430762aa 100644 --- a/Gii/GiiController.php +++ b/Gii/GiiController.php @@ -241,7 +241,7 @@ use {$model_namespace}\\{$managerName}; #[Middleware(middleware: [])] public function actionUpdate(): string { - $model = ' . $className . '::findOne($this->input->post(\'id\', 0)); + $model = ' . $className . '::findOne($this->request->post(\'id\', 0)); if (empty($model)) { return JSON::to(500, SELECT_IS_NULL); } @@ -278,12 +278,12 @@ use {$model_namespace}\\{$managerName}; #[Middleware(middleware: [])] public function actionBatchDelete(): string { - $_key = $this->input->array(\'ids\'); + $_key = $this->request->array(\'ids\'); if (empty($_key)) { return JSON::to(500, PARAMS_IS_NULL); } - $model = ' . $className . '::find()->in(\'id\', $_key); + $model = ' . $className . '::find()->whereIn(\'id\', $_key); if (!$model->delete()) { return JSON::to(500, DB_ERROR_BUSY); } @@ -315,7 +315,7 @@ use {$model_namespace}\\{$managerName}; #[Middleware(middleware: [])] public function actionDetail(): string { - $model = ' . $managerName . '::findOne($this->input->get(\'id\')); + $model = ' . $managerName . '::findOne($this->request->query(\'id\')); if (empty($model)) { return JSON::to(404, SELECT_IS_NULL); } @@ -347,7 +347,7 @@ use {$model_namespace}\\{$managerName}; #[Middleware(middleware: [])] public function actionDelete(): string { - $_key = $this->input->int(\'id\', true); + $_key = $this->request->int(\'id\', true); $model = ' . $managerName . '::findOne($_key); if (empty($model)) { @@ -386,18 +386,18 @@ use {$model_namespace}\\{$managerName}; public function actionList(): string { //分页处理 - $count = $this->input->get(\'count\', -1); - $order = $this->input->get(\'order\', \'id\'); + $count = $this->request->query(\'count\', -1); + $order = $this->request->query(\'order\', \'id\'); if (!empty($order)) { - $order .= !$this->input->get(\'isDesc\', 0) ? \' asc\' : \' desc\'; + $order .= !$this->request->query(\'isDesc\', 0) ? \' asc\' : \' desc\'; } else { $order = \'id desc\'; } //列表输出 - $model = ' . $managerName . '::find()->where($this->input->gets())->orderBy($order); + $model = ' . $managerName . '::find()->where($this->request->gets())->orderBy($order); - $keyword = $this->input->get(\'keyword\', null); + $keyword = $this->request->query(\'keyword\', null); if (!empty($keyword)) { $model->like(\'keyword\', $keyword); } @@ -406,7 +406,7 @@ use {$model_namespace}\\{$managerName}; $count = $model->count(); } if ($count != -100) { - $model->limit($this->input->offset() ,$this->input->size()); + $model->limit($this->request->offset() ,$this->request->size()); } $data = $model->all()->toArray(); @@ -439,9 +439,9 @@ use {$model_namespace}\\{$managerName}; if ($type == 'date' || $type == 'datetime' || $type == 'time') { $_tps = match ($type) { - 'date' => '$this->input->' . $_key . '(\'' . $val['Field'] . '\', date(\'Y-m-d\'))', - 'time' => '$this->input->' . $_key . '(\'' . $val['Field'] . '\', date(\'H:i:s\'))', - default => '$this->input->' . $_key . '(\'' . $val['Field'] . '\', date(\'Y-m-d H:i:s\'))', + 'date' => '$this->request->' . $_key . '(\'' . $val['Field'] . '\', date(\'Y-m-d\'))', + 'time' => '$this->request->' . $_key . '(\'' . $val['Field'] . '\', date(\'H:i:s\'))', + default => '$this->request->' . $_key . '(\'' . $val['Field'] . '\', date(\'Y-m-d H:i:s\'))', }; $html .= ' \'' . str_pad($val['Field'] . '\'', $length, ' ', STR_PAD_RIGHT) . ' => ' . str_pad($_tps . ',', 60, ' ', STR_PAD_RIGHT) . $comment; @@ -459,21 +459,21 @@ use {$model_namespace}\\{$managerName}; } } if ($key == 'string') { - $_tps = '$this->input->' . $_key . '(\'' . $val['Field'] . '\', ' . $_field['required'] . ', ' . $tmp . ')'; + $_tps = '$this->request->' . $_key . '(\'' . $val['Field'] . '\', ' . $_field['required'] . ', ' . $tmp . ')'; } else if ($type == 'int') { if ($number[0] == 10) { - $_tps = '$this->input->' . $_key . '(\'' . $val['Field'] . '\', time())'; + $_tps = '$this->request->' . $_key . '(\'' . $val['Field'] . '\', time())'; } else { - $_tps = '$this->input->' . $_key . '(\'' . $val['Field'] . '\', ' . $_field['required'] . ')'; + $_tps = '$this->request->' . $_key . '(\'' . $val['Field'] . '\', ' . $_field['required'] . ')'; } } else if ($type == 'float') { - $_tps = '$this->input->' . $_key . '(\'' . $val['Field'] . '\', ' . $_field['required'] . ', ' . ($number[3] ?? '2') . ')'; + $_tps = '$this->request->' . $_key . '(\'' . $val['Field'] . '\', ' . $_field['required'] . ', ' . ($number[3] ?? '2') . ')'; } else if ($key == 'email') { - $_tps = '$this->input->' . $_key . '(\'' . $val['Field'] . '\', ' . $_field['required'] . ')'; + $_tps = '$this->request->' . $_key . '(\'' . $val['Field'] . '\', ' . $_field['required'] . ')'; } else if ($key == 'timestamp') { - $_tps = '$this->input->' . $_key . '(\'' . $val['Field'] . '\', time())'; + $_tps = '$this->request->' . $_key . '(\'' . $val['Field'] . '\', time())'; } else { - $_tps = '$this->input->' . $_key . '(\'' . $val['Field'] . '\', ' . $_field['required'] . ')'; + $_tps = '$this->request->' . $_key . '(\'' . $val['Field'] . '\', ' . $_field['required'] . ')'; } $html .= ' \'' . str_pad($val['Field'] . '\'', $length, ' ', STR_PAD_RIGHT) . ' => ' . str_pad($_tps . ',', 60, ' ', STR_PAD_RIGHT) . $comment; @@ -521,14 +521,14 @@ use {$model_namespace}\\{$managerName}; if (!in_array(strtolower($first), $value)) continue; $comment = '//' . $val['Comment']; if ($type == 'date' || $type == 'datetime' || $type == 'time') { - $_tps = '$this->input->get(\'' . $val['Field'] . '\', null)'; + $_tps = '$this->request->query(\'' . $val['Field'] . '\', null)'; $html .= ' $pWhere[\'' . str_pad($val['Field'] . ' <=\']', $length, ' ', STR_PAD_RIGHT) . ' = ' . str_pad($_tps . ';', 60, ' ', STR_PAD_RIGHT) . $comment; $html .= ' $pWhere[\'' . str_pad($val['Field'] . ' >=\']', $length, ' ', STR_PAD_RIGHT) . ' = ' . str_pad($_tps . ';', 60, ' ', STR_PAD_RIGHT) . $comment; } else { - $_tps = '$this->input->get(\'' . $val['Field'] . '\', null)'; + $_tps = '$this->request->query(\'' . $val['Field'] . '\', null)'; $html .= ' $pWhere[\'' . str_pad($val['Field'] . '\']', $length, ' ', STR_PAD_RIGHT) . ' = ' . str_pad($_tps . ';', 60, ' ', STR_PAD_RIGHT) . $comment; } diff --git a/Gii/GiiModel.php b/Gii/GiiModel.php index 5db23fec..4ed87eb4 100644 --- a/Gii/GiiModel.php +++ b/Gii/GiiModel.php @@ -335,7 +335,7 @@ use Database\ActiveRecord; public function getUnique($fields): string { $data = []; - foreach ($fields as $_key => $_val) { + foreach ($fields as $_val) { if ($_val['Extra'] == 'auto_increment') continue; if (str_contains($_val['Type'], 'unique')) { $data[] = $_val['Field']; diff --git a/Gii/GiiRpcService.php b/Gii/GiiRpcService.php index 60eac7ea..32b459f6 100644 --- a/Gii/GiiRpcService.php +++ b/Gii/GiiRpcService.php @@ -26,8 +26,6 @@ class GiiRpcService extends GiiBase throw new Exception('文件名称不能为空~'); } - $service = $this->input->get('service', strtolower($managerName)); - $port = $this->input->get('port', 443); $html = 'data = $context; + return $this; + } + + /** + * @return mixed + */ + public function getData(): mixed + { + $data = $this->data; + $this->clear(); + return $data; + } + + + public function clear(): void + { + $this->data = null; + unset($this->data); + } +} diff --git a/HttpServer/Http/Response.php b/HttpServer/Http/Response.php index 4f60f0fe..5bb92256 100644 --- a/HttpServer/Http/Response.php +++ b/HttpServer/Http/Response.php @@ -11,9 +11,11 @@ namespace HttpServer\Http; use Exception; use HttpServer\Abstracts\HttpService; +use HttpServer\Http\Formatter\FileFormatter; use HttpServer\Http\Formatter\HtmlFormatter; use HttpServer\Http\Formatter\JsonFormatter; use HttpServer\Http\Formatter\XmlFormatter; +use HttpServer\IInterface\IFormatter; use Server\ResponseInterface; use Snowflake\Exception\NotFindClassException; use Swoole\Http\Response as SResponse; @@ -28,9 +30,10 @@ class Response extends HttpService implements ResponseInterface const JSON = 'json'; const XML = 'xml'; const HTML = 'html'; + const FILE = 'file'; /** @var ?string */ - public ?string $format = null; + private ?string $format = null; /** @var int */ public int $statusCode = 200; @@ -45,11 +48,22 @@ class Response extends HttpService implements ResponseInterface const FORMAT_MAPS = [ self::JSON => JsonFormatter::class, self::XML => XmlFormatter::class, - self::HTML => HtmlFormatter::class + self::HTML => HtmlFormatter::class, + self::FILE => FileFormatter::class, ]; public int $fd = 0; + + /** + * @return string + */ + public function getFormat(): string + { + return $this->format; + } + + /** * @param $format * @return $this @@ -100,6 +114,20 @@ class Response extends HttpService implements ResponseInterface } + /** + * @param string $path + * @param bool $isChunk + * @param int $limit + * @return $this|Response + */ + public function sendFile(string $path, bool $isChunk = false, int $limit = 10240): static + { + $this->format = self::FILE; + $this->endData = ['path' => $path, 'isChunk' => $isChunk, 'limit' => $limit]; + return $this; + } + + /** * @param $key * @param $value @@ -148,7 +176,7 @@ class Response extends HttpService implements ResponseInterface public function getResponseFormat(): string { return match ($this->format) { - Response::HTML => 'text/html;charset=utf-8', + Response::HTML, Response::FILE => 'text/html;charset=utf-8', Response::XML => 'application/xml;charset=utf-8', default => 'application/json;charset=utf-8', }; @@ -171,10 +199,11 @@ class Response extends HttpService implements ResponseInterface /** - * @param SResponse|null $response + * @param SResponse $response + * @return Response * @throws Exception */ - public function configure(SResponse $response = null): static + public function configure(SResponse $response): static { $response->setStatusCode($this->statusCode); $response->header('Content-Type', $this->getResponseFormat()); @@ -205,17 +234,14 @@ class Response extends HttpService implements ResponseInterface /** - * @return string - * @throws \ReflectionException + * @return IFormatter * @throws NotFindClassException + * @throws \ReflectionException */ - public function getContent(): string + public function getContent(): IFormatter { - if (empty($this->endData) || is_string($this->endData)) { - return $this->endData; - } $class = Response::FORMAT_MAPS[$this->format] ?? HtmlFormatter::class; - return \di($class)->send($this->endData)->getData(); + return \di($class)->send($this->endData); } @@ -236,43 +262,12 @@ class Response extends HttpService implements ResponseInterface /** @var SResponse $response */ $response = Context::getContext('response'); if (!empty($response)) { - return $response->redirect($url); + return $response->redirect($url,302); } return false; } - /** - * @param string $path - * @param int $offset - * @param int $limit - * @param int $sleep - * @return string - */ - public function sendFile(string $path, int $offset = 0, int $limit = 1024000, int $sleep = 0): string - { - $open = fopen($path, 'r'); - - $stat = fstat($open); - - - /** @var SResponse $response */ - $response = Context::getContext('response'); - $response->header('Content-length', $stat['size']); - while ($file = fread($open, $limit)) { - $response->write($file); - fseek($open, $offset); - if ($sleep > 0) sleep($sleep); - if ($offset >= $stat['size']) { - break; - } - $offset += $limit; - } - $response->end(); - return ''; - } - - /** * @return string * @throws Exception diff --git a/Server/Constrict/Response.php b/Server/Constrict/Response.php index 180fb6e0..06fb67db 100644 --- a/Server/Constrict/Response.php +++ b/Server/Constrict/Response.php @@ -20,6 +20,7 @@ class Response implements ResponseInterface const JSON = 'json'; const XML = 'xml'; const HTML = 'html'; + const FILE = 'file'; /** * @param $name diff --git a/Server/Constrict/ResponseEmitter.php b/Server/Constrict/ResponseEmitter.php new file mode 100644 index 00000000..d3324b3b --- /dev/null +++ b/Server/Constrict/ResponseEmitter.php @@ -0,0 +1,65 @@ +configure($response)->getContent(); + if (!($content instanceof FileFormatter)) { + $response->end($content->getData()); + return; + } + $this->download($content->getData(), $response); + } + + + /** + * @param array $content + * @param \Swoole\Http\Response $response + */ + private function download(array $content, \Swoole\Http\Response $response) + { + if ($content['isChunk'] === false) { + $response->sendfile($content['path']); + return; + } + + $resource = fopen($content['path'], 'r'); + + $state = fstat($resource); + + $offset = 0; + + $response->header('Content-length', $state['size']); + while ($file = fread($resource, $content['limit'])) { + $response->write($file); + fseek($resource, $offset); + if ($offset >= $state['size']) { + break; + } + $offset += $content['limit']; + } + $response->end(); + } + + +} diff --git a/Server/HTTPServerListener.php b/Server/HTTPServerListener.php index 20bb298d..45f24e62 100644 --- a/Server/HTTPServerListener.php +++ b/Server/HTTPServerListener.php @@ -10,6 +10,7 @@ use HttpServer\Route\Node; use HttpServer\Route\Router; use ReflectionException; use Server\Constrict\Response as CResponse; +use Server\Constrict\ResponseEmitter; use Server\Events\OnAfterRequest; use Snowflake\Abstracts\Config; use Snowflake\Events\EventDispatch; @@ -50,6 +51,11 @@ class HTTPServerListener extends Abstracts\Server public EventDispatch $eventDispatch; + + #[Inject(ResponseEmitter::class)] + public ResponseEmitter $responseEmitter; + + /** * @var ExceptionHandlerInterface */ @@ -127,8 +133,7 @@ class HTTPServerListener extends Abstracts\Server } catch (Error | Throwable $exception) { $responseData = $this->exceptionHandler->emit($exception, $this->response); } finally { - $response->end($responseData->configure($response)->getContent()); - + $this->responseEmitter->sender($response, $responseData); $this->eventDispatch->dispatch(new OnAfterRequest()); } } diff --git a/Server/ResponseInterface.php b/Server/ResponseInterface.php index 096d2d13..aab5bd6e 100644 --- a/Server/ResponseInterface.php +++ b/Server/ResponseInterface.php @@ -2,6 +2,12 @@ namespace Server; + +use HttpServer\Http\Response; + +/** + * @mixin Response + */ interface ResponseInterface { diff --git a/System/Abstracts/Input.php b/System/Abstracts/Input.php index d51890f1..d249dd32 100644 --- a/System/Abstracts/Input.php +++ b/System/Abstracts/Input.php @@ -38,7 +38,7 @@ class Input /** * @param $key * @param null $default - * @return mixed|null + * @return mixed */ public function get($key, $default = null): mixed {