registerServices($config, $container); Artful::set(DirectionInterface::class, CollectionDirection::class); Artful::set(PackerInterface::class, JsonPacker::class); } /** * @return mixed * * @throws ContainerException * @throws ServiceNotFoundException */ public static function __callStatic(string $service, array $config) { if (!empty($config)) { self::config(...$config); } return self::get($service); } /** * @throws ContainerException */ public static function config(array $config = [], null|Closure|ContainerInterface $container = null): bool { if (self::hasContainer() && !($config['_force'] ?? false)) { return false; } new self($config, $container); return true; } /** * @codeCoverageIgnore * * @throws ContainerException */ public static function set(string $name, mixed $value): void { try { $container = Artful::getContainer(); if ($container instanceof LaravelContainer) { $container->singleton($name, $value instanceof Closure ? $value : static fn () => $value); return; } if (method_exists($container, 'set')) { $container->set(...func_get_args()); return; } } catch (ContainerNotFoundException $e) { throw $e; } catch (Throwable $e) { throw new ContainerException('容器异常: '.$e->getMessage()); } throw new ContainerException('容器异常: 当前容器类型不支持 `set` 方法'); } /** * @codeCoverageIgnore * * @throws ContainerException */ public static function make(string $service, array $parameters = []): mixed { try { $container = Artful::getContainer(); if (method_exists($container, 'make')) { return $container->make(...func_get_args()); } } catch (ContainerNotFoundException $e) { throw $e; } catch (Throwable $e) { throw new ContainerException('容器异常: '.$e->getMessage()); } $parameters = array_values($parameters); return new $service(...$parameters); } /** * @throws ServiceNotFoundException * @throws ContainerException */ public static function get(string $service): mixed { try { return Artful::getContainer()->get($service); } catch (NotFoundExceptionInterface $e) { throw new ServiceNotFoundException('服务未找到: '.$e->getMessage()); } catch (ContainerNotFoundException $e) { throw $e; } catch (Throwable $e) { throw new ContainerException('容器异常: '.$e->getMessage()); } } /** * @throws ContainerNotFoundException */ public static function has(string $service): bool { return Artful::getContainer()->has($service); } public static function setContainer(null|Closure|ContainerInterface $container): void { self::$container = $container; } /** * @throws ContainerNotFoundException */ public static function getContainer(): ContainerInterface { if (self::$container instanceof ContainerInterface) { return self::$container; } if (self::$container instanceof Closure) { return (self::$container)(); } throw new ContainerNotFoundException('容器未找到: `getContainer()` 方法调用失败! 或许你应该先 `setContainer()`'); } public static function hasContainer(): bool { return self::$container instanceof ContainerInterface || self::$container instanceof Closure; } public static function clear(): void { self::$container = null; } /** * @throws ContainerException */ public static function load(string $service, mixed $data = null): void { self::registerService($service, $data); } /** * @throws ContainerException */ public static function registerService(string $service, mixed $data = null): void { $var = new $service(); if ($var instanceof ServiceProviderInterface) { $var->register($data); } } /** * @throws ContainerException * @throws InvalidParamsException * @throws ServiceNotFoundException */ public static function shortcut(string $shortcut, array $params = []): null|Collection|MessageInterface|Rocket { if (!class_exists($shortcut) || !in_array(ShortcutInterface::class, class_implements($shortcut))) { throw new InvalidParamsException(Exception::PARAMS_SHORTCUT_INVALID, "参数异常: [{$shortcut}] 未实现 `ShortcutInterface`"); } /* @var ShortcutInterface $shortcutInstance */ $shortcutInstance = self::get($shortcut); return self::artful($shortcutInstance->getPlugins($params), $params); } /** * @throws ContainerException * @throws InvalidParamsException */ public static function artful(array $plugins, array $params): null|Collection|MessageInterface|Rocket { Event::dispatch(new Event\ArtfulStart($plugins, $params)); self::verifyPlugin($plugins); /* @var Pipeline $pipeline */ $pipeline = self::make(Pipeline::class); /* @var Rocket $rocket */ $rocket = $pipeline ->send((new Rocket())->setParams($params)->setPayload(new Collection())) ->through($plugins) ->via('assembly') ->then(static fn ($rocket) => self::ignite($rocket)); Event::dispatch(new Event\ArtfulEnd($rocket)); if (!empty($params['_return_rocket'])) { return $rocket; } return $rocket->getDestination(); } /** * @throws ContainerException * @throws InvalidParamsException * @throws InvalidResponseException * @throws ServiceNotFoundException */ public static function ignite(Rocket $rocket): Rocket { if (!should_do_http_request($rocket->getDirection())) { return $rocket; } /* @var HttpClientFactoryInterface $httpFactory */ $httpFactory = self::get(HttpClientFactoryInterface::class); /* @var Config $config */ $config = self::get(ConfigInterface::class); if (!$httpFactory instanceof HttpClientFactoryInterface) { throw new InvalidParamsException(Exception::PARAMS_HTTP_CLIENT_FACTORY_INVALID, '参数异常: 配置的 `HttpClientFactoryInterface` 不符合规范'); } Logger::info('[Artful] 准备请求第三方 API', $rocket->toArray()); $http = $httpFactory->create(array_merge($config->get('http', []), $rocket->getPayload()?->get('_http') ?? [])); Event::dispatch(new Event\HttpStart($rocket)); try { $response = $http->sendRequest($rocket->getRadar()); $rocket->setDestination(clone $response) ->setDestinationOrigin(clone $response); } catch (Throwable $e) { Logger::error('[Artful] 请求第三方 API 出错', ['message' => $e->getMessage(), 'rocket' => $rocket->toArray(), 'trace' => $e->getTrace()]); throw new InvalidResponseException(Exception::REQUEST_RESPONSE_ERROR, '响应异常: 请求第三方 API 出错 - '.$e->getMessage(), [], $e); } Logger::info('[Artful] 请求第三方 API 成功', ['rocket' => $rocket->toArray()]); Event::dispatch(new Event\HttpEnd($rocket)); return $rocket; } /** * @throws InvalidParamsException */ protected static function verifyPlugin(array $plugins): void { foreach ($plugins as $plugin) { if (is_callable($plugin)) { continue; } if ((is_object($plugin) || (is_string($plugin) && class_exists($plugin))) && in_array(PluginInterface::class, class_implements($plugin))) { continue; } throw new InvalidParamsException(Exception::PARAMS_PLUGIN_INCOMPATIBLE, "参数异常: [{$plugin}] 插件未实现 `PluginInterface`"); } } /** * @throws ContainerException */ private function registerServices(array $config, null|Closure|ContainerInterface $container = null): void { foreach ($this->coreService as $service) { self::registerService($service, ContainerServiceProvider::class == $service ? $container : $config); } } }