- Создано ядро MVC: App, Router, Controller, Model, View, Database - Созданы модели: User, Product, Category, Cart, Order - Созданы контроллеры: Home, Auth, Product, Cart, Order, Page, Admin - Созданы layouts и partials для представлений - Добавлены все views для страниц - Настроена маршрутизация с чистыми URL - Обновлена конфигурация Docker и Apache для mod_rewrite - Добавлена единая точка входа public/index.php
111 lines
2.9 KiB
PHP
111 lines
2.9 KiB
PHP
<?php
|
|
|
|
namespace App\Core;
|
|
|
|
/**
|
|
* Database - Singleton класс для подключения к PostgreSQL
|
|
*/
|
|
class Database
|
|
{
|
|
private static ?Database $instance = null;
|
|
private \PDO $connection;
|
|
|
|
private function __construct()
|
|
{
|
|
$config = require dirname(__DIR__, 2) . '/config/database.php';
|
|
|
|
try {
|
|
$dsn = "pgsql:host={$config['host']};port={$config['port']};dbname={$config['database']}";
|
|
$this->connection = new \PDO($dsn, $config['username'], $config['password']);
|
|
$this->connection->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
|
|
$this->connection->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
|
|
$this->connection->exec("SET NAMES 'utf8'");
|
|
} catch (\PDOException $e) {
|
|
throw new \Exception("Ошибка подключения к базе данных: " . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public static function getInstance(): self
|
|
{
|
|
if (self::$instance === null) {
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
public function getConnection(): \PDO
|
|
{
|
|
return $this->connection;
|
|
}
|
|
|
|
/**
|
|
* Выполнить SELECT запрос
|
|
*/
|
|
public function query(string $sql, array $params = []): array
|
|
{
|
|
$stmt = $this->connection->prepare($sql);
|
|
$stmt->execute($params);
|
|
return $stmt->fetchAll();
|
|
}
|
|
|
|
/**
|
|
* Выполнить SELECT запрос и получить одну запись
|
|
*/
|
|
public function queryOne(string $sql, array $params = []): ?array
|
|
{
|
|
$stmt = $this->connection->prepare($sql);
|
|
$stmt->execute($params);
|
|
$result = $stmt->fetch();
|
|
return $result ?: null;
|
|
}
|
|
|
|
/**
|
|
* Выполнить INSERT/UPDATE/DELETE запрос
|
|
*/
|
|
public function execute(string $sql, array $params = []): bool
|
|
{
|
|
$stmt = $this->connection->prepare($sql);
|
|
return $stmt->execute($params);
|
|
}
|
|
|
|
/**
|
|
* Получить ID последней вставленной записи
|
|
*/
|
|
public function lastInsertId(): string
|
|
{
|
|
return $this->connection->lastInsertId();
|
|
}
|
|
|
|
/**
|
|
* Начать транзакцию
|
|
*/
|
|
public function beginTransaction(): bool
|
|
{
|
|
return $this->connection->beginTransaction();
|
|
}
|
|
|
|
/**
|
|
* Подтвердить транзакцию
|
|
*/
|
|
public function commit(): bool
|
|
{
|
|
return $this->connection->commit();
|
|
}
|
|
|
|
/**
|
|
* Откатить транзакцию
|
|
*/
|
|
public function rollBack(): bool
|
|
{
|
|
return $this->connection->rollBack();
|
|
}
|
|
|
|
// Запрещаем клонирование и десериализацию
|
|
private function __clone() {}
|
|
public function __wakeup()
|
|
{
|
|
throw new \Exception("Десериализация Singleton запрещена");
|
|
}
|
|
}
|
|
|