PHP triky

Weblog o elegantním programování v PHP pro mírně pokročilé

Adminer 5.4.0

Delší dobu se v Admineru neobjevila žádná závažná chyba, tak jsem nemusel vydávat novou verzi, až počet změn hodně nabobtnal.

  • Při vyhledávání ve všech tabulkách se dá nově zadat jakýkoliv operátor. Dřív se vždy používalo =.
  • Při GROUP BY selectu (např. vybrání sloupce a k tomu nějaké agregační funkce) se výsledky už neřadí sestupně.
  • V SQL příkazu lze nově exportovat i zadaný příkaz (bug #1092).
  • V přehledu databáze jsem přidal odkazy na sekce (např. na rutiny), což se hodí, když je toho v databázi hodně.
  • Při importu se zobrazí varování v případě překročení max_file_uploads.
  • V seznamu existujících přihlášení v menu přihlašovací stránky se za uživatelským jménem zobrazuje @, i pokud je server prázdný.
  • V přehledu databáze se u materializovaných pohledů zobrazuje velikost dat a indexů.
  • Při zvýrazňování syntaxe se nově kromě tabulek odkazují i rutiny.
  • Ve změně struktury tabulky se přesune focus na nově přidaný sloupec.
  • Do hlášek o provedených SQL příkazech jsem přidal tlačítko na jejich zkopírování.
  • Po nahrání více řádek ve výpisu se spouští zvýrazňování syntaxe, hlavně kvůli JSON sloupcům.
  • Je možné se připojit k serveru pomocí IPv6 adresy (bug #1095). Dřív se chápala jako server s portem.
  • V MySQL jsem opravil ukládání enum s prázdnou hodnotou (bug #1152).
  • V MySQL 5.0- se nenahrávají informace o rozdělených tabulkách (bug #1099).
  • V MariaDB se parsuje COLLATE v definici rutiny (bug #1104).
  • V Elasticsearch lze smazat alias.

Další spousta změn je pro PostgreSQL, který jsem začal více používat:

  • U zděděných tabulek se zobrazuje struktura.
  • Zobrazují se výrazy indexů, např. lower(filename).
  • K operátorům jsem přidal SQL, který dovoluje hledat podle libovolného SQL výrazu.
  • V menu se skrývají jen oddíly, ne všechny zděděné tabulky.
  • Lze porovnávat JSON sloupce (bug #1107).
  • Kromě textových sloupců se při výpisu zkracují i hodnoty ve sloupcích hstore.
  • S operátorem interval se hodnoty předávají jako řetězce.
  • Opravil jsem volání funkcí s bezejmennými parametry.
  • Opravil jsem volání funkcí vracejících tabulky.
  • Uživatelské typy obsahující file už se neberou jako blob (bug #1118).
  • Při exportu databáze se respektuje požadavek na její DROP a CREATE (bug #1140).
  • Ve verzi 11 a nižší jsem opravil duplicitní oid při získávání informací o tabulce (bug #1089).

Pluginy:

  • Přidal jsem metody afterConnect(), processList() a killProcess().
  • Vytvořil jsem plugin pro zobrazení čísla řádku ve výpisu (bug #1106).
  • Vytvořil jsem plugin pro nastavení timeoutu dotazů.
Jakub Vrána, Adminer, 8.9.2025

Php-Wasm

WebAssembly je pozoruhodná technologie. Umožňuje běh binárních programů v různých prostředích, především pak v prohlížečích. Do Wasm se dá kompilovat z různých programovacích jazyků, pro PHP existuje Php-Wasm. To umožňuje spouštět PHP kód v prohlížeči na počítači klienta. Výhoda je mnohem rychlejší odezva, než když se data pro zpracování posílají na server a zpátky, dále pak nezatěžování serveru. Další využití je, pokud spouštěnému kódu nevěříte a nechcete si ho pouštět na server.

Php-Wasm jsem si vyzkoušel na demu PhpShrink:

let highlightShrink;
(async function () {
	// momentálně je potřeba použít alfa verzi, vydaná 0.0.8 toto nepodporuje
	const { PhpWeb } = await import('https://cdn.jsdelivr.net/npm/php-wasm@0.0.9-alpha-29/PhpWeb.mjs');
	const php = new PhpWeb({files: [
		// namapujeme URL jako soubor v prostředí Wasm; URL musí vrátit PHP kód nezpracovaný serverem
		{name: 'phpShrink.php', url: 'https://raw.githubusercontent.com/vrana/PhpShrink/refs/heads/main/phpShrink.php'}
	]});
	// výstup a chybový výstup nepoužíváme, tak ho jen pošleme do konzole
	php.addEventListener('output', event => console.log(event.detail));
	php.addEventListener('error',  event => console.error(event.detail));
	// zpracuje PHP kód z URL zadaného výše
	await php.run('<?php include "./phpShrink.php"; ?>');
	// největší magie - PHP funkci zpřístupní do JavaScriptu
	highlightShrink = await php.x`function ($input) { return highlight_string(phpShrink($input), true); }`;
	shrink();
	document.getElementById('input').oninput = shrink;
})();

function shrink() {
	document.getElementById('output').innerHTML = highlightShrink(document.getElementById('input').value);
}

Php-Wasm má mnohem širší možnosti, kód se dá definovat i rovnou ve <script type="text/php">, existuje také CGI umožňující třeba i běh WordPressu v prohlížeči.

Jakub Vrána, Seznámení s oblastí, 15.8.2025

SimpleXML: jmenné prostory

Extenzi SimpleXML mám v oblibě pro velice jednoduchou práci s XML dokumenty. Konec konců jsem se jí nechal inspirovat při tvorbě NotORM. Např. pro získání hodnoty atributu <meta charset> se dá použít jednoduché $html->meta["charset"]. Pro složitější dotazy se dá použít XPath, např. všechny tabulky v dokumentu pomocí $html->xpath("//table").

Když dokument obsahuje jmenné prostory, tak je práce složitější a část magie mizí. Mějme takovýto dokument:

<movies xmlns="http://default" xmlns:a="http://a">
 <movie xml:id="movie1" a:link="IMDB">
  <a:actor>Onlivia Actora</a:actor>
 </movie>
</movies>

Dá se s ním pracovat takhle:

<?php
$movies = simplexml_load_string($file);

// Namespace http://www.w3.org/XML/1998/namespace is available as "xml".
echo $movies->movie->attributes("xml", true)["id"] . "\n";

// Namespaced attributes can be accessed with attributes().
echo $movies->movie->attributes("a", true)["link"] . "\n";

// Using namespace URI allows document to use any namespace alias.
echo $movies->movie->attributes("http://a")["link"] . "\n";

// Children can be accessed with children().
echo $movies->movie->children("http://a")->actor . "\n";

// Using xpath() with namespace requires registering it first.
$movies->registerXPathNamespace("a", "http://a");
echo count($movies->xpath("//a:actor")) . "\n";

// Even the default namespace must be registered.
$movies->registerXPathNamespace("default", "http://default");
echo count($movies->xpath("//default:movie")) . "\n";
?>
Jakub Vrána, Seznámení s oblastí, 6.5.2025

Adminer 5.3.0 - možnosti indexů

Největší změna v Admineru 5.3.0 je podpora algoritmu indexu (bug #1030). PostgreSQL podporuje šest algoritmů, MySQL jen dva a to jen u některých typů tabulek.

Druhou novinkou jsou částečné indexy. V PostgreSQL lze nastavit podmínku, při které se hodnota do indexu uloží (bug #1048).

Do PostgreSQL a CockroachDB jsem přidal možnost vytvářet tabulky s oddíly (bug #1031). PostgreSQL bohužel nedovoluje oddíly změnit po vytvoření tabulky a automatická migrace (jako ji v některých případech dělá ovladač pro SQLite) mi přišla trochu riskantní. S tím souvisí i přesun oddílů v PostgreSQL z menu do rodičovské tabulky.

Další změny jsou menší:

  • Výsledky funkcí vracejících číslo (např. COUNT(*) nebo CHAR_LENGTH() jsem nechal zarovnat doprava stejně jako číselné sloupce. V PostgreSQL se z hodnoty COUNT(*) vytvoří odkaz stejně jako v MySQL.
  • Autocomplete SQL nyní podporuje aliasy tabulek.
  • Verze 5.1.1 rozbila vytváření uložených funkcí, nová verze typovou chybu opravuje (bug #1053).
  • Akce sloupečků zobrazené po najetí myši mají nyní rámeček (bug #1072).
  • Hodnoty typu money jsem nechal zarovnat doprava stejně jako čísla (bug #1071).
  • V MySQL jsem opravil varování při zobrazení dat z tabulek s fulltext indexem (bug #1036).
  • Verze 5.1.1 rozbila připojování přes localhost:3306, zkoušel se hledat socket 3306. Nová verze to opravuje (bug #1057).
  • V PostgreSQL mohou uživatelské funkce vracet tabulku, kterou Adminer při zavolání funkce nyní ukáže (bug #1040).
  • Do PostgreSQL jsem přidal operátor NOT ILIKE (bug #1062).
  • V Editoru jsem opravil vyhledávání podle sloupců bit a enum (bug #1062).
  • Pokud uživatelský styl v souboru adminer.css podporuje přepínání do tmavého režimu, tak Adminer svůj tmavý styl nevypne.
  • Pluginy můžou v metodě css() určit, zda styl podporuje tmavý vzhled. Výchozí implementace u souboru adminer.css zkoumá přítomnost prefers-color-scheme: dark.
  • Pluginům jsem dal možnost přidat třídu do <body class>. Adminer tam přidává třídu adminer, Editor třídu editor.
  • Přibyl překlad do hindštiny.
Jakub Vrána, Adminer, 4.5.2025

Adminer 5.2.0

Uživatelsky nejviditelnější změna v Admineru 5.2.0 je našeptávač pro SQL. Dále jsem udělal několik drobnějších změn:

  • Při hromadné editaci záznamů přes odkaz Změnit se nevytvoří políčka pro hodnotu NULL. Tento jednoduchý formulář totiž nerozlišuje prázdný řetězec a NULL, takže pouhé uložení nezměněného formuláře přepsalo NULL na prázdný řetězec. Políčka s hodnotou NULL se v tomto formuláři dají změnit pomocí Ctrl+klik, což používám primárně já (bug #967).
  • Předchozí verze rozbila akce cizích klíčů.
  • V MySQL se v GROUP BY dotazech zobrazuje počet nalezených řádek, což rozbila předchozí verze.
  • SQL příkaz pro PostgreSQL podporuje příkaz COPY FROM stdin, který generuje pgdump (bug #942).
  • V ne-MySQL se -- bere jako začátek komentáře, v MySQL za tím musí být ještě mezera (bug SF-842).
  • V exportu MS SQL je počet řádků v jednom INSERT omezen na 1000 (bug #983).
  • Udělal jsem maličký facelift – přidal logo, zaoblil nějaké rohy, přidal nějaké stíny. Alternativní designy jsem upravil, aby fungovaly na mobilu.
  • Možnost rozesílat hromadné e-maily z Adminer Editoru jsem přesunul do pluginu. Jednak to asi není moc používané a jednak to jde teď naopak použít i v Admineru.
  • Do pluginů jsem přidal možnost překladů. Ty nově můžou dědit ze třídy Adminer\Plugin, která jim dá metodu lang(). Pokud pluginy používají nějaké fráze z Admineru, tak můžou nadále volat Adminer\lang().
  • Pro Adminer Editor jsem přidal plugin pro jednodušší nastavení ovladače, serveru a databáze.

Konfigurace

Před představením dalších dvou nových pluginů udělám trochu odbočku. Čas od času po mně někdo chce, abych třeba změnil odkazy na tabulky z menu. Že používá jen odkaz pro výpis dat, druhý odkaz je zbytečný a způsobuje menší přehlednost menu. Někdo naopak usoudil, že je zbytečný odkaz pro výpis dat a nechal jen odkaz na strukturu tabulky. Další lidi po mně chtějí, ať pro to přidám možnost konfigurace. Nebo ať o podobných věcech nechám hlasovat uživatele. Většinou to rychle smetu ze stolu pomocí „použij plugin nebo vlastní vzhled“, ale zamyslel jsem se nad tím trochu víc.

Chování Admineru ovlivňují tři různé strany:

  • Vývojář: Rozhoduje o výchozím chování a poskytuje hooky pro pluginy
  • Admin: Instaluje Adminer, vybírá pluginy a výchozí vzhled
  • Uživatel: Používá Adminer

Díky tomu, že je Adminer k dispozici v jednom souboru a že jeho cílová skupina jsou především programátoři, tak Admin je často ta stejná osoba jako Uživatel. Ale zdaleka to neplatí vždy. Pokud si ve WordPressu nainstaluji plugin pro Adminer, tak jsem jeho Uživatel, ale ne jeho Admin. Nebo pokud mi hosting dá Adminer předinstalovaný.

Adminer na Uživatele myslí jen trochu. Třeba kromě vzhledu v souboru adminer.css (o tom rozhoduje Admin) existuje i plugin designs, který vzhledy dovoluje přepínat uživateli.

screenshot

Nově přidávám plugin config, který dovoluje chování Admineru změnit Uživateli. Nastavení ukládá do cookie. Pokud chci stejné nastavení použít na více zařízeních, tak se dá URL s konfigurací uložit do záložky a tu pak otevřít jinde. Samotný plugin config momentálně dovoluje vypnout načítání vzhledu adminer.css a použít vestavěný vzhled Admineru. Dají se na něj ale napojit další pluginy.

Druhý plugin s nastavením pro uživatele je menu-links, který dovoluje změnit ono chování odkazů na tabulky v menu. Dá se použít jako normální plugin, kde může Admin přepnout chování natvrdo všem uživatelům. Ale v kombinaci s config si Uživatel toto chování může změnit sám pro sebe.

Možností konfigurace uživateli možná časem přidám víc. Zvažoval jsem i dát uživatelům možnost vypnout některé pluginy, ale třeba možnost vypnout bezpečnostní pluginy by mít neměli. Časem možná plugin config integruji i přímo do Admineru, stejně jako se to stalo s pluginem plugin, který dovoloval pluginy používat.

Adminer 5.2.1 opravuje především chyby odhalené díky typové kontrole.

Jakub Vrána, Adminer, 8.4.2025

Starší články naleznete v archivu.

avatar © 2005-2025 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.