PHP triky

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

Adminer 5.4.2

Adminer 5.4.2 opravuje bezpečnostní chybu DoS: útočník může Admineru podstrčit nesprávně formátovanou verzi a Adminer se pak všem uživatelům na tomto serveru odmítne nahrát. Chyba postihuje verze 4.6.2 až 5.4.1. Pokud nemůžete Adminer aktualizovat, dá se chyba potlačit tak, že souboru adminer.version v dočasném adresáři (obvykle hodnota upload_tmp_dir) seberete práva zápisu.

Způsob kontroly nové verze byl dříve dost komplikovaný – z adminer.org se nahrál <iframe>, ten pomocí postMessage poslal informaci zpátky Admineru, který ji uložil do cookie a také do souboru na serveru. Tento soubor se vytvářel kvůli uživatelům s vypnutými cookies, kteří jinak server Admineru bombardují žádostí o novou verzi při každém požadavku. Aby soubor nemohl nikdo podstrčit, tak byl podepsaný – a právě při ověřování podpisu mohlo dojít k DoS.

Kontrolu nové verze jsem teď díky CORS dramaticky zjednodušil – Adminer se ptá adminer.org rovnou přes fetch a novou verzi ukládá jen do cookie. Snad mi to nesloží server. Připomínám, že kontrola nové verze se pomocí pluginu dá přepnout na GitHub, nebo úplně vypnout.

Další změny

  • V editačním formuláři se JSON vypisuje hezky.
  • Při změně tabulky lze upravovat víceřádkové generované hodnoty.
  • Z textů, které začínají // a vypadají jako URL, se nyní vytváří odkaz stejně jako když začínají https://.
  • Některé ovladače v pluginech vracejí jako hodnoty tabulky pole. Toto pole se teď vykresluje jako vnořená tabulka.
  • Některé databáze mají právo pro řazení podle sloupce. Adminer ho nyní respektuje při vytváření odkazů v záhlaví tabulky.
  • V editačním formuláři se nyní zobrazují i hodnoty, které se nedají upravit. To jsou jednak generované sloupce a jednak sloupce bez práva modifikace (u některých databází např. auto increment).
  • Při výpisu dat se zkracují textové sloupce. Ale typů, které se zkracovaly, postupně přibývalo, tak jsem podmínku znegoval – nyní se zkracuje vše kromě čísel a datumů.
  • Pro ošetření hodnot cookie se používalo urlencode. To asi někdy může způsobit nějaké komplikace, tak jsem to přehodil na rawurlencode. (bug #1208)
  • V TSV exportu se do uvozovek zavíraly i hodnoty s čárkou. To sice ničemu nevadilo, ale nebylo to pěkné. (bug #1238)
  • V MariaDB není název checků unikátní, takže se mohly zobrazit i checky z jiné tabulky. (bug #1135)

PostgreSQL

  • Při vytváření tabulky se podle názvu sloupce nabízí vytvoření cizího klíče stejně jako to už 16 let dělá Adminer v MySQL. Změna přitom byla na pár řádek. Těch člověko-hodin, co jsem tím mohl ostatním ušetřit…
  • V exportu checků chyběly závorky.
  • … a naopak se duplikovalo DEFERRABLE u cizích klíčů.
  • Lze vytvářet NOT DEFERRABLE cizí klíče.
  • V exportu sekvencí a pohledů se nyní uvádí schéma stejně jako u tabulek.
  • Opravil jsem zobrazování složitých generovaných sloupců.
  • Unikátní částečné klíče se nyní označují jako unikátní. (bug #1172)
  • U zděděných tabulek se správně zobrazují tabulky z jiných schémat. (bug #1221)
  • Naopak všude kromě PostgreSQL se zobrazují explicitně vytvořené NOT NULL checky. (bug #1237)

Pluginy dostaly metody showVariables() a showStatus() (bug #1157). Také mohou být v jakémkoliv jmenném prostoru, pokud dědí z Adminer\Plugin.

Sponzoři

Mezi sponzory Admineru chci po první vlaštovce PikaPods přivítat také AI-Text-Humanizer.com.

Jakub Vrána, Adminer, 8.2.2026

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

Starší články naleznete v archivu.

avatar © 2005-2026 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.