Adminer používá pro práci s databázovým systémem tři druhy metod:
query
se s extenzí MySQL přeloží na mysql_query
.getTables
se v MySQL přeloží na SHOW TABLES
, s jinými systémy to může položit dotaz do databáze information_schema
.getVals
položí dotaz a jeho výsledek vrátí v poli.Jak tyto tři druhy metod propojit?
Vytvoříme abstraktní třídu se společnými metodami, jejího potomka s metodami specifickými pro systém a jejího potomka s metodami pro extenzi. Asi takhle (kód je zjednodušen):
<?php abstract class Connection { abstract function query($query); abstract function getTables(); function getVals($query) { $this->query($query); // ... } } abstract class ConnectionMysql extends Connection { function getTables() { return $this->getVals("SHOW TABLES"); } } class ConnectionMysqlMysql extends ConnectionMysql { function query($query) { return mysql_query($query); } } $connection = new ConnectionMysqlMysql; $connection->query(""); $connection->getTables(); $connection->getVals(""); ?>
Nevýhodu vidím v tom, že je všechno smíchané pohromadě.
<?php abstract class Database { protected $connection; function __construct(Connection $connection) { $this->connection = $connection; } abstract function getTables(); function getVals($query) { $this->connection->query($query); // ... } } class DatabaseMysql extends Database { function getTables() { return $this->getVals("SHOW TABLES"); } } interface Connection { function query($query); } class ConnectionMysql implements Connection { function query($query) { return mysql_query($query); } } $connection = new ConnectionMysql; $database = new DatabaseMysql($connection); $connection->query(""); $database->getTables(); $database->getVals(""); ?>
Nelíbí se mi, že se v metodách uvnitř Database
(kterých je naprostá většina) musí přistupovat k vlastnosti $connection
(kterou potřebují skoro všechny metody).
Společné metody by mohly být statické a dostávat konexi v parametru. Tím pádem by to rovnou mohly být globální funkce.
<?php function getVals($connection, $query) { $connection->query($query); // ... } abstract class Database { protected $connection; function __construct(Connection $connection) { $this->connection = $connection; } abstract function getTables(); } class DatabaseMysql extends Database { function getTables() { return getVals($this->connection, "SHOW TABLES"); } } interface Connection { function query($query); } class ConnectionMysql implements Connection { function query($query) { return mysql_query($query); } } $connection = new ConnectionMysql; $database = new DatabaseMysql($connection); $connection->query(""); $database->getTables(); getVals($connection, ""); ?>
Nelíbí se mi, že musím společným metodám (nebo funkcím) konexi předávat v parametru.
Koukal jsem se, jak je to udělané v Dibi, a to se mi moc nelíbí. Společné metody jsou v jedné třídě, metody specifické pro extenzi v druhé třídě – to je v pořádku. Metody specifické pro databázový systém (např. getIndexes
) jsou ale zkopírované do ovladačů pro jednotlivé extenze – programování metodou copy–paste se snažím zásadně vyhýbat. Podle mě tyto metody do Dibi ani nepatří, to ale řešení neospravedlňuje.
V Admineru to je zatím tak, že kromě metod specifických pro extenzi jde o globální funkce používající globální proměnnou, což je asi nejúspornější, ale nelíbí se mi to.
Diskuse je zrušena z důvodu spamu.