165 lines
4.3 KiB
PHP
165 lines
4.3 KiB
PHP
<?php
|
||
|
||
namespace App\Core;
|
||
|
||
/**
|
||
* App - главный класс приложения
|
||
*/
|
||
class App
|
||
{
|
||
private Router $router;
|
||
private static ?App $instance = null;
|
||
|
||
public function __construct()
|
||
{
|
||
self::$instance = $this;
|
||
|
||
// Регистрируем автозагрузчик сразу
|
||
$this->registerAutoloader();
|
||
|
||
$this->router = new Router();
|
||
}
|
||
|
||
/**
|
||
* Получить экземпляр приложения
|
||
*/
|
||
public static function getInstance(): ?self
|
||
{
|
||
return self::$instance;
|
||
}
|
||
|
||
/**
|
||
* Получить роутер
|
||
*/
|
||
public function getRouter(): Router
|
||
{
|
||
return $this->router;
|
||
}
|
||
|
||
/**
|
||
* Инициализация приложения
|
||
*/
|
||
public function init(): self
|
||
{
|
||
// Запускаем сессию
|
||
if (session_status() === PHP_SESSION_NONE) {
|
||
session_start();
|
||
}
|
||
|
||
// Настраиваем обработку ошибок
|
||
$this->setupErrorHandling();
|
||
|
||
// Загружаем маршруты
|
||
$this->loadRoutes();
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* Регистрация автозагрузчика классов
|
||
*/
|
||
private function registerAutoloader(): void
|
||
{
|
||
spl_autoload_register(function ($class) {
|
||
// Преобразуем namespace в путь к файлу
|
||
$prefix = 'App\\';
|
||
$baseDir = dirname(__DIR__) . '/';
|
||
|
||
$len = strlen($prefix);
|
||
if (strncmp($prefix, $class, $len) !== 0) {
|
||
return;
|
||
}
|
||
|
||
$relativeClass = substr($class, $len);
|
||
$file = $baseDir . str_replace('\\', '/', $relativeClass) . '.php';
|
||
|
||
if (file_exists($file)) {
|
||
require $file;
|
||
}
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Настройка обработки ошибок
|
||
*/
|
||
private function setupErrorHandling(): void
|
||
{
|
||
$config = require dirname(__DIR__, 2) . '/config/app.php';
|
||
|
||
if ($config['debug'] ?? false) {
|
||
error_reporting(E_ALL);
|
||
ini_set('display_errors', '1');
|
||
} else {
|
||
error_reporting(0);
|
||
ini_set('display_errors', '0');
|
||
}
|
||
|
||
set_exception_handler(function (\Throwable $e) {
|
||
$this->handleException($e);
|
||
});
|
||
|
||
set_error_handler(function ($severity, $message, $file, $line) {
|
||
throw new \ErrorException($message, 0, $severity, $file, $line);
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Обработка исключений
|
||
*/
|
||
private function handleException(\Throwable $e): void
|
||
{
|
||
$config = require dirname(__DIR__, 2) . '/config/app.php';
|
||
|
||
http_response_code(500);
|
||
|
||
if ($config['debug'] ?? false) {
|
||
echo "<h1>Ошибка приложения</h1>";
|
||
echo "<p><strong>Сообщение:</strong> " . htmlspecialchars($e->getMessage()) . "</p>";
|
||
echo "<p><strong>Файл:</strong> " . htmlspecialchars($e->getFile()) . ":" . $e->getLine() . "</p>";
|
||
echo "<pre>" . htmlspecialchars($e->getTraceAsString()) . "</pre>";
|
||
} else {
|
||
echo View::render('errors/500', [], 'main');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Загрузка маршрутов
|
||
*/
|
||
private function loadRoutes(): void
|
||
{
|
||
$routesFile = dirname(__DIR__, 2) . '/config/routes.php';
|
||
|
||
if (file_exists($routesFile)) {
|
||
$router = $this->router;
|
||
require $routesFile;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Запуск приложения
|
||
*/
|
||
public function run(): void
|
||
{
|
||
$uri = $_SERVER['REQUEST_URI'] ?? '/';
|
||
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
|
||
|
||
// Удаляем базовый путь, если он есть
|
||
$basePath = '/cite_practica';
|
||
if (strpos($uri, $basePath) === 0) {
|
||
$uri = substr($uri, strlen($basePath));
|
||
}
|
||
|
||
// Если URI пустой, делаем его корневым
|
||
if (empty($uri) || $uri === false) {
|
||
$uri = '/';
|
||
}
|
||
|
||
try {
|
||
$this->router->dispatch($uri, $method);
|
||
} catch (\Exception $e) {
|
||
$this->handleException($e);
|
||
}
|
||
}
|
||
}
|
||
|