PHP triky
Weblog o elegantním programování v PHP pro mírně pokročilé
Novinky PHP 8.5
Novinky v PHP 8.5:
- Operátor pro řetězení funkcí
|>(nepříliš praktický). - Anonymní funkce lze použít na místě konstant:
const FN = strlen(...); - Předdefinovaný atribut
#[\NoDiscard]pro vynucení použití návratové hodnoty funkce. S ním související přetypování(void)pro zahození návratové hodnoty. - Globálním konstantám lze přiřadit atribut:
#[Deprecated] const A = 1; - Atribut
#[\DelayedTargetValidation]pro odložení kontroly nepodporovaných atributů. - Atribut
#[\Override]lze použít i u vlastností. - Statické vlastnosti můžu mít také asymetrickou viditelnost.
- Fatální chyby (jako překročení maximálního času) mají backtrace.
- Property promotion lze použít s
final. - V hodnotách konstant lze použít přetypování:
const T1 = (int) 0.3; - Operátor
clonelze používat jako funkci s druhým parametrem, který určí novou hodnotu vlastností:$b = clone($a, ['x' => 2]); - Třídy ve jmenném prostoru Uri pro práci s URL podle RFC 3986 a WHATWG.
- Chybové handlery lze získat funkcemi get_error_handler a get_exception_handler.
- Metodou Closure::getCurrent lze získat vlastní closure.
- Funkcí curl_share_init_persistent lze vytvořit cURL handle, který nezanikne po skončení aktuálního požadavku.
- Funkce array_first a array_last jako obdoba
resetaendnepotřebující referenci. - Zaniklo nastavení
disable_classes. - Zastaralé obraty: operátor
`,__sleep()a__wakeup(),$http_response_header.
Adminer 5.4.3
Vyšel Adminer 5.4.3. Opravuje několik nepříliš vážných bezpečnostních chyb:
- Pro obranu proti CSRF se nově používá hlavička Sec-Fetch-Site. Náhodně generovaný token neměl dostatečnou entropii. (GHSA-33j4-hc95-pggg)
- Ošetřuje se REQUEST_URI, které bylo možné zneužít pro nastavení parametrů cookies. (GHSA-c533-9qwm-8w5h)
- Validuje se název databázového serveru. V Oracle se pomocí toho dal vytvořit soubor. (GHSA-r4x9-5m63-3vxw)
- Validuje se verze databázového serveru. Pokud modifikovaný server vrátil neplatný řetězec s verzí, mohlo dojít k XSS. (GHSA-h6jr-7pr6-grgj)
- Pomocí SQL příkazu s 350 000 komentáři se dala v SQLite obejít obrana proti ATTACH. (GHSA-q4f2-39gr-45jh)
- V SQLite chyběla ochrana proti VACUUM INTO. (GHSA-gmx3-g29w-77wf)
- V SQLite se před smazáním databáze nekontrolovalo, jestli je název povolený. (GHSA-6pg3-chwq-wgqc)
- Místo
unserialize()se používájson_decode(). (bug #1289)
Ostatní změny jsou starší, ale dřív jsem je nevydal.
- Tabulky v přehledu lze třídit. (bug #1231)
- Inline editace pomocí Ctrl+klik je deaktivovaná, pokud uživatel nemá právo UPDATE.
- Ve výpisu tabulky se v bublině názvu sloupce zobrazuje typ, teď jsem přidal i informaci o NULL.
- V exportu se pamatují nevybrané položky. (regrese z 5.0.6)
- U cizího klíče se v případě chyby zobrazí nová hodnota.
- Adminer Editor: Sloupec typu
tinyint(1)se zobrazí jako checkbox. (bug #1246, regrese z 5.4.2) - Přibyl chorvatský překlad.
Další změny se týkají PostgreSQL:
Rozčarování z AI
Budoucnost celkem jasně vidím v tom, že AI řeknu, co má udělat a jak si to má zkontrolovat, a ona se bude tak dlouho snažit, dokud to neudělá a kontrola neprojde. Možná mám moc velké nároky, ale schopnosti modelů zatím nejsou tak daleko, aby mi ušetřily práci, pokud chci dosáhnout požadované kvality. Často mi ji naopak přidělají.
PHP_CodeSniffer
Na PHP_CodeSniffer je vidět, že byl navržen v „minulém století“ a pravidla pro něj se píšou strašně nešikovně. Když jsem potřeboval napsat celkem jednoduché pravidlo (kolem vlastností tříd může být 0-1 prázdný řádek), tak jsem to milerád přenechal modelu Claude Opus. Na specifikaci chování i v okrajových případech jsem si dal záležet, zadání mělo asi půl stránky. Model přesto přišel s řešením, které zadání nesplňovalo. Navíc bylo dost pomalé – zkoumalo všechny proměnné v souboru a ne jen vlastnosti. Hodinu jsem se s modelem hádal, ukazoval mu příklady, kde kód nesplňuje zadání, a vysvětloval mu, že takhle napsaný kód je navíc pomalý. Všelijak to záplatoval, řešení bylo čím dál ošklivější a zanášelo nové chyby. Nakonec jsem to celé zahodil a za hodinu si napsal pravidlo po svém – správné, rychlé a elegantní.
Upgrade verzí
Jeden projekt mi běžel na prehistorické verzi Nette. Požádal jsem Claude o převod na moderní verzi Nette, čehož se zhostil velmi dobře – pár problémů tam bylo, ale ty jsme rychle vyřešili. Tady jsem byl spokojen.
Stejně tak u převodu jiného projektu na moderní verzi PHP – převedl odstraněné funkce, našel zastaralé obraty a převedl i je. Při plánování jsme se dohodli, že nemá dělat shim, ale funkce má nahradit přímo v kódu. Trochu mě ale překvapilo, jak tupě převod dělá – hledá regulární výrazy a nahrazuje je něčím jiným – kódu vůbec nerozumí. Vím, že existuje napojení na MCP třeba v Idea, nebo LSP, ale to je trochu složitější rozchodit. V tomto případě regulární výrazy stačily.
Třetí převod verze dopadl katastrofálně – některé soubory nebyly v UTF-8 a Claude rozbil kódování. Chvíli jsem se ho snažil donutit je opravit, on původní verze lovil z nějaké své historie, ale nakonec jsem to vzdal, obnovil původní verzi a nechal ho udělat všechno znovu. Tentokrát s explicitní instrukcí, že některé soubory nejsou v UTF-8 a ať si na to dá pozor. Co myslíte? Dopadlo to úplně stejně a soubory jsem si nakonec převedl sám.
Jazykový model
Od té doby, co si David Grudl (velký popularizátor AI) nechává pomocí AI psát články, tak se nedají číst. Dřív měl břitký styl a věřím, že napsání dobrého textu trvalo řádově déle, než nadiktování poznámek AI s instrukcí, ať z toho udělá článek. Ale obraty jako „Jedna uživatelka nahrála hlasové poznámky z procházek s kočárkem“ tento styl prostě nemají. Dřív jsem rád poslouchal i jeho podcast Na vlnách EKG. Nový podcast Uměligence předčítaný robotickým hlasem se poslouchat fakt nedá, přestože mi je zaměřením mnohem bližší.
Windows
Část mých problémů je způsobena asi i tím, že Claude Code pouštím na Windows. Tam se dá spustit buď v PowerShellu nebo ve WSL. Půlka věcí nefunguje tam, druhá půlka tam. Propojení služeb (které vnímám jako největší skok dopředu) je kvůli tomu o dost komplikovanější. Pokud mám např. Claude spuštěný ve WSL a vývojový server mi běží ve Windows, tak bych Clauda ve WSL chtěl naučit koukat se na výsledky na vývojovém serveru. Sám to protunelovat neumím a když jsem to zadal Claudu, tak si s tím taky neporadil.
Integrace
Kde mi AI docela pomáhá, jsou jednoduché úlohy – hledám nějaké nastavení v Idea a ChatGPT ho celkem spolehlivě najde. Proč ale nemůžu vlastními slovy říct přímo Idea, co chci nastavit? Místo toho je tam úplně stupidní AI generování commit zpráv, které se nedá vypnout.
Stejně tak v Google Sheets – nemůžu si vzpomenout, jak se jmenuje nějaká funkce, tak Gemini řeknu, co potřebuji udělat (nejlépe s konkrétním vstupem) a funkci dostanu. Opět – proč kvůli tomu musím z Google Sheets odcházet (nebo za to platit, když ve vedlejším okně to mám zdarma)?
Co mě baví
Nedávno jsem objevil Wikidata, ze které se dají data získávat jazykem Sparql. Prvních pár dotazů jsem si nechal napsat pomocí AI a učící křivka tedy byla velmi strmá – rychle jsem dostával výsledky, které jsem potřeboval. Ale jak se mé požadavky komplikovaly, tak se do toho AI začala zamotávat a já se s ní víc času musel hádat o tom, že má něco špatně nebo pomale (nebo oboje). Organizaci dat ve Wikidata a způsob jejich dotazování jsem pochopil a dotazy si už většinou snadněji napíšu sám. Nebo u těch vygenerovaných aspoň dokážu rychle identifikovat, pokud je na nich něco špatně a buď to opravit, nebo AI říct, co má špatně.
U toho jsem si uvědomil, co mě při práci vlastně baví – často to není jen samotný výsledek, ale i způsob, jak se k němu dostanu. Něco pochopit a dokázat to aplikovat na nové problémy – to mi přináší radost. Ne hádání se s tupou AI, co zase udělala špatně, nebo spokojení se s neefektivním kódem. Nebaví mě ani konfigurace – nastavit robota, aby si dokázal spustit webový server a v prohlížeči si ověřoval výsledky. U každého projektu se to dělá trochu jinak a vždycky je potřeba to nějak nastavit.
Budoucnost
Modely se rychle zlepšují a s čím měly včera problémy, už dnes obstojně zvládají. Pořád mi ale přijde užitečné, když problému sám rozumím a poznám, když AI něco dělá špatně. Nudné práce bude ubývat, ale pro mě je větší nuda vysvětlovat AI, co má udělat, než problém pochopit a udělat to sám.
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 narawurlencode. (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 prázdné
<textarea>byl problém s autocomplete. (bug #1173) - Vypisované SQL dotazy jsem proudloužil na 10000 znaků. (bug #1186)
- V MySQL se pro získání definice rutin používá
information_schema. (bug #1179) - 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
DEFERRABLEu cizích klíčů. - Lze vytvářet
NOT DEFERRABLEcizí 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 NULLchecky. (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 a Humanize AI Text.
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 BYselectu (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í
enums 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
COLLATEv 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
intervalse 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í
fileuž se neberou jakoblob(bug #1118). - Při exportu databáze se respektuje požadavek na její
DROPaCREATE(bug #1140). - Ve verzi 11 a nižší jsem opravil duplicitní
oidpři získávání informací o tabulce (bug #1089).
Pluginy:
- Přidal jsem metody
afterConnect(),processList()akillProcess(). - Vytvořil jsem plugin pro zobrazení čísla řádku ve výpisu (bug #1106).
- Vytvořil jsem plugin pro nastavení timeoutu dotazů.
Starší články naleznete v archivu.

