app = AppFactory::create(); $this->loadSettings(); $this->loadRoutes(); $this->loadTwig(); return $this->app; } /** * Возвращает объект приложения * * @return Kernel */ public static function instance(): Kernel { return self::$instance ??= new self(); } /** * Загружает файл .env или .env.$env * * @param string $env * @return array */ protected function loadDotEnvFile(string $env = ''): array { $filename = empty($env) ? '.env' : ".env.$env"; if (!file_exists(root_path($filename))) { return []; } $dotenv = Dotenv::createMutable(root_path(), $filename); return $dotenv->safeLoad(); } /** * Загружает конфигурационные файлы * * @return void */ protected function loadSettings(): void { $env = $this->loadDotEnvFile(); if (!empty($env['APP_ENV'])) { $this->loadDotEnvFile($env['APP_ENV']); } foreach (glob(config_path() . '/*.php') as $file) { $key = basename($file, '.php'); $this->config += [$key => require_once $file]; } date_default_timezone_set($this->config['app']['timezone'] ?? 'GMT'); } /** * Загружает маршруты * * @return void * @see https://www.slimframework.com/docs/v4/objects/routing.html */ protected function loadRoutes(): void { foreach ($this->config['routes'] as $route) { if (is_array($route['method'])) { $definition = $this->app->map($route['method'], $route['path'], $route['handler']); } else { $method = trim($route['method']); $isPossible = in_array($method, ['GET', 'POST', 'OPTIONS', 'PUT', 'PATCH', 'DELETE']); $func = match (true) { $method === '*' => 'any', $isPossible => strtolower($method), default => throw new InvalidArgumentException(sprintf('Неверный HTTP метод %s', $method)) }; $definition = $this->app->$func($route['path'], $route['handler']); } if (!empty($route['name'])) { $definition->setName($route['name']); } } } /** * Загружает шаблонизатор и его расширения * * @return void * @throws LoaderError * @see https://www.slimframework.com/docs/v4/features/twig-view.html */ protected function loadTwig(): void { $twig = Twig::create(root_path('views'), $this->config['twig']); $twig->addExtension(new IptvTwigExtension()); $this->app->add(TwigMiddleware::create($this->app, $twig)); if ($this->config['twig']['debug']) { $twig->addExtension(new DebugExtension()); } } /** * Возвращает объект подключения к Redis * * @return Redis * @see https://github.com/phpredis/phpredis/?tab=readme-ov-file */ public function redis(): Redis { if (!empty($this->cache)) { return $this->cache; } $options = [ 'host' => $this->config['cache']['host'], 'port' => (int)$this->config['cache']['port'], ]; if (!empty($this->config['cache']['password'])) { $options['auth'] = $this->config['cache']['password']; } $this->cache = new Redis($options); $this->cache->select((int)$this->config['cache']['db']); $this->cache->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_JSON); return $this->cache; } /** * Возвращает объект http-клиента * * @return Client */ public function guzzle(): Client { return $this->httpClient ??= new Client($this->config['http']); } /** * Возвращает значение из конфига * * @param string $key Ключ в формате "config.key" * @param mixed|null $default Значение по умолчанию * @return mixed */ public function config(string $key, mixed $default = null): mixed { $parts = explode('.', $key); return $this->config[$parts[0]][$parts[1]] ?? $default; } /** * Возвращает объект приложения * * @return App */ public function app(): App { return $this->app; } /** * Возвращает объект ini-файла * * @return IniFile */ public function ini(): IniFile { return $this->iniFile ??= new IniFile(); } }