Popis tříd k přístupu k databázi¶
Tento dokument popisuje hlavní PHP třídy v core/database. Cílem je přiblížit novému vývojáři, jak třídy fungují, jak spolu souvisejí a co je jejich odpovědnost.
Třída DB¶
Statická brána k databázovému rozhraní. Poskytuje přístup k metodám přes statické volání, ale veškerou práci deleguje na vnitřní instanci třídy PDOHandler.
Automatická inicializace (lazy loading)¶
Třída DB využívá lazy initialization - připojení k databázi se vytvoří automaticky při prvním volání libovolné metody (query(), results(), row(), atd.).
Není potřeba:
- Manuálně volat
DB::fromUrl() - Includovat
app/database.php - Dělat cokoliv na inicializaci - DB se postará automaticky
Příklad:
// Automaticky se inicializuje při prvním dotazu - bez jakéhokoli require
$users = DB::results("SELECT * FROM users");
echo count($users); // Funguje okamžitě!
Interně je připojení inicializováno prostřednictvím ensureInitialized() metody, která se volá automaticky před prvním SQL dotazem.
Klíčové public metody¶
DB::fromUrl(string $url)– explicitní inicializace zmysql://nebopgsql://URLDB::query($sql, $params = [])– provede SQL dotazDB::results($sql, $params = [], asArray: false)– vrátí více řádkůDB::row($sql, $params = [], asArray: false)– vrátí jeden řádekDB::var($sql, $params = [])– vrátí jednu hodnotuDB::col($sql, $params = [])– vrátí jeden sloupecDB::test($sql, $params = [])– debug helper: vypíše finální SQL s dosazením parametrů (bez spuštění)DB::beginTransaction(),commit(),rollback()– správa transakcíDB::set($fields)– generuje SET část dotazuDB::setExcluded($fields, $exclude = [])– generuje PostgreSQLEXCLUDED.columnčást proON CONFLICT DO UPDATEDB::getLog()– vrátí pole logovaných dotazů s časy
DB::fromUrl() místo DB::init()¶
Původní ruční inicializace přes DB::init(...) byla nahrazena URL-based API:
DB používá lazy load přes app/database.php, takže v běžném CMS kódu tuto metodu volat nemusíš. Je důležitá hlavně pro explicitní inicializaci druhého připojení nebo mimo standardní bootstrap.
Třída PDOHandler¶
Třída, která drží instanci PDO a vykonává reálné SQL operace. Je použita interně v DB::$DB. Lze ji použít přímo jako instanci pro sekundární DB připojení.
Klíčové public metody¶
__construct(...)– vytvoření připojenístatic fromUrl(string $url): self– factory z DATABASE_URL stringuquery(),results(),row(),var(),col()– stejné jako DBbeginTransaction(),commit(),rollback()– transakcegetLog(): array– logované dotazy s časy (dědí z Base)
Drivery a DSN¶
PDOHandler nově rozlišuje driver už při konstrukci.
mysql/mariadbvětev používá MySQL DSN scharset=utf8mb4pgsqlvětev používá PostgreSQL DSNfromUrl()rozpoznámysql://,pgsql://,postgresql://,postgres://- Default port je
3306pro MySQL a5432pro PostgreSQL
To samé API tedy funguje nad oběma databázemi, rozdíl je jen v použitém driveru.
Proč není veřejné prepare()/execute() API¶
PDO je nakonfigurováno s ATTR_EMULATE_PREPARES = false. To znamená, že každé volání DB::query(), DB::results() atd. interně provede server-side prepare + execute.
Veřejné metody DB::prepare() a DB::execute() už v této vrstvě nejsou. Konzumující kód má používat přímo vyšší API:
Interně PDOHandler stále používá prepare()/execute() pro každý parametrizovaný dotaz, ale není to vystaveno jako public API, protože to nepřináší další užitek pro běžný CMS kód.
Třída Base¶
Poskytuje základní infrastrukturu – výsledky dotazů, stavové proměnné a možnosti nastavení.
Klíčové vlastnosti¶
$lastQuery,$lastError,$queryError,$lastResult,$insertId,$affectedRows,$numRows$driver– aktivní databázový driver (mysqlnebopgsql)$quoteChar– znak pro quoting identifikátorů (`pro MySQL,"pro PostgreSQL)setting(array $array)set(array $fields, array $exclude = [], bool $useValues = false)setExcluded(array $fields, array $exclude = [])
Quoting a generování SQL¶
Base::set() už nepoužívá napevno backticky. Místo toho pracuje s $quoteChar, takže stejný helper funguje jak pro MySQL, tak pro PostgreSQL.
Pro PostgreSQL upsert je navíc přidaná metoda setExcluded(), která generuje pravou stranu pro ON CONFLICT DO UPDATE:
$sql = 'INSERT INTO t ("id", "name") VALUES (:id, :name)
ON CONFLICT (id) DO UPDATE SET ' . DB2::setExcluded($set, ['id']);
Výstup bude ve stylu:
Naopak MySQL-specific REPLACE už se v DB vrstvě nepovažuje za standardní write query.
Třída DB2¶
DB2 je druhá statická DB vrstva nad stejným API jako DB. Dědí z DB, ale drží vlastní statické properties, takže má oddělený connection state, query log i metadata výsledků.
K čemu slouží¶
- PostgreSQL připojení vedle hlavní CMS databáze
- Integrace s externím systémem
- Druhá databáze se samostatným lifecycle
Důležité chování¶
DBse inicializuje lazy přesapp/database.phpDB2nepodporuje lazy inicializaci- Před prvním použitím je nutné zavolat
DB2::fromUrl(...) - Pokud to neuděláš,
DB2::ensureInitialized()vyhodí výjimku
Příklad¶
use Core\Database\DB2;
DB2::fromUrl('pgsql://user:pass@host/dbname');
$row = DB2::row('SELECT * FROM article WHERE id = ?', [$id]);
Vztahy mezi třídami¶
classDiagram
class DB {
+static fromUrl()
+static query()
+static beginTransaction()
+static setExcluded()
}
class PDOHandler {
+query()
+results()
+row()
+fromUrl()
}
class Base {
+lastQuery
+lastError
+driver
+quoteChar
+setting()
}
DB --> PDOHandler : obsahuje instanci
DB2 --|> DB : dědí
PDOHandler --> Base : dědí
Sekundární databáze (PDOHandler přímo)¶
Pro výjimečné případy připojení k externí nebo partnerské databázi se použije PDOHandler přímo jako instance — bez statické třídy.
Kdy se to používá¶
- Integrace se starším systémem (legacy databáze)
- Partnerský web / subdoména s vlastní DB
- Datový sklad s jinými přihlašovacími údaji
V 99% projektů na Petrovo CMS stačí jen DB.
Použití¶
use Core\Database\PDOHandler;
$db2 = PDOHandler::fromUrl(env('PARTNER_DATABASE_URL'));
$rows = $db2->results("SELECT * FROM products WHERE active = ?", [1]);
$row = $db2->row("SELECT * FROM orders WHERE id = ?", [$id]);
$db2->getLog(); // timing k dispozici
Nebo s přímými parametry:
Rozdíl od DB¶
| Aspekt | DB | PDOHandler instance |
|---|---|---|
| Inicializace | Automatická (lazy) | new nebo fromUrl() |
| Přístup | Statický DB:: |
Instance $db2-> |
| Debug bar | ✅ DB::getLog() | $db2->getLog() (samostatné) |
| API metody | Stejné | Stejné |
Shrnutí (důležité pro vývojáře)¶
- Používej
DB::pro veškeré databázové operace — auto-init, žádný setup - Vždy používej parametrizované dotazy (
DB::query($sql, $params)) - Výsledky vrací objekty (přístup
->columnName); pole jen pokud explicitněasArray: true Baseposkytuje metadata:lastQuery,lastError,affectedRows,insertId,getLog()- Pro druhé statické připojení použij
DB2::fromUrl(env('...')) - Pro sekundární databázi jako instanci použij
PDOHandler::fromUrl(env('...'))nebonew PDOHandler(...)