From a095c94e21b373be1b410d9ded77acfc22eb7ef6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mr=C2=B7x?= Date: Mon, 2 Aug 2021 16:38:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Database/ActiveQuery.php | 23 +- Database/Base/BaseActiveRecord.php | 28 +- HttpServer/Controller.php | 60 +- HttpServer/Route/Router.php | 1260 +++++++++++----------- System/Abstracts/BaseApplication.php | 852 +++++++-------- System/Abstracts/TraitApplication.php | 5 +- System/Cache/Redis.php | 9 +- System/Di/Attributes.php | 132 +++ System/Di/Container.php | 390 ++----- System/Di/Service.php | 240 +++-- System/Events/EventDispatch.php | 32 + System/Events/EventDispatchInterface.php | 18 + System/Events/EventListener.php | 37 + System/Events/EventProviders.php | 8 + System/Snowflake.php | 12 +- 15 files changed, 1593 insertions(+), 1513 deletions(-) create mode 100644 System/Di/Attributes.php create mode 100644 System/Events/EventDispatch.php create mode 100644 System/Events/EventDispatchInterface.php create mode 100644 System/Events/EventListener.php create mode 100644 System/Events/EventProviders.php diff --git a/Database/ActiveQuery.php b/Database/ActiveQuery.php index 4c911fcd..7c3ecfee 100644 --- a/Database/ActiveQuery.php +++ b/Database/ActiveQuery.php @@ -12,7 +12,6 @@ namespace Database; use Database\Traits\QueryTrait; use Exception; use Snowflake\Abstracts\Component; -use Snowflake\Snowflake; /** * Class ActiveQuery @@ -107,22 +106,12 @@ class ActiveQuery extends Component implements ISqlBuilder if (is_string($name)) { $name = explode(',', $name); } - foreach ($name as $key => $val) { + foreach ($name as $val) { array_push($this->with, $val); } return $this; } - /** - * @param bool $isArray - * @return $this - */ - public function asArray(bool $isArray = TRUE): static - { - $this->asArray = $isArray; - return $this; - } - /** * @param $sql @@ -137,20 +126,16 @@ class ActiveQuery extends Component implements ISqlBuilder /** - * @return ActiveRecord|array|null + * @return ActiveRecord|null * @throws Exception */ - public function first(): ActiveRecord|array|null + public function first(): ActiveRecord|null { $data = $this->execute($this->builder->one())->one(); if (empty($data)) { return NULL; } - $newModel = $this->modelClass::populate($data); - if ($this->asArray) { - return $newModel->toArray(); - } - return $newModel; + return $this->modelClass::populate($data); } diff --git a/Database/Base/BaseActiveRecord.php b/Database/Base/BaseActiveRecord.php index 04bc17bd..724c7913 100644 --- a/Database/Base/BaseActiveRecord.php +++ b/Database/Base/BaseActiveRecord.php @@ -43,7 +43,7 @@ use validator\Validator; * @property bool $isCreate * @method rules() * @method static tableName() - * @property Application $application + * @property Application $container */ abstract class BaseActiveRecord extends Component implements IOrm, ArrayAccess { @@ -106,7 +106,7 @@ abstract class BaseActiveRecord extends Component implements IOrm, ArrayAccess /** * @return Application */ - #[Pure] private function getApplication(): Application + #[Pure] private function getContainer(): Application { return Snowflake::app(); } @@ -322,14 +322,30 @@ abstract class BaseActiveRecord extends Component implements IOrm, ArrayAccess /** * @return ActiveQuery - * @throws ReflectionException - * @throws NotFindClassException */ public static function find(): ActiveQuery { - return Snowflake::createObject(ActiveQuery::class, [static::class]); + return new ActiveQuery(get_called_class()); } + /** + * @return ActiveQuery + */ + public static function query(): ActiveQuery + { + return new ActiveQuery(get_called_class()); + } + + + /** + * @throws ConfigException + */ + protected function getConnection() + { + return Config::get('connections.' . static::$ab_name, null, true); + } + + /** * @param null $condition * @param array $attributes @@ -710,7 +726,7 @@ abstract class BaseActiveRecord extends Component implements IOrm, ArrayAccess * @return bool * @throws Exception */ - #[Event(ActiveRecord::AFTER_SAVE)] + #[Event(self::AFTER_SAVE)] public function afterSave($attributes, $changeAttributes): bool { return true; diff --git a/HttpServer/Controller.php b/HttpServer/Controller.php index e28e0126..21eb95dd 100644 --- a/HttpServer/Controller.php +++ b/HttpServer/Controller.php @@ -10,6 +10,7 @@ use HttpServer\Http\HttpParams; use HttpServer\Http\Request; use HttpServer\Http\Response; use Snowflake\Abstracts\TraitApplication; +use Snowflake\Application; /** * Class WebController @@ -18,39 +19,48 @@ use Snowflake\Abstracts\TraitApplication; class Controller { - use TraitApplication; + use TraitApplication; - /** - * inject request - * - * @var Request|null - */ - #[Inject('request')] - public ?Request $request = null; + /** + * @param Application $container + */ + public function __construct(protected Application $container) + { + + } - /** - * @var HttpParams|null - */ - #[Inject('input')] - public ?HttpParams $input = null; + /** + * inject request + * + * @var Request|null + */ + #[Inject('request')] + public ?Request $request = null; - /** - * @var HttpHeaders|null - */ - #[Inject('header')] - public ?HttpHeaders $header = null; + /** + * @var HttpParams|null + */ + #[Inject('input')] + public ?HttpParams $input = null; - /** - * inject response - * - * @var Response|null - */ - #[Inject('response')] - public ?Response $response = null; + /** + * @var HttpHeaders|null + */ + #[Inject('header')] + public ?HttpHeaders $header = null; + + + /** + * inject response + * + * @var Response|null + */ + #[Inject('response')] + public ?Response $response = null; } diff --git a/HttpServer/Route/Router.php b/HttpServer/Route/Router.php index cb162c2d..2a9e6860 100644 --- a/HttpServer/Route/Router.php +++ b/HttpServer/Route/Router.php @@ -28,656 +28,656 @@ defined('ROUTER_HASH') or define('ROUTER_HASH', 2); */ class Router extends HttpService implements RouterInterface { - /** @var Node[] $nodes */ - public static array $nodes = []; - public array $groupTacks = []; - public ?string $dir = 'App\\Http\\Controllers'; - - const NOT_FOUND = 'Page not found or method not allowed.'; - - /** @var string[] */ - public array $methods = ['GET', 'POST', 'OPTIONS', 'PUT', 'DELETE', 'RECEIVE', 'HEAD']; - - - public ?Closure $middleware = null; - - public int $useTree = ROUTER_TREE; - - - private static array $controllers = []; - - - public ?Response $response = null; - - - /** - * @param Closure $middleware - */ - public function setMiddleware(\Closure $middleware): void - { - $this->middleware = $middleware; - } - - - /** - * @throws ConfigException - * @throws Exception - * 初始化函数路径 - */ - public function init() - { - $this->dir = Config::get('http.namespace', $this->dir); - - $this->response = Snowflake::app()->get('response'); - } - - - /** - * @param bool $useTree - */ - public function setUseTree(bool $useTree): void - { - $this->useTree = $useTree ? ROUTER_TREE : ROUTER_HASH; - } - - - /** - * @param $port - * @param Closure|array|string $closure - * @param null $method - * @return Node|bool|null - * @throws - */ - public function addPortListen($port, Closure|array|string $closure, $method = null): Node|null|bool - { - if (!is_string($closure)) { - return $this->addRoute('add-port-listen/port_' . $port, $closure, 'listen'); - } - if (empty($method)) { - return $this->addError($closure . '::' . $method); - } - $_closure = Snowflake::createObject($closure); - if (!method_exists($_closure, $method)) { - return $this->addError($closure . '::' . $method); - } - return $this->addRoute('add-port-listen/port_' . $port, [$_closure, $method], 'listen'); - } - - - /** - * @param $path - * @param $handler - * @param string $method - * @return ?Node - * @throws Exception - */ - public function addRoute($path, $handler, string $method = 'any'): ?Node - { - if (!isset(static::$nodes[$method])) { - static::$nodes[$method] = []; - } - if ($handler instanceof Closure) { - $handler = Closure::bind($handler, di(Controller::class)); - } - return $this->hash($path, $handler, $method); - } - - - /** - * @param $path - * @param $handler - * @param string $method - * @return ?Node - */ - private function hash($path, $handler, string $method = 'any'): ?Node - { - $path = $this->resolve($path); - static::$nodes[$method][$path] = $this->NodeInstance($path, 0, $method); - - return static::$nodes[$method][$path]->bindHandler($handler); - } - - - /** - * @param $path - * @return string - */ - #[Pure] private function resolve($path): string - { - $paths = array_column($this->groupTacks, 'prefix'); - if (empty($paths)) { - return '/' . ltrim($path, '/'); - } - $paths = '/' . implode('/', $paths); - if ($path != '/') { - return $paths . '/' . ltrim($path, '/'); - } - return $paths . '/'; - } - - - /** - * @param $path - * @param $handler - * @param string $method - * @return Node - * @throws Exception - */ - private function tree($path, $handler, string $method = 'any'): Node - { - list($first, $explode) = $this->split($path); - - $parent = static::$nodes[$method][$first] ?? null; - if (empty($parent)) { - static::$nodes[$method][$first] = $parent = $this->NodeInstance('/', 0, $method); - } - - if ($first !== '/') { - $parent = $this->bindNode($parent, $explode, $method); - } - $parent->path = $path; - return $parent->bindHandler($handler); - } - - - /** - * @param Node $parent - * @param array $explode - * @param $method - * @return Node - * @throws Exception - */ - private function bindNode(Node $parent, array $explode, $method): Node - { - $a = 0; - if (empty($explode)) { - return $parent->addChild($this->NodeInstance('/', $a, $method), '/'); - } - foreach ($explode as $value) { - if (empty($value)) { - continue; - } - ++$a; - - $search = $parent->findNode($value); - if ($search === null) { - $parent = $parent->addChild($this->NodeInstance($value, $a, $method), $value); - } else { - $parent = $search; - } - } - return $parent; - } - - /** - * @param $route - * @param $handler - * @return Node|null - * @throws - */ - public function socket($route, $handler): ?Node - { - return $this->addRoute($route, $handler, 'socket'); - } - - - /** - * @param $route - * @param $handler - * @return Node|null - * @throws - */ - public function post($route, $handler): ?Node - { - return $this->addRoute($route, $handler, 'POST'); - } - - /** - * @param $route - * @param $handler - * @return Node|null - * @throws - */ - public function get($route, $handler): ?Node - { - return $this->addRoute($route, $handler, 'GET'); - } - - - /** - * @param $port - * @param callable $callback - * @return mixed - * @throws Exception - */ - public function addRpcService($port, callable $callback): mixed - { - return call_user_func($callback, new Actuator($port)); - } - - - /** - * @param $route - * @param $handler - * @return Node|null - * @throws - */ - public function options($route, $handler): ?Node - { - return $this->addRoute($route, $handler, 'OPTIONS'); - } - - - /** - * @param $route - * @param $handler - * @return Any - * @throws - */ - public function any($route, $handler): Any - { - $nodes = []; - foreach (['GET', 'POST', 'OPTIONS', 'PUT', 'DELETE', 'HEAD'] as $method) { - $nodes[] = $this->addRoute($route, $handler, $method); - } - return new Any($nodes); - } - - /** - * @param $route - * @param $handler - * @return Node|null - * @throws - */ - public function delete($route, $handler): ?Node - { - return $this->addRoute($route, $handler, 'DELETE'); - } - - - /** - * @param $route - * @param $handler - * @return Node|null - * @throws Exception - */ - public function head($route, $handler): ?Node - { - return $this->addRoute($route, $handler, 'HEAD'); - } - - - /** - * @param $route - * @param $handler - * @return Node|null - * @throws - */ - public function put($route, $handler): ?Node - { - return $this->addRoute($route, $handler, 'PUT'); - } - - /** - * @param $value - * @param int $index - * @param string $method - * @return Node - * @throws - */ - public function NodeInstance($value, int $index = 0, string $method = 'GET'): Node - { - $node = new Node(); - $node->childes = []; - $node->path = $value; - $node->index = $index; - $node->method = $method; - $node->namespace = $this->loadNamespace($method); - - $name = array_column($this->groupTacks, 'middleware'); - if ($this->middleware instanceof \Closure) { - $node->addMiddleware([$this->middleware]); - } - if (is_array($name)) { - $node->addMiddleware($this->resolve_middleware($name)); - } - return $node; - } - - - /** - * @param string|array $middleware - * @return array - * @throws NotFindClassException - * @throws ReflectionException - */ - private function resolve_middleware(string|array $middleware): array - { - if (is_string($middleware)) { - $middleware = [$middleware]; - } - - $array = []; - foreach ($middleware as $value) { - if (is_array($value)) { - foreach ($value as $item) { - $array[] = $this->getMiddlewareInstance($item); - } - } else { - $array[] = $this->getMiddlewareInstance($value); - } - } - return array_filter($array); - } - - - /** - * @param $value - * @return Closure|array|null - * @throws NotFindClassException - * @throws ReflectionException - */ - private function getMiddlewareInstance($value): null|Closure|array - { - if (!is_string($value)) { - return $value; - } - $value = Snowflake::createObject($value); - if (!($value instanceof Middleware)) { - return null; - } - return [$value, 'onHandler']; - } - - - /** - * @param $method - * @return array - */ - private function loadNamespace($method): array - { - $name = array_column($this->groupTacks, 'namespace'); - if ($method == 'package' || $method == 'RECEIVE') { - $dir = 'App\\Listener'; - } else { - $dir = $this->dir; - } - array_unshift($name, $dir); - return array_filter($name); - } - - /** - * @param array $config - * @param callable $callback - * 路由分组 - * @param null $stdClass - */ - public function group(array $config, callable $callback, $stdClass = null) - { - $this->groupTacks[] = $config; - if ($stdClass) { - $callback($stdClass); - } else { - $callback($this); - } - array_pop($this->groupTacks); - } - - /** - * @return string - */ - public function addPrefix(): string - { - $prefix = array_column($this->groupTacks, 'prefix'); - - $prefix = array_filter($prefix); - - if (empty($prefix)) { - return ''; - } - - return '/' . implode('/', $prefix); - } - - /** - * @param array|null $explode - * @param $method - * @return Node|null - * 查找指定路由 - */ - public function tree_search(?array $explode, $method): ?Node - { - if (empty($explode)) { - return static::$nodes[$method]['/'] ?? null; - } - $first = array_shift($explode); - if (!($parent = static::$nodes[$method][$first] ?? null)) { - return null; - } - if (empty($explode)) { - return $parent->findNode('/'); - } - while ($value = array_shift($explode)) { - $node = $parent->findNode($value); - if (!$node) { - break; - } - $parent = $node; - } - return $parent; - } - - /** - * @param $path - * @return array - * '*' - */ - public function split($path): array - { - $prefix = $this->addPrefix(); - $path = ltrim($path, '/'); - if (!empty($prefix)) { - $path = $prefix . '/' . $path; - } - - $explode = array_filter(explode('/', $path)); - if (empty($explode)) { - return ['/', []]; - } - - $first = array_shift($explode); - if (empty($explode)) { - $explode = []; - } - return [$first, $explode]; - } - - /** - * @return array - */ - public function each(): array - { - $paths = []; - foreach (static::$nodes as $node) { - /** @var Node[] $node */ - foreach ($node as $path => $_node) { - $paths[] = strtoupper($_node->method) . ' : ' . $path; - } - } - return $paths; - } - - - /** - * @return mixed - * @throws - */ - public function dispatch(Request $request): void - { - $node = $this->find_path($request); - if (!($node instanceof Node)) { - $this->response->setFormat(Response::HTML); - $this->response->send('

404

'); - } else { - $this->response->send($node->dispatch(), 200); - } - } + /** @var Node[] $nodes */ + public static array $nodes = []; + public array $groupTacks = []; + public ?string $dir = 'App\\Http\\Controllers'; + + const NOT_FOUND = 'Page not found or method not allowed.'; + + /** @var string[] */ + public array $methods = ['GET', 'POST', 'OPTIONS', 'PUT', 'DELETE', 'RECEIVE', 'HEAD']; + + + public ?Closure $middleware = null; + + public int $useTree = ROUTER_TREE; + + + private static array $controllers = []; + + + public ?Response $response = null; + + + /** + * @param Closure $middleware + */ + public function setMiddleware(\Closure $middleware): void + { + $this->middleware = $middleware; + } + + + /** + * @throws ConfigException + * @throws Exception + * 初始化函数路径 + */ + public function init() + { + $this->dir = Config::get('http.namespace', $this->dir); + + $this->response = Snowflake::app()->get('response'); + } + + + /** + * @param bool $useTree + */ + public function setUseTree(bool $useTree): void + { + $this->useTree = $useTree ? ROUTER_TREE : ROUTER_HASH; + } + + + /** + * @param $port + * @param Closure|array|string $closure + * @param null $method + * @return Node|bool|null + * @throws + */ + public function addPortListen($port, Closure|array|string $closure, $method = null): Node|null|bool + { + if (!is_string($closure)) { + return $this->addRoute('add-port-listen/port_' . $port, $closure, 'listen'); + } + if (empty($method)) { + return $this->addError($closure . '::' . $method); + } + $_closure = Snowflake::createObject($closure); + if (!method_exists($_closure, $method)) { + return $this->addError($closure . '::' . $method); + } + return $this->addRoute('add-port-listen/port_' . $port, [$_closure, $method], 'listen'); + } + + + /** + * @param $path + * @param $handler + * @param string $method + * @return ?Node + * @throws Exception + */ + public function addRoute($path, $handler, string $method = 'any'): ?Node + { + if (!isset(static::$nodes[$method])) { + static::$nodes[$method] = []; + } + if ($handler instanceof Closure) { + $handler = Closure::bind($handler, di(Controller::class)); + } + return $this->hash($path, $handler, $method); + } + + + /** + * @param $path + * @param $handler + * @param string $method + * @return ?Node + */ + private function hash($path, $handler, string $method = 'any'): ?Node + { + $path = $this->resolve($path); + static::$nodes[$method][$path] = $this->NodeInstance($path, 0, $method); + + return static::$nodes[$method][$path]->bindHandler($handler); + } + + + /** + * @param $path + * @return string + */ + #[Pure] private function resolve($path): string + { + $paths = array_column($this->groupTacks, 'prefix'); + if (empty($paths)) { + return '/' . ltrim($path, '/'); + } + $paths = '/' . implode('/', $paths); + if ($path != '/') { + return $paths . '/' . ltrim($path, '/'); + } + return $paths . '/'; + } + + + /** + * @param $path + * @param $handler + * @param string $method + * @return Node + * @throws Exception + */ + private function tree($path, $handler, string $method = 'any'): Node + { + list($first, $explode) = $this->split($path); + + $parent = static::$nodes[$method][$first] ?? null; + if (empty($parent)) { + static::$nodes[$method][$first] = $parent = $this->NodeInstance('/', 0, $method); + } + + if ($first !== '/') { + $parent = $this->bindNode($parent, $explode, $method); + } + $parent->path = $path; + return $parent->bindHandler($handler); + } + + + /** + * @param Node $parent + * @param array $explode + * @param $method + * @return Node + * @throws Exception + */ + private function bindNode(Node $parent, array $explode, $method): Node + { + $a = 0; + if (empty($explode)) { + return $parent->addChild($this->NodeInstance('/', $a, $method), '/'); + } + foreach ($explode as $value) { + if (empty($value)) { + continue; + } + ++$a; + + $search = $parent->findNode($value); + if ($search === null) { + $parent = $parent->addChild($this->NodeInstance($value, $a, $method), $value); + } else { + $parent = $search; + } + } + return $parent; + } + + /** + * @param $route + * @param $handler + * @return Node|null + * @throws + */ + public function socket($route, $handler): ?Node + { + return $this->addRoute($route, $handler, 'socket'); + } + + + /** + * @param $route + * @param $handler + * @return Node|null + * @throws + */ + public function post($route, $handler): ?Node + { + return $this->addRoute($route, $handler, 'POST'); + } + + /** + * @param $route + * @param $handler + * @return Node|null + * @throws + */ + public function get($route, $handler): ?Node + { + return $this->addRoute($route, $handler, 'GET'); + } + + + /** + * @param $port + * @param callable $callback + * @return mixed + * @throws Exception + */ + public function addRpcService($port, callable $callback): mixed + { + return call_user_func($callback, new Actuator($port)); + } + + + /** + * @param $route + * @param $handler + * @return Node|null + * @throws + */ + public function options($route, $handler): ?Node + { + return $this->addRoute($route, $handler, 'OPTIONS'); + } + + + /** + * @param $route + * @param $handler + * @return Any + * @throws + */ + public function any($route, $handler): Any + { + $nodes = []; + foreach (['GET', 'POST', 'OPTIONS', 'PUT', 'DELETE', 'HEAD'] as $method) { + $nodes[] = $this->addRoute($route, $handler, $method); + } + return new Any($nodes); + } + + /** + * @param $route + * @param $handler + * @return Node|null + * @throws + */ + public function delete($route, $handler): ?Node + { + return $this->addRoute($route, $handler, 'DELETE'); + } + + + /** + * @param $route + * @param $handler + * @return Node|null + * @throws Exception + */ + public function head($route, $handler): ?Node + { + return $this->addRoute($route, $handler, 'HEAD'); + } + + + /** + * @param $route + * @param $handler + * @return Node|null + * @throws + */ + public function put($route, $handler): ?Node + { + return $this->addRoute($route, $handler, 'PUT'); + } + + /** + * @param $value + * @param int $index + * @param string $method + * @return Node + * @throws + */ + public function NodeInstance($value, int $index = 0, string $method = 'GET'): Node + { + $node = new Node(); + $node->childes = []; + $node->path = $value; + $node->index = $index; + $node->method = $method; + $node->namespace = $this->loadNamespace($method); + + $name = array_column($this->groupTacks, 'middleware'); + if ($this->middleware instanceof \Closure) { + $node->addMiddleware([$this->middleware]); + } + if (is_array($name)) { + $node->addMiddleware($this->resolve_middleware($name)); + } + return $node; + } + + + /** + * @param string|array $middleware + * @return array + * @throws NotFindClassException + * @throws ReflectionException + */ + private function resolve_middleware(string|array $middleware): array + { + if (is_string($middleware)) { + $middleware = [$middleware]; + } + + $array = []; + foreach ($middleware as $value) { + if (is_array($value)) { + foreach ($value as $item) { + $array[] = $this->getMiddlewareInstance($item); + } + } else { + $array[] = $this->getMiddlewareInstance($value); + } + } + return array_filter($array); + } + + + /** + * @param $value + * @return Closure|array|null + * @throws NotFindClassException + * @throws ReflectionException + */ + private function getMiddlewareInstance($value): null|Closure|array + { + if (!is_string($value)) { + return $value; + } + $value = Snowflake::createObject($value); + if (!($value instanceof Middleware)) { + return null; + } + return [$value, 'onHandler']; + } + + + /** + * @param $method + * @return array + */ + private function loadNamespace($method): array + { + $name = array_column($this->groupTacks, 'namespace'); + if ($method == 'package' || $method == 'RECEIVE') { + $dir = 'App\\Listener'; + } else { + $dir = $this->dir; + } + array_unshift($name, $dir); + return array_filter($name); + } + + /** + * @param array $config + * @param callable $callback + * 路由分组 + * @param null $stdClass + */ + public function group(array $config, callable $callback, $stdClass = null) + { + $this->groupTacks[] = $config; + if ($stdClass) { + $callback($stdClass); + } else { + $callback($this); + } + array_pop($this->groupTacks); + } + + /** + * @return string + */ + public function addPrefix(): string + { + $prefix = array_column($this->groupTacks, 'prefix'); + + $prefix = array_filter($prefix); + + if (empty($prefix)) { + return ''; + } + + return '/' . implode('/', $prefix); + } + + /** + * @param array|null $explode + * @param $method + * @return Node|null + * 查找指定路由 + */ + public function tree_search(?array $explode, $method): ?Node + { + if (empty($explode)) { + return static::$nodes[$method]['/'] ?? null; + } + $first = array_shift($explode); + if (!($parent = static::$nodes[$method][$first] ?? null)) { + return null; + } + if (empty($explode)) { + return $parent->findNode('/'); + } + while ($value = array_shift($explode)) { + $node = $parent->findNode($value); + if (!$node) { + break; + } + $parent = $node; + } + return $parent; + } + + /** + * @param $path + * @return array + * '*' + */ + public function split($path): array + { + $prefix = $this->addPrefix(); + $path = ltrim($path, '/'); + if (!empty($prefix)) { + $path = $prefix . '/' . $path; + } + + $explode = array_filter(explode('/', $path)); + if (empty($explode)) { + return ['/', []]; + } + + $first = array_shift($explode); + if (empty($explode)) { + $explode = []; + } + return [$first, $explode]; + } + + /** + * @return array + */ + public function each(): array + { + $paths = []; + foreach (static::$nodes as $node) { + /** @var Node[] $node */ + foreach ($node as $path => $_node) { + $paths[] = strtoupper($_node->method) . ' : ' . $path; + } + } + return $paths; + } + + + /** + * @return mixed + * @throws + */ + public function dispatch(Request $request): void + { + $node = $this->find_path($request); + if (!($node instanceof Node)) { + $this->response->setFormat(Response::HTML); + $this->response->send('

404

'); + } else { + $this->response->send($node->dispatch(), 200); + } + } /** * @throws Exception */ - public function pageNotFound() - { - $this->response->setFormat(Response::HTML); - $this->response->send('

404

'); - } + public function pageNotFound() + { + $this->response->setFormat(Response::HTML); + $this->response->send('

404

'); + } - /** - * @param $exception - * @return mixed - * @throws Exception - */ - public function exception($exception): mixed - { - return Snowflake::app()->getLogger()->exception($exception); - } + /** + * @param $exception + * @return mixed + * @throws Exception + */ + public function exception($exception): mixed + { + return Snowflake::app()->getLogger()->exception($exception); + } - /** - * @param Request $request - * @return Node|null 树干搜索 - * 树干搜索 - */ - public function find_path(Request $request): ?Node - { - $method = $request->getMethod(); - $uri = $request->headers->get('request_uri', '/'); + /** + * @param Request $request + * @return Node|null 树干搜索 + * 树干搜索 + */ + public function find_path(Request $request): ?Node + { + $method = $request->getMethod(); + $uri = $request->headers->get('request_uri', '/'); - $methods = static::$nodes[$method][$uri] ?? null; - if (!is_null($methods)) { - return $methods; - } - if ($request->isOption) { - return static::$nodes[$method]['*'] ?? null; - } - return null; - } + $methods = static::$nodes[$method][$uri] ?? null; + if (!is_null($methods)) { + return $methods; + } + if ($request->isOption) { + return static::$nodes[$method]['*'] ?? null; + } + return null; + } - /** - * @param $uri - * @param $method - * @return Node|null - */ - public function search($uri, $method): Node|null - { - if (!isset(static::$nodes[$method])) { - return null; - } - $methods = static::$nodes[$method]; - if (isset($methods[$uri])) { - return $methods[$uri]; - } - return $methods['/'] ?? null; - } + /** + * @param $uri + * @param $method + * @return Node|null + */ + public function search($uri, $method): Node|null + { + if (!isset(static::$nodes[$method])) { + return null; + } + $methods = static::$nodes[$method]; + if (isset($methods[$uri])) { + return $methods[$uri]; + } + return $methods['/'] ?? null; + } - /** - * @param $request - * @return Node|null - */ - private function search_options($request): ?Node - { - $method = $request->getMethod(); - if (!isset(static::$nodes[$method])) { - return null; - } - if (!isset(static::$nodes[$method]['*'])) { - return null; - } - return static::$nodes[$method]['*']; - } + /** + * @param $request + * @return Node|null + */ + private function search_options($request): ?Node + { + $method = $request->getMethod(); + if (!isset(static::$nodes[$method])) { + return null; + } + if (!isset(static::$nodes[$method]['*'])) { + return null; + } + return static::$nodes[$method]['*']; + } - /** - * @param Request $request - * @return Node|null - * 树杈搜索 - */ - private function Branch_search(Request $request): ?Node - { - $node = $this->tree_search($request->getExplode(), $request->getMethod()); - if ($node instanceof Node) { - return $node; - } - if (!$request->isOption) { - return null; - } - $node = $this->tree_search(['*'], $request->getMethod()); - if (!($node instanceof Node)) { - return null; - } - return $node; - } + /** + * @param Request $request + * @return Node|null + * 树杈搜索 + */ + private function Branch_search(Request $request): ?Node + { + $node = $this->tree_search($request->getExplode(), $request->getMethod()); + if ($node instanceof Node) { + return $node; + } + if (!$request->isOption) { + return null; + } + $node = $this->tree_search(['*'], $request->getMethod()); + if (!($node instanceof Node)) { + return null; + } + return $node; + } - /** - * @throws - */ - public function _loader() - { - $this->loadRouteDir(APP_PATH . 'routes'); - $classes = Snowflake::getAnnotation()->runtime(CONTROLLER_PATH); - foreach ($classes as $class) { - $instance = Snowflake::getDi()->get($class); - $methods = Snowflake::getDi()->getMethodAttribute($class); - foreach ($methods as $method => $attribute) { - if (empty($attribute)) { - continue; - } - foreach ($attribute as $item) { - $item->execute($instance, $method); - } - } - } - } + /** + * @throws + */ + public function _loader() + { + $this->loadRouteDir(APP_PATH . 'routes'); + $classes = Snowflake::getAnnotation()->runtime(CONTROLLER_PATH); + foreach ($classes as $class) { + $instance = Snowflake::getDi()->get($class); + $methods = Snowflake::getDi()->getMethodAttribute($class); + foreach ($methods as $method => $attribute) { + if (empty($attribute)) { + continue; + } + foreach ($attribute as $item) { + $item->execute($instance, $method); + } + } + } + } - /** - * @param $path - * @throws Exception - * 加载目录下的路由文件 - */ - private function loadRouteDir($path) - { - $files = glob($path . '/*'); - for ($i = 0; $i < count($files); $i++) { - if (is_dir($files[$i])) { - $this->loadRouteDir($files[$i]); - } else { - $this->loadRouterFile($files[$i]); - } - } - } + /** + * @param $path + * @throws Exception + * 加载目录下的路由文件 + */ + private function loadRouteDir($path) + { + $files = glob($path . '/*'); + for ($i = 0; $i < count($files); $i++) { + if (is_dir($files[$i])) { + $this->loadRouteDir($files[$i]); + } else { + $this->loadRouterFile($files[$i]); + } + } + } - /** - * @param $files - * @throws Exception - */ - private function loadRouterFile($files) - { - try { - $router = $this; - include_once "{$files}"; - } catch (\Throwable $exception) { - $this->addError($exception, 'throwable'); - } finally { - if (isset($exception)) { - unset($exception); - } - } - } + /** + * @param $files + * @throws Exception + */ + private function loadRouterFile($files) + { + try { + $router = $this; + include_once "{$files}"; + } catch (\Throwable $exception) { + $this->addError($exception, 'throwable'); + } finally { + if (isset($exception)) { + unset($exception); + } + } + } } diff --git a/System/Abstracts/BaseApplication.php b/System/Abstracts/BaseApplication.php index bc5e9309..e34e6226 100644 --- a/System/Abstracts/BaseApplication.php +++ b/System/Abstracts/BaseApplication.php @@ -50,429 +50,431 @@ use Swoole\Table; abstract class BaseApplication extends Service { - use TraitApplication; - - - /** - * @var string - */ - public string $storage = APP_PATH . 'storage'; - - public string $envPath = APP_PATH . '.env'; - - /** - * Init constructor. - * - * @param array $config - * - * @throws - */ - public function __construct(array $config = []) - { - Snowflake::init($this); - - $this->moreComponents(); - $this->parseInt($config); - $this->parseEvents($config); - $this->initErrorHandler(); - $this->enableEnvConfig(); - - parent::__construct($config); - } - - - /** - * @return array - */ - public function enableEnvConfig(): array - { - if (!file_exists($this->envPath)) { - return []; - } - $lines = $this->readLinesFromFile($this->envPath); - foreach ($lines as $line) { - if (!$this->isComment($line) && $this->looksLikeSetter($line)) { - [$key, $value] = explode('=', $line); - putenv(trim($key) . '=' . trim($value)); - } - } - return $lines; - } - - - /** - * Read lines from the file, auto detecting line endings. - * - * @param string $filePath - * - * @return array - */ - protected function readLinesFromFile(string $filePath): array - { - // Read file into an array of lines with auto-detected line endings - $autodetect = ini_get('auto_detect_line_endings'); - ini_set('auto_detect_line_endings', '1'); - $lines = file($filePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); - ini_set('auto_detect_line_endings', $autodetect); - - return $lines; - } - - /** - * Determine if the line in the file is a comment, e.g. begins with a #. - * - * @param string $line - * - * @return bool - */ - protected function isComment(string $line): bool - { - $line = ltrim($line); - - return isset($line[0]) && $line[0] === '#'; - } - - /** - * Determine if the given line looks like it's setting a variable. - * - * @param string $line - * - * @return bool - */ - #[Pure] protected function looksLikeSetter(string $line): bool - { - return str_contains($line, '='); - } - - - /** - * @param $config - * - * @throws - */ - public function parseInt($config) - { - Config::sets($config); - if ($storage = Config::get('storage', 'storage')) { - if (!str_contains($storage, APP_PATH)) { - $storage = APP_PATH . $storage . '/'; - } - if (!is_dir($storage)) { - mkdir($storage); - } - if (!is_dir($storage) || !is_writeable($storage)) { - throw new InitException("Directory {$storage} does not have write permission"); - } - } - } - - - /** - * @param $config - * - * @throws - */ - public function parseEvents($config) - { - if (!isset($config['events']) || !is_array($config['events'])) { - return; - } - foreach ($config['events'] as $key => $value) { - if (is_string($value)) { - $value = Snowflake::createObject($value); - } - $this->addEvent($key, $value); - } - } - - - /** - * @param $key - * @param $value - * @throws InitException - * @throws NotFindClassException - * @throws ReflectionException - * @throws Exception - */ - private function addEvent($key, $value): void - { - if ($value instanceof \Closure) { - Event::on($key, $value, [], true); - return; - } - if (is_object($value)) { - Event::on($key, $value, [], true); - return; - } - if (is_array($value)) { - if (is_object($value[0]) && !($value[0] instanceof \Closure)) { - Event::on($key, $value, [], true); - return; - } - - if (is_string($value[0])) { - $value[0] = Snowflake::createObject($value[0]); - Event::on($key, $value, [], true); - return; - } - - foreach ($value as $item) { - if (!is_callable($item, true)) { - throw new InitException("Class does not hav callback."); - } - Event::on($key, $item, [], true); - } - } - - } - - - /** - * @param $name - * @return mixed - * @throws Exception - */ - public function clone($name): mixed - { - return clone $this->get($name); - } - - /** - * - * @throws Exception - */ - public function initErrorHandler() - { - $this->get('error')->register(); - } - - /** - * @return mixed - */ - public function getLocalIps(): mixed - { - return swoole_get_local_ip(); - } - - /** - * @return mixed - */ - public function getFirstLocal(): mixed - { - return current($this->getLocalIps()); - } - - - /** - * @return Logger - * @throws Exception - */ - public function getLogger(): Logger - { - return $this->get('logger'); - } - - - /** - * @return Producer - * @throws Exception - */ - public function getKafka(): Producer - { - return $this->get('kafka'); - } - - - /** - * @return \Redis|Redis - * @throws Exception - */ - public function getRedis(): Redis|\Redis - { - return $this->get('redis'); - } - - /** - * @param $ip - * @return bool - */ - public function isLocal($ip): bool - { - return $this->getFirstLocal() == $ip; - } - - - /** - * @return ErrorHandler - * @throws Exception - */ - public function getError(): ErrorHandler - { - return $this->get('error'); - } - - - /** - * @return Connection - * @throws Exception - */ - public function getMysqlFromPool(): Connection - { - return $this->get('connections'); - } - - - /** - * @return SRedis - * @throws Exception - */ - public function getRedisFromPool(): SRedis - { - return $this->get('redis_connections'); - } - - - /** - * @param $name - * @return Table - * @throws Exception - */ - public function getTable($name): Table - { - return $this->get($name); - } - - - /** - * @return Config - * @throws Exception - */ - public function getConfig(): Config - { - return $this->get('config'); - } - - - /** - * @return Router - * @throws Exception - */ - public function getRouter(): Router - { - return $this->get('router'); - } - - - /** - * @return Jwt - * @throws Exception - */ - public function getJwt(): Jwt - { - return $this->get('jwt'); - } - - - /** - * @return Server - * @throws Exception - */ - public function getServer(): Server - { - return $this->get('server'); - } - - - /** - * @return \Swoole\Http\Server|\Swoole\Server|\Swoole\WebSocket\Server|null - */ - public function getSwoole(): \Swoole\Http\Server|\Swoole\Server|\Swoole\WebSocket\Server|null - { - return ServerManager::getContext()->getServer(); - } - - - /** - * @return SAnnotation - * @throws Exception - */ - public function getAnnotation(): SAnnotation - { - return $this->get('annotation'); - } - - - /** - * @return Async - * @throws Exception - */ - public function getAsync(): Async - { - return $this->get('async'); - } - - - /** - * @return \Rpc\Producer - * @throws Exception - */ - public function getRpc(): \Rpc\Producer - { - return $this->get('rpc'); - } - - - /** - * @return Channel - * @throws Exception - */ - public function getChannel(): Channel - { - return $this->get('channel'); - } - - - /** - * @return Pool - * @throws Exception - */ - public function getClientsPool(): Pool - { - return $this->get('clientsPool'); - } - - - /** - * @throws Exception - */ - protected function moreComponents(): void - { - $this->setComponents([ - 'error' => ['class' => ErrorHandler::class], - 'connections' => ['class' => Connection::class], - 'redis_connections' => ['class' => SRedis::class], - 'clientsPool' => ['class' => Pool::class], - 'config' => ['class' => Config::class], - 'logger' => ['class' => Logger::class], - 'annotation' => ['class' => SAnnotation::class], - 'router' => ['class' => Router::class], - 'event' => ['class' => Event::class], - 'redis' => ['class' => Redis::class], - 'aop' => ['class' => Aop::class], - 'input' => ['class' => HttpParams::class], - 'header' => ['class' => HttpHeaders::class], - 'jwt' => ['class' => Jwt::class], - 'async' => ['class' => Async::class], - 'kafka-container' => ['class' => TaskContainer::class], - 'filter' => ['class' => HttpFilter::class], - 'goto' => ['class' => BaseGoto::class], - 'response' => ['class' => Response::class], - 'request' => ['class' => Request::class], - 'channel' => ['class' => Channel::class], - 'rpc' => ['class' => \Rpc\Producer::class], - 'rpc-service' => ['class' => \Rpc\Service::class], - 'http2' => ['class' => Http2::class], - 'shutdown' => ['class' => Shutdown::class], - ]); - } + use TraitApplication; + + + /** + * @var string + */ + public string $storage = APP_PATH . 'storage'; + + public string $envPath = APP_PATH . '.env'; + + /** + * Init constructor. + * + * + * @throws + */ + public function __construct() + { + Snowflake::init($this); + + $config = sweep(APP_PATH . '/config'); + + $this->moreComponents(); + $this->parseInt($config); + $this->parseEvents($config); + $this->initErrorHandler(); + $this->enableEnvConfig(); + + parent::__construct(); + } + + + /** + * @return array + */ + public function enableEnvConfig(): array + { + if (!file_exists($this->envPath)) { + return []; + } + $lines = $this->readLinesFromFile($this->envPath); + foreach ($lines as $line) { + if (!$this->isComment($line) && $this->looksLikeSetter($line)) { + [$key, $value] = explode('=', $line); + putenv(trim($key) . '=' . trim($value)); + } + } + return $lines; + } + + + /** + * Read lines from the file, auto detecting line endings. + * + * @param string $filePath + * + * @return array + */ + protected function readLinesFromFile(string $filePath): array + { + // Read file into an array of lines with auto-detected line endings + $autodetect = ini_get('auto_detect_line_endings'); + ini_set('auto_detect_line_endings', '1'); + $lines = file($filePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + ini_set('auto_detect_line_endings', $autodetect); + + return $lines; + } + + /** + * Determine if the line in the file is a comment, e.g. begins with a #. + * + * @param string $line + * + * @return bool + */ + protected function isComment(string $line): bool + { + $line = ltrim($line); + + return isset($line[0]) && $line[0] === '#'; + } + + /** + * Determine if the given line looks like it's setting a variable. + * + * @param string $line + * + * @return bool + */ + #[Pure] protected function looksLikeSetter(string $line): bool + { + return str_contains($line, '='); + } + + + /** + * @param $config + * + * @throws + */ + public function parseInt($config) + { + Config::sets($config); + if ($storage = Config::get('storage', 'storage')) { + if (!str_contains($storage, APP_PATH)) { + $storage = APP_PATH . $storage . '/'; + } + if (!is_dir($storage)) { + mkdir($storage); + } + if (!is_dir($storage) || !is_writeable($storage)) { + throw new InitException("Directory {$storage} does not have write permission"); + } + } + } + + + /** + * @param $config + * + * @throws + */ + public function parseEvents($config) + { + if (!isset($config['events']) || !is_array($config['events'])) { + return; + } + foreach ($config['events'] as $key => $value) { + if (is_string($value)) { + $value = Snowflake::createObject($value); + } + $this->addEvent($key, $value); + } + } + + + /** + * @param $key + * @param $value + * @throws InitException + * @throws NotFindClassException + * @throws ReflectionException + * @throws Exception + */ + private function addEvent($key, $value): void + { + if ($value instanceof \Closure) { + Event::on($key, $value, [], true); + return; + } + if (is_object($value)) { + Event::on($key, $value, [], true); + return; + } + if (is_array($value)) { + if (is_object($value[0]) && !($value[0] instanceof \Closure)) { + Event::on($key, $value, [], true); + return; + } + + if (is_string($value[0])) { + $value[0] = Snowflake::createObject($value[0]); + Event::on($key, $value, [], true); + return; + } + + foreach ($value as $item) { + if (!is_callable($item, true)) { + throw new InitException("Class does not hav callback."); + } + Event::on($key, $item, [], true); + } + } + + } + + + /** + * @param $name + * @return mixed + * @throws Exception + */ + public function clone($name): mixed + { + return clone $this->get($name); + } + + /** + * + * @throws Exception + */ + public function initErrorHandler() + { + $this->get('error')->register(); + } + + /** + * @return mixed + */ + public function getLocalIps(): mixed + { + return swoole_get_local_ip(); + } + + /** + * @return mixed + */ + public function getFirstLocal(): mixed + { + return current($this->getLocalIps()); + } + + + /** + * @return Logger + * @throws Exception + */ + public function getLogger(): Logger + { + return $this->get('logger'); + } + + + /** + * @return Producer + * @throws Exception + */ + public function getKafka(): Producer + { + return $this->get('kafka'); + } + + + /** + * @return \Redis|Redis + * @throws Exception + */ + public function getRedis(): Redis|\Redis + { + return $this->get('redis'); + } + + /** + * @param $ip + * @return bool + */ + public function isLocal($ip): bool + { + return $this->getFirstLocal() == $ip; + } + + + /** + * @return ErrorHandler + * @throws Exception + */ + public function getError(): ErrorHandler + { + return $this->get('error'); + } + + + /** + * @return Connection + * @throws Exception + */ + public function getMysqlFromPool(): Connection + { + return $this->get('connections'); + } + + + /** + * @return SRedis + * @throws Exception + */ + public function getRedisFromPool(): SRedis + { + return $this->get('redis_connections'); + } + + + /** + * @param $name + * @return Table + * @throws Exception + */ + public function getTable($name): Table + { + return $this->get($name); + } + + + /** + * @return Config + * @throws Exception + */ + public function getConfig(): Config + { + return $this->get('config'); + } + + + /** + * @return Router + * @throws Exception + */ + public function getRouter(): Router + { + return $this->get('router'); + } + + + /** + * @return Jwt + * @throws Exception + */ + public function getJwt(): Jwt + { + return $this->get('jwt'); + } + + + /** + * @return Server + * @throws Exception + */ + public function getServer(): Server + { + return $this->get('server'); + } + + + /** + * @return \Swoole\Http\Server|\Swoole\Server|\Swoole\WebSocket\Server|null + */ + public function getSwoole(): \Swoole\Http\Server|\Swoole\Server|\Swoole\WebSocket\Server|null + { + return ServerManager::getContext()->getServer(); + } + + + /** + * @return SAnnotation + * @throws Exception + */ + public function getAnnotation(): SAnnotation + { + return $this->get('annotation'); + } + + + /** + * @return Async + * @throws Exception + */ + public function getAsync(): Async + { + return $this->get('async'); + } + + + /** + * @return \Rpc\Producer + * @throws Exception + */ + public function getRpc(): \Rpc\Producer + { + return $this->get('rpc'); + } + + + /** + * @return Channel + * @throws Exception + */ + public function getChannel(): Channel + { + return $this->get('channel'); + } + + + /** + * @return Pool + * @throws Exception + */ + public function getClientsPool(): Pool + { + return $this->get('clientsPool'); + } + + + /** + * @throws Exception + */ + protected function moreComponents(): void + { + $this->setComponents([ + 'error' => ['class' => ErrorHandler::class], + 'connections' => ['class' => Connection::class], + 'redis_connections' => ['class' => SRedis::class], + 'clientsPool' => ['class' => Pool::class], + 'config' => ['class' => Config::class], + 'logger' => ['class' => Logger::class], + 'annotation' => ['class' => SAnnotation::class], + 'router' => ['class' => Router::class], + 'event' => ['class' => Event::class], + 'redis' => ['class' => Redis::class], + 'databases' => ['class' => \Database\Connection::class], + 'aop' => ['class' => Aop::class], + 'input' => ['class' => HttpParams::class], + 'header' => ['class' => HttpHeaders::class], + 'jwt' => ['class' => Jwt::class], + 'async' => ['class' => Async::class], + 'kafka-container' => ['class' => TaskContainer::class], + 'filter' => ['class' => HttpFilter::class], + 'goto' => ['class' => BaseGoto::class], + 'response' => ['class' => Response::class], + 'request' => ['class' => Request::class], + 'channel' => ['class' => Channel::class], + 'rpc' => ['class' => \Rpc\Producer::class], + 'rpc-service' => ['class' => \Rpc\Service::class], + 'http2' => ['class' => Http2::class], + 'shutdown' => ['class' => Shutdown::class], + ]); + } } diff --git a/System/Abstracts/TraitApplication.php b/System/Abstracts/TraitApplication.php index 79a6ccc6..64ce0301 100644 --- a/System/Abstracts/TraitApplication.php +++ b/System/Abstracts/TraitApplication.php @@ -16,15 +16,15 @@ use HttpServer\Route\Router; use HttpServer\Server; use HttpServer\Shutdown; use Kafka\Producer; +use Rpc\Producer as RPCProducer; use Snowflake\Async; use Snowflake\Cache\Redis; use Snowflake\Channel; use Snowflake\Error\Logger; use Snowflake\Event; use Snowflake\Jwt\Jwt; -use Snowflake\Pool\Pool; use Snowflake\Pool\Connection; -use Rpc\Producer as RPCProducer; +use Snowflake\Pool\Pool; /** * Trait TraitApplication @@ -45,6 +45,7 @@ use Rpc\Producer as RPCProducer; * @property BaseGoto $goto * @property Producer $kafka * @property Client $client + * @property \Database\Connection $databases * @property Curl $curl * @property \Snowflake\Crontab\Producer $crontab * @property HttpFilter $filter diff --git a/System/Cache/Redis.php b/System/Cache/Redis.php index bf888b8f..4e3d7d9f 100644 --- a/System/Cache/Redis.php +++ b/System/Cache/Redis.php @@ -25,12 +25,7 @@ use Snowflake\Snowflake; */ class Redis extends Component { - public string $host = '127.0.0.1'; - public string $auth = 'xl.2005113426'; - public int $port = 6973; - public int $databases = 0; - public int $timeout = -1; - public string $prefix = 'idd'; + /** * @throws Exception @@ -54,7 +49,7 @@ class Redis extends Component $config = $this->get_config(); - $length = (int)env('REDIS.POOL_LENGTH', 100); + $length = Config::get('connections.pool.max',10); $connections->initConnections('Redis:' . $config['host'], true, $length); } diff --git a/System/Di/Attributes.php b/System/Di/Attributes.php new file mode 100644 index 00000000..7290de9a --- /dev/null +++ b/System/Di/Attributes.php @@ -0,0 +1,132 @@ +getName(); + if (!isset($this->_classTarget[$className])) { + $this->_classTarget[$className] = []; + } + foreach ($class->getAttributes() as $attribute) { + if (!class_exists($attribute->getName())) { + continue; + } + $this->_classTarget[$className][] = $attribute->newInstance(); + } + } + + + /** + * @param mixed $class + * @return array + */ + public function getTargetNote(mixed $class): array + { + if (!is_string($class)) { + $class = $class::class; + } + return $this->_classTarget[$class] ?? []; + } + + + /** + * @param ReflectionClass $class + */ + protected function setMethodNote(ReflectionClass $class) + { + $className = $class->getName(); + $this->_classMethodNote[$className] = $this->_classMethod[$className] = []; + foreach ($class->getMethods(ReflectionMethod::IS_FINAL | ReflectionMethod::IS_PRIVATE + | ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED | ReflectionMethod::IS_ABSTRACT + ) as $ReflectionMethod) { + $this->_classMethod[$className][$ReflectionMethod->getName()] = $ReflectionMethod; + foreach ($ReflectionMethod->getAttributes() as $attribute) { + if (!class_exists($attribute->getName())) { + continue; + } + $this->_classMethodNote[$className][] = $attribute->newInstance(); + } + } + } + + + /** + * @param ReflectionClass $class + * @return array + */ + #[Pure] public function getMethodNote(ReflectionClass $class): array + { + return $this->_classMethodNote[$class->getName()] ?? []; + } + + + /** + * @param ReflectionClass $class + */ + protected function setPropertyNote(ReflectionClass $class) + { + $className = $class->getName(); + $this->_classProperty[$className] = $this->_classPropertyNote[$className] = []; + foreach ($class->getProperties(\ReflectionProperty::IS_PRIVATE | \ReflectionProperty::IS_PUBLIC | + \ReflectionProperty::IS_PROTECTED) as $ReflectionMethod) { + $this->_classProperty[$className][$ReflectionMethod->getName()] = $ReflectionMethod; + foreach ($ReflectionMethod->getAttributes() as $attribute) { + if (!class_exists($attribute->getName())) { + continue; + } + $this->_classPropertyNote[$className][] = $attribute->newInstance(); + } + } + } + + + /** + * @param ReflectionClass $class + * @return array + */ + #[Pure] public function getMethods(ReflectionClass $class): array + { + return $this->_classMethod[$class->getName()] ?? []; + } + + + /** + * @param ReflectionClass $class + * @return \ReflectionProperty[] + */ + #[Pure] public function getProperty(ReflectionClass $class): array + { + return $this->_classProperty[$class->getName()] ?? []; + } + + + /** + * @param ReflectionClass $class + * @return array + */ + #[Pure] public function getPropertyNote(ReflectionClass $class): array + { + return $this->_classPropertyNote[$class->getName()] ?? []; + } + + +} diff --git a/System/Di/Container.php b/System/Di/Container.php index 3ce79e1a..7b3dcf8a 100644 --- a/System/Di/Container.php +++ b/System/Di/Container.php @@ -10,14 +10,13 @@ declare(strict_types=1); namespace Snowflake\Di; use Annotation\Inject; -use Annotation\Target; use Exception; +use JetBrains\PhpStorm\Pure; use ReflectionClass; use ReflectionException; use ReflectionMethod; use ReflectionProperty; use Snowflake\Abstracts\BaseObject; -use Snowflake\Abstracts\Configure; use Snowflake\Exception\NotFindClassException; use Snowflake\Snowflake; @@ -28,63 +27,32 @@ use Snowflake\Snowflake; class Container extends BaseObject { + use Attributes; + /** * @var array * * instance class by className */ - private static array $_singletons = []; + private array $_singletons = []; /** * @var array * * class new instance construct parameter */ - private static array $_constructs = []; + private array $_constructs = []; /** * @var array * * implements \ReflectClass */ - private static array $_reflection = []; + private array $_reflection = []; - /** - * @var ReflectionProperty[] - */ - private static array $_reflectionProperty = []; - - /** - * @var ReflectionMethod[] - */ - private static array $_reflectionMethod = []; - - /** - * @var ReflectionClass[] - */ - private static array $_reflectionClass = []; - - - /** - * @var array - */ - private static array $_propertyAttributes = []; - - - /** - * @var array - */ - private static array $_methodsAttributes = []; - - - /** - * @var array - */ - private static array $_targetAttributes = []; - - - private static array $_attributeMapping = []; + /** @var array */ + private array $_parameters = []; /** @@ -92,7 +60,7 @@ class Container extends BaseObject * * The construct parameter */ - private static array $_param = []; + private array $_param = []; /** * @param $class @@ -106,50 +74,25 @@ class Container extends BaseObject */ public function get($class, array $constrict = [], array $config = []): mixed { - if (isset(static::$_singletons[$class])) { - return static::$_singletons[$class]; - } else if (!isset(static::$_constructs[$class])) { - return $this->resolve($class, $constrict, $config); - } - $definition = static::$_constructs[$class]; - if (is_callable($definition, TRUE)) { - return call_user_func($definition, $this, $constrict, $config); - } else if (is_array($definition)) { - return static::$_singletons[$class] = $this->resolveDefinition($definition, $class, $config, $constrict); - } else if (is_object($definition)) { - return static::$_singletons[$class] = $definition; - } else { - throw new NotFindClassException($class); + if (!isset($this->_singletons[$class])) { + $this->_singletons[$class] = $this->resolve($class, $constrict, $config); } + return $this->_singletons[$class]; } /** - * @param $definition * @param $class - * @param $config - * @param $constrict - * @return mixed + * @param array $constrict + * @param array $config + * @return object * @throws NotFindClassException * @throws ReflectionException * @throws Exception */ - private function resolveDefinition($definition, $class, $config, $constrict): mixed + public function newObject($class, array $constrict = [], array $config = []): object { - if (!isset($definition['class'])) { - throw new NotFindClassException($class); - } - $_className = $definition['class']; - unset($definition['class']); - - $definition = $this->mergeParam($class, $constrict); - - if ($_className === $class) { - $object = $this->resolve($class, $definition, $config); - } else { - $object = $this->get($class, $definition, $config); - } - return $object; + return $this->resolve($class, $constrict, $config); } @@ -163,65 +106,44 @@ class Container extends BaseObject */ private function resolve($class, $constrict, $config): object { - /** @var ReflectionClass $reflect */ - [$reflect, $dependencies] = $this->resolveDependencies($class, $constrict); + $reflect = $this->resolveDependencies($class); if (empty($reflect) || !$reflect->isInstantiable()) { throw new NotFindClassException($class); } - $object = $this->setConfig($config, $reflect, $dependencies, $class); - return $this->setClassAnnotation($reflect, $object); - } + $object = $this->setConfig($config, $reflect, $constrict); - - /** - * @param $reflect - * @param $object - * @return mixed - * @throws Exception - */ - private function setClassAnnotation($reflect, $object): mixed - { - static::$_reflectionClass[$reflect->getName()] = []; - foreach ($reflect->getAttributes() as $attribute) { - static::$_reflectionClass[$reflect->getName()][] = $attribute->newInstance(); - } return $this->propertyInject($reflect, $object); } - /** * @param $config * @param $reflect * @param $dependencies - * @param $class - * @return mixed + * @return object + * @throws NotFindClassException + * @throws ReflectionException */ - private function setConfig($config, $reflect, $dependencies, $class): mixed + private function setConfig($config, $reflect, $dependencies): object { - if (empty($config) || !is_array($config)) { - $object = $this->newInstance($reflect, $dependencies); - } else if (!empty($dependencies) && $reflect->implementsInterface(Configure::class)) { - $dependencies[count($dependencies) - 1] = $config; - $object = $this->newInstance($reflect, $dependencies); - } else { - static::$_param[$class] = $config; - - $object = $this->onAfterInit($this->newInstance($reflect, $dependencies), $config); - } - return $object; + $object = $this->newInstance($reflect, $dependencies); + return $this->onAfterInit($object, $config); } /** - * @param $reflect + * @param ReflectionClass $reflect * @param $dependencies - * @return mixed + * @return object + * @throws ReflectionException + * @throws NotFindClassException */ - private function newInstance($reflect, $dependencies): mixed + private function newInstance(ReflectionClass $reflect, $dependencies): object { - if (!empty($dependencies)) { - return $reflect->newInstanceArgs($dependencies); + $parameters = $this->getMethodParameters($reflect, '__construct'); + $parameters = $this->mergeParam($parameters, $dependencies); + if (!empty($parameters)) { + return $reflect->newInstanceArgs($parameters); } return $reflect->newInstance(); } @@ -235,10 +157,7 @@ class Container extends BaseObject */ public function propertyInject(ReflectionClass $reflect, $object): mixed { - if (!isset(static::$_propertyAttributes[$reflect->getName()])) { - return $object; - } - foreach (static::$_propertyAttributes[$reflect->getName()] as $property => $inject) { + foreach ($this->getPropertyNote($reflect) as $property => $inject) { /** @var Inject $inject */ $inject->execute($object, $property); } @@ -246,102 +165,15 @@ class Container extends BaseObject } - /** - * @param ReflectionClass $class - */ - private function resolveMethodAttribute(ReflectionClass $class) - { - if ($class->isAbstract() || $class->isTrait()) { - return; - } - foreach ($class->getMethods() as $method) { - if ($method->isStatic()) { - continue; - } - $this->setReflectionMethod($class, $method); - foreach ($method->getAttributes() as $attribute) { - if (!class_exists($attribute->getName())) { - continue; - } - $this->setMethodsAttributes($class, $method, $attribute->newInstance()); - } - } - } - - - /** - * @param ReflectionClass $class - * @param ReflectionMethod $method - */ - private function setReflectionMethod(ReflectionClass $class, ReflectionMethod $method) - { - if (!isset(static::$_attributeMapping[$class->getName()])) { - static::$_attributeMapping[$class->getName()] = []; - } - static::$_attributeMapping[$class->getName()][$method->getName()][] = $method; - } - - - /** - * @param ReflectionClass $attribute - * @param ReflectionMethod $method - * @param $object - */ - private function setMethodsAttributes(ReflectionClass $attribute, ReflectionMethod $method, $object) - { - if (!isset(static::$_methodsAttributes[$attribute->getName()])) { - static::$_methodsAttributes[$attribute->getName()] = []; - } - static::$_methodsAttributes[$attribute->getName()][$method->getName()][] = $object; - } - - - /** - * @param ReflectionClass $class - */ - private function resolveTargetAttribute(ReflectionClass $class) - { - if ($class->isAbstract() || $class->isTrait()) { - return; - } - foreach ($class->getAttributes() as $method) { - if ($method->getName() == Target::class) { - continue; - } - static::$_targetAttributes[$class->getName()] = $method->newInstance(); - } - } - - - /** - * @param $className - * @param $method - * @return ReflectionMethod|null - */ - public function getReflectionMethod($className, $method): ?ReflectionMethod - { - return static::$_reflectionMethod[$className][$method] ?? null; - } - - - /** - * @param $className - * @return ReflectionMethod|null - */ - public function getTargetAnnotation($className): ?ReflectionMethod - { - return static::$_targetAttributes[$className] ?? null; - } - - /** * @param $className * @param $method * @return array + * @throws ReflectionException */ public function getMethodAttribute($className, $method = null): array { - $methods = static::$_methodsAttributes[$className] ?? []; + $methods = $this->getMethodNote($this->getReflect($className)); if (!empty($method)) { return $methods[$method] ?? []; } @@ -353,17 +185,18 @@ class Container extends BaseObject * @param string $class * @param string|null $property * @return ReflectionProperty|ReflectionProperty[]|null + * @throws ReflectionException */ public function getClassReflectionProperty(string $class, string $property = null): ReflectionProperty|null|array { - if (!isset(static::$_reflectionProperty[$class])) { + $lists = $this->getProperty($this->getReflect($class)); + if (empty($lists)) { return null; } - $properties = static::$_reflectionProperty[$class]; if (!empty($property)) { - return $properties[$property] ?? null; + return $lists[$property] ?? null; } - return $properties; + return $lists; } @@ -381,75 +214,78 @@ class Container extends BaseObject return $object; } + /** * @param $class - * @param array $dependencies + * @return ReflectionClass + * @throws ReflectionException + */ + private function resolveDependencies($class): ReflectionClass + { + $this->_reflection[$class] = new ReflectionClass($class); + if (!$this->_reflection[$class]->isInstantiable()) { + throw new ReflectionException('Class ' . $class . ' cannot be instantiated'); + } + $this->setPropertyNote($this->_reflection[$class]); + $this->setTargetNote($this->_reflection[$class]); + $this->setMethodNote($this->_reflection[$class]); + if (!is_null($construct = $this->_reflection[$class]->getConstructor())) { + $this->_constructs[$class] = $construct; + } + return $this->_reflection[$class]; + } + + + /** + * @param ReflectionClass|string $class + * @return ReflectionMethod[] + */ + #[Pure] public function getReflectMethods(ReflectionClass|string $class): array + { + return $this->getMethods($class); + } + + + /** + * @param ReflectionClass|string $class + * @param string $method + * @return ReflectionMethod|null + */ + #[Pure] public function getReflectMethod(ReflectionClass|string $class, string $method): ?ReflectionMethod + { + return $this->getReflectMethods($class)[$method] ?? null; + } + + + /** + * @param ReflectionClass|string $class + * @param string $method * @return array|null * @throws NotFindClassException * @throws ReflectionException */ - private function resolveDependencies($class, array $dependencies = []): ?array + public function getMethodParameters(ReflectionClass|string $class, string $method): ?array { - if (!isset(static::$_reflection[$class])) { - if (!($reflect = new ReflectionClass($class))->isInstantiable()) { - throw new ReflectionException('Class ' . $class . ' cannot be instantiated'); - } - static::$_reflection[$class] = $reflect; - $this->resolveTargetAttribute(static::$_reflection[$class]); - $this->resolveMethodAttribute(static::$_reflection[$class]); - $this->scanProperty(static::$_reflection[$class]); + if (isset($this->_parameters[$class]) && isset($this->_parameters[$class][$method])) { + return $this->_parameters[$class][$method]; } - if (!is_null($construct = static::$_reflection[$class]->getConstructor())) { - foreach ($this->resolveMethodParam($construct) as $key => $item) { - $dependencies[$key] = $item; - } + $reflectMethod = $this->getReflectMethod($class, $method); + if (!($reflectMethod instanceof ReflectionMethod)) { + throw new ReflectionException("Class does not have a function $class::$method"); } - return [static::$_reflection[$class], $dependencies]; - } - - - /** - * @param ReflectionClass $reflectionClass - * @return void - */ - private function scanProperty(ReflectionClass $reflectionClass): void - { - $properties = $reflectionClass->getProperties(ReflectionProperty::IS_PUBLIC | - ReflectionProperty::IS_PRIVATE | ReflectionProperty::IS_PROTECTED - ); - - $className = $reflectionClass->getName(); - foreach ($properties as $property) { - $targets = $property->getAttributes(Inject::class); - if (count($targets) < 1) { - continue; - } - - static::$_reflectionProperty[$className][$property->getName()] = $property; - - static::$_propertyAttributes[$className][$property->getName()] = $targets[0]->newInstance(); + if ($reflectMethod->getNumberOfParameters() < 1) { + return []; } - } - - - /** - * @param ReflectionMethod|null $method - * @return array - * @throws NotFindClassException - * @throws ReflectionException - */ - private function resolveMethodParam(?ReflectionMethod $method): array - { - $array = []; - foreach ($method->getParameters() as $parameter) { + $this->_parameters[$class][$method] = $params = []; + foreach ($reflectMethod->getParameters() as $key => $parameter) { if ($parameter->isDefaultValueAvailable()) { - $array[] = $parameter->getDefaultValue(); + $params[$key] = $parameter->getDefaultValue(); } else { $type = $parameter->getType(); if (is_string($type) && class_exists($type)) { - $type = Snowflake::createObject($type); + $type = Snowflake::getDi()->get($type); } - $array[] = match ($parameter->getType()) { + $params[$key] = match ($parameter->getType()) { 'string' => '', 'int', 'float' => 0, '', null, 'object', 'mixed' => NULL, @@ -458,23 +294,21 @@ class Container extends BaseObject }; } } - return $array; + return $this->_parameters[$class][$method] = $params; } /** * @param $class * @return ReflectionClass|null - * @throws NotFindClassException * @throws ReflectionException */ public function getReflect($class): ?ReflectionClass { - $reflect = static::$_reflection[$class] ?? null; - if (!is_null($reflect)) { - return $reflect; + if (!isset($this->_reflection[$class])) { + return $this->resolveDependencies($class); } - return $this->resolveDependencies($class)[0]; + return $this->_reflection[$class]; } /** @@ -488,8 +322,8 @@ class Container extends BaseObject $class = $class::class; } unset( - static::$_reflection[$class], static::$_singletons[$class], - static::$_param[$class], static::$_constructs[$class] + $this->_reflection[$class], $this->_singletons[$class], + $this->_param[$class], $this->_constructs[$class] ); } @@ -498,10 +332,10 @@ class Container extends BaseObject */ public function flush(): static { - static::$_reflection = []; - static::$_singletons = []; - static::$_param = []; - static::$_constructs = []; + $this->_reflection = []; + $this->_singletons = []; + $this->_param = []; + $this->_constructs = []; return $this; } @@ -513,12 +347,12 @@ class Container extends BaseObject */ private function mergeParam($class, $newParam): array { - if (empty(static::$_param[$class])) { + if (empty($this->_param[$class])) { return $newParam; } else if (empty($newParam)) { - return static::$_param[$class]; + return $this->_param[$class]; } - $old = static::$_param[$class]; + $old = $this->_param[$class]; foreach ($newParam as $key => $val) { $old[$key] = $val; } diff --git a/System/Di/Service.php b/System/Di/Service.php index 43d21d4c..a28342d3 100644 --- a/System/Di/Service.php +++ b/System/Di/Service.php @@ -23,133 +23,143 @@ use Snowflake\Snowflake; class Service extends Component { - private array $_components = []; + private array $_components = []; - private array $_definition = []; + private array $_definition = []; - private array $_ids = []; + private array $_ids = []; - protected array $_alias = []; + protected array $_alias = []; - /** - * @param $id - * @param bool $try - * @return mixed - * @throws Exception - */ - public function get($id, bool $try = true): mixed - { - if (isset($this->_components[$id])) { - return $this->_components[$id]; - } - if (!isset($this->_definition[$id]) && !isset($this->_alias[$id])) { - if ($try === false) { - return null; - } - throw new ComponentException("Unknown component ID: $id"); - } - if (isset($this->_definition[$id])) { - $config = $this->_definition[$id]; - if (is_object($config)) { - return $this->_components[$id] = $config; - } - } else { - $config = $this->_alias[$id]; - } - return $this->_components[$id] = Snowflake::createObject($config); - } - - /** - * @param string $className - * @param string $alias - */ - public function setAlias(string $className, string $alias) - { - $this->_alias[$className] = $alias; - } - - /** - * @param $id - * @param $definition - * - * @return mixed - * @throws Exception - */ - public function set($id, $definition): void - { - if ($definition === NULL) { - $this->remove($id); - return; - } - - $this->_ids[] = $id; - - unset($this->_components[$id]); - if (is_object($definition) || is_callable($definition, TRUE)) { - $this->_definition[$id] = $definition; - } else if (!is_array($definition)) { - throw new ComponentException("Unexpected configuration type for the \"$id\" component: " . gettype($definition)); - } - $this->_definition[$id] = $definition; - } - - /** - * @param $id - * @return bool - */ - #[Pure] public function has($id): bool - { - return in_array($id, $this->_ids); - } - - /** - * @param array $data - * @throws Exception - */ - public function setComponents(array $data) - { - foreach ($data as $key => $val) { - $this->set($key, $val); - } - } + /** + * @param $id + * @param bool $try + * @return mixed + * @throws Exception + */ + public function get($id, bool $try = true): mixed + { + if (isset($this->_components[$id])) { + return $this->_components[$id]; + } + $config = $this->_getConfig($id, $try); + if (!is_object($config)) { + $config = Snowflake::createObject($config); + } + return $this->_components[$id] = $config; + } - /** - * @param $name - * @return mixed - * @throws Exception - */ - public function __get($name): mixed - { - if ($this->has($name)) { - return $this->get($name); - } + /** + * @param $id + * @param $try + * @return mixed + * @throws ComponentException + */ + private function _getConfig($id, $try): mixed + { + $config = $this->_definition[$id] ?? $this->_alias[$id] ?? null; + if (is_null($config)) { + if ($try === false) { + return null; + } + throw new ComponentException("Unknown component ID: $id"); + } + return $config; + } - return parent::__get($name); - } - /** - * @param $id - * @return bool - */ - public function remove($id): bool - { - $component = $this->_components[$id]; - $className = $component::class; + /** + * @param string $className + * @param string $alias + */ + public function setAlias(string $className, string $alias) + { + $this->_alias[$className] = $alias; + } - unset($component, $this->_components[$id]); - unset($this->_definition[$id]); - if (isset($this->_alias[$id])) { - unset($this->_components[$this->_alias[$id]]); - unset($this->_definition[$this->_alias[$id]]); - unset($this->_alias[$id]); - } + /** + * @param $id + * @param $definition + * + * @return mixed + * @throws Exception + */ + public function set($id, $definition): void + { + if ($definition === NULL) { + $this->remove($id); + return; + } + $this->_ids[] = $id; + unset($this->_components[$id]); + if (is_object($definition)) { + $this->_components[$id] = $definition; + $this->_definition[$id] = $definition; + } else if (!is_array($definition)) { + throw new ComponentException("Unexpected configuration type for the \"$id\" component: " . gettype($definition)); + } else { + $this->_definition[$id] = $definition; + } + } - Snowflake::getDi()->unset($className); + /** + * @param $id + * @return bool + */ + #[Pure] public function has($id): bool + { + return in_array($id, $this->_ids); + } - return $this->has($id); - } + /** + * @param array $data + * @throws Exception + */ + public function setComponents(array $data) + { + foreach ($data as $key => $val) { + $this->set($key, $val); + } + } + + + /** + * @param $name + * @return mixed + * @throws Exception + */ + public function __get($name): mixed + { + if ($this->has($name)) { + return $this->get($name); + } + + return parent::__get($name); + } + + /** + * @param $id + * @return bool + */ + public function remove($id): bool + { + $component = $this->_components[$id]; + $className = $component::class; + + unset($component, $this->_components[$id]); + unset($this->_definition[$id]); + if (isset($this->_alias[$id])) { + unset($this->_components[$this->_alias[$id]]); + unset($this->_definition[$this->_alias[$id]]); + unset($this->_alias[$id]); + } + + Snowflake::getDi()->unset($className); + + return $this->has($id); + } } diff --git a/System/Events/EventDispatch.php b/System/Events/EventDispatch.php new file mode 100644 index 00000000..e3531c2c --- /dev/null +++ b/System/Events/EventDispatch.php @@ -0,0 +1,32 @@ +eventListener->getEventListeners($event); + if (empty($events)) { + return; + } + while ($events->valid()) { + /** @var EventDispatchInterface $interface */ + $interface = $events->current(); + $interface->onHandler(); + if ($interface->stopPagination()) { + break; + } + $events->next(); + } + } + +} diff --git a/System/Events/EventDispatchInterface.php b/System/Events/EventDispatchInterface.php new file mode 100644 index 00000000..42fb8986 --- /dev/null +++ b/System/Events/EventDispatchInterface.php @@ -0,0 +1,18 @@ +_events[$event])) { + $this->_events[$event] = new SplPriorityQueue(); + } + $this->_events[$event]->insert($handler, $handler->getZOrder()); + } + + + /** + * @param $event + * @return SplPriorityQueue|null + */ + public function getEventListeners($event): ?SplPriorityQueue + { + return $this->_events[$event] ?? null; + } + + +} diff --git a/System/Events/EventProviders.php b/System/Events/EventProviders.php new file mode 100644 index 00000000..88441e1e --- /dev/null +++ b/System/Events/EventProviders.php @@ -0,0 +1,8 @@ +get($class, $construct, $className); + return static::$container->newObject($class, $construct, $className); } else if (is_callable($className, TRUE)) { return call_user_func($className, $construct); } else { @@ -250,7 +250,7 @@ class Snowflake */ public static function setManagerId($workerId): mixed { - if (empty($workerId) || static::isDcoker()) { + if (empty($workerId) || static::isDocker()) { return $workerId; } @@ -267,7 +267,7 @@ class Snowflake */ public static function setProcessId($workerId): mixed { - if (empty($workerId) || static::isDcoker()) { + if (empty($workerId) || static::isDocker()) { return $workerId; } @@ -280,7 +280,7 @@ class Snowflake /** * @return bool */ - public static function isDcoker(): bool + public static function isDocker(): bool { $output = shell_exec('[ -f /.dockerenv ] && echo yes || echo no'); if (trim($output) === 'yes') { @@ -297,7 +297,7 @@ class Snowflake */ public static function setWorkerId($workerId): mixed { - if (empty($workerId) || static::isDcoker()) { + if (empty($workerId) || static::isDocker()) { return $workerId; } @@ -314,7 +314,7 @@ class Snowflake */ public static function setTaskId($workerId): mixed { - if (empty($workerId) || static::isDcoker()) { + if (empty($workerId) || static::isDocker()) { return $workerId; }