Co všechno umí Claude Code

Nedávno jsem Claudovi řekl: „Vypni wifi." A on to udělal – protože ví, jak se to dělá z příkazové řádky. Pak jsem řekl: „Zapni wifi." A on neudělal nic. Protože neměl internet.

Tento zážitek hezky ilustruje, co Claude Code vlastně je. Není to jen chatbot, se kterým si povídáte. Je to nástroj, který má přístup k vašemu počítači a může na něm provádět akce. Může číst a upravovat soubory, spouštět programy, instalovat software, pracovat s daty. Prostě téměř cokoli, co byste normálně dělali ručně.

předchozím článku jsme si ukázali, jak Claude Code nainstalovat. Teď se podíváme na to, k čemu všemu ho můžete využít. A věřte mi – je toho mnohem víc, než byste čekali.

Programování

Začněme tím nejočekávanějším. Claude Code je primárně nástroj pro programátory a v této oblasti skutečně exceluje.

Psaní nového kódu. Popíšete, jakou funkci potřebujete, a Claude ji napíše. Nemusíte znát syntax, nemusíte googlit – prostě řeknete, co má kód dělat, a on ho vytvoří. Tým datových inženýrů z Anthropic takhle nechal Clauda napsat kompletní React aplikaci – 5000 řádků TypeScriptu – přestože sami React neuměli.

Opravy chyb. Hodíte na něj chybovou hlášku a necháte ho, ať najde příčinu a opraví ji. Claude projde váš kód, pochopí kontext a navrhne opravu. Nemusíte trávit hodiny hledáním, kde je problém.

Refaktoring. Máte starý nepřehledný kód? Claude ho vyčistí, rozdělí dlouhé funkce na menší, přejmenuje proměnné na srozumitelné názvy. Jeden vývojář popsal, jak zrefaktoroval 210řádkovou Python funkci na méně než 30 řádků.

Testy. Claude napíše unit testy k vašemu kódu. Dokonce umí pracovat metodou test-driven development – nejdřív napíše testy, pak kód, který jimi projde.

Dokumentace. Zdokumentuje funkce, vytvoří README, popíše API. Všechno, co programátoři neradi dělají ručně.

Code review. Projde kód a navrhne vylepšení – lepší názvy, efektivnější algoritmy, potenciální bugy.

Práce se soubory

Tady začíná být Claude Code zajímavý i pro neprogramátory. Má přístup k vašim souborům a umí s nimi pracovat.

Organizace. Máte chaotickou složku Downloads plnou náhodně pojmenovaných souborů? Claude ji roztřídí. Vytvoří podsložky podle typu, data, projektu – jak potřebujete.

Hromadné přejmenování. Potřebujete přejmenovat stovky souborů podle určitého vzoru? Třeba faktury na formát „2024–01–15 Dodavatel – Faktura.pdf"? Claude to zvládne během vteřin.

Konverze formátů. Převede data mezi formáty – CSV na JSON, XML na tabulku, cokoliv potřebujete.

Psaní a práce s texty

Ač se jmenuje „Code", Claude Code překvapivě dobře pomáhá s texty.

Články a blogy. Pomůže strukturovat myšlenky, napsat první draft, editovat a vylepšovat. Jeden uživatel ho označil za nejlepší systém pro podporu psaní, jaký kdy zkoušel.

Uspořádání poznámek. Máte chaotické poznámky rozházené v různých souborech? Claude je projde a uspořádá do koherentního celku. Jedna uživatelka nahrála hlasové poznámky z procházek s kočárkem – Claude je přepsal a uspořádal do výzkumných témat a nakonec napsal článek v jejím stylu.

Překlady. Přeloží texty a zachová formátování. Umí i hromadně přeložit všechny textové soubory v projektu.

Korektura. Opraví pravopis, gramatiku, styl. Navrhne lepší formulace.

Analýza dat

Na rozdíl od webového Clauda, který má limity na velikost souborů, Claude Code zpracuje i obrovské datasety. A hlavně – umí si napsat vlastní kód pro analýzu a rovnou ho spustit.

Reporty na požádání. Řeknete mu: „Podívej se na tato data o prodejích a vytvoř report s grafy a zhodnocením trendů." A on to udělá. Načte data, zanalyzuje je, vytvoří vizualizace a napíše shrnutí.

Hledání vzorů. Claude najde anomálie a trendy, které byste ručně hledali hodiny. Který produkt má klesající prodeje? Kde jsou sezónní výkyvy?

Čištění dat. Máte seznam adres plný překlepů a duplicit? Claude ho vyčistí, sjednotí formát a odstraní chyby.

Jeden uživatel popsal, jak prostě nahrál CSV soubor s daty o zákaznících a řekl: „Představ si, že jsi datový konzultant. Proveď analýzu a navrhni doporučení." Claude data prošel a dodal detailní zprávu se zjištěními.

Automatizace

Tady Claude Code opravdu září. Umí vytvářet automatizované procesy, které vám ušetří hodiny práce.

Opakující se úkoly. Máte něco, co děláte každý den nebo týden stejně? Claude to zautomatizuje. Stahování dat, generování reportů, odesílání notifikací.

Propojení služeb. Claude umí spojit různé nástroje dohromady. Marketingový tým Anthropic si takto vytvořil systém, který automaticky generuje stovky variant reklamních textů z CSV souboru s daty o výkonu reklam.

Sledování a notifikace. Můžete Clauda nechat sledovat logy nebo data a upozornit vás, když se něco pokazí nebo objeví zajímavý vzorec.

Správa systému

Claude Code může fungovat jako váš osobní IT podpora.

Diagnostika. „Proč je můj počítač pomalý?" – a Claude zkontroluje vytížení procesoru, paměti, disku, běžící procesy, Docker kontejnery, všechno možné. A navrhne řešení.

Konfigurace. Potřebujete nastavit něco v systému, ale nevíte jak? Popište, co chcete, a Claude to nastaví.

Instalace. Claude nainstaluje software, nakonfiguruje prostředí, nastaví závislosti.

Jeden uživatel popsal, jak se Claude přes SSH připojil k vzdálenému serveru, upravil konfiguraci monitorovacího nástroje a adaptoval se, když některé příkazy selhaly.

Pro pokročilejší uživatele Claude Code pomáhá i se správou infrastruktury. Nastaví automatické buildy a deploye, nakonfiguruje monitoring serverů, pomůže s Docker kontejnery. I netechnický člověk může s pomocí Clauda nastavit základní CI/CD pipeline.

Ale pozor – je to pořád AI

Než se necháte unést nadšením, je potřeba říct jednu důležitou věc: Claude Code dělá chyby. Jako každá AI. Někdy malé, někdy… no, někdy monumentální.

Jeden programátor mi vyprávěl následující příběh. Dal Claudovi za úkol zmodernizovat zastaralý projekt. Claude běžel hodinu. Přepsal všechno. Legacy kód z roku 2015? Pryč. Zastaralé patterny? Nahrazeny elegantními moderními řešeními. Nepřehledná architektura? Teď křišťálově čistá. Výsledek vypadal jako z učebnice – TypeScript, testy, dokumentace, všechno.

Byl to naprosto špičkový kód.

Který vůbec nefungoval.

Proto platí: čím lepší jste programátor a čím víc svému oboru rozumíte, tím lepších výsledků s Claude Code dosáhnete. Ne proto, že byste museli psát kód sami – ale proto, že poznáte, když Claude udělá chybu. A on ji udělá. Otázka není jestli, ale kdy.

Berte Clauda jako juniora s neomezenou energií a encyklopedickými znalostmi, který ale potřebuje dozor. Nechte ho pracovat, ale kontrolujte výsledky. Testujte. Zkoušejte, jestli to opravdu funguje, než to pošlete do produkce.

Chcete se naučit používat Claude Code naplno? Pořádám kurz, kde vás provedu vším od základů až po pokročilé techniky. Naučíte se, jak z Clauda dostat maximum a vyhnout se typickým chybám. Více informací a přihlášky

Co z toho plyne?

Claude Code není jen nástroj pro programátory. Je to „everything agent" – univerzální asistent, který má přístup k vašemu počítači a umí provádět téměř jakékoliv úkoly.

Klíč k úspěchu je jednoduchý: popište, co chcete, lidsky. Nemusíte znát příkazy, nemusíte rozumět technikáliím. Prostě řekněte, čeho chcete dosáhnout, a Claude najde způsob, jak to udělat.

Uživatelé hlásí 40–80% úsporu času na rutinních úlohách. Některé startupy postavily celé produkty prakticky bez tradičního programování. A to všechno díky tomu, že máte k dispozici inteligentního pomocníka, který umí ovládat váš počítač.

Jen pozor na tu wifi.

Velký přehled porovnávání v PHP je tu!

Už žádné psaní testovacích skriptů, když si nejste stoprocentně jistí. Už žádné zdlouhavé listování v dokumentaci. Konečně je tu tabulka pravdy PHP. Připravil jsem pro vás definitivní PHP Comparison Cheat Sheet. Je to mapa pro území, kde neplatí ===.

Protože PHP 8 v tomto ohledu přepsalo pravidla, tabulky jsou dvě:

👉 Tabulka pro PHP 8.x (Současnost, kterou musíte znát)
👉 Tabulka pro PHP 7.x (Pro legacy warriors a archeology)

Všichni jsme se naučili používat ===, abychom měli klidné spaní. Je to naše jistota. Jenže co ve chvíli, kdy nepotřebujete vědět, jestli jsou hodnoty totožné, ale která je větší nebo menší? Tady veškerá jistota končí. Pro operátory <, >, <= a >= totiž žádná „strict“ verze neexistuje. PHP v tu chvíli přebírá otěže a spouští type juggling. Víte s jistotou, jak se zachová porovnání čísla a řetězce? Nebo null a false?

Stačí se podívat do tabulky a okamžitě vidíte, jak se k sobě typy chovají, když je PHP nutí do interakce. Začíná kompletním přehledem všech operátorů včetně spaceship (<=>).

Odhalíte tiché chyby dřív, než nastanou

Uveďme si dva příklady, které vás mohou stát hodiny ladění. Různé PHP funkce používají různé strategie porovnávání. Třeba funkce sort() má jako výchozí nastavení SORT_REGULAR.

Jak se zachová u řetězců, které vypadají jako čísla, například "042" a " 42"? Jak je seřadí?

  • V tabulce si najdu sekci SORT_REGULAR
  • Podívám se na průsečík těchto hodnot.
  • Vidím symbol =
  • Co to znamená: PHP je v tomto režimu považuje za identické. Výsledné pořadí těchto prvků po seřazení bude náhodné (nedefinované). Pokud na pořadí záleží, máme problém.

A co array_unique()? „Nezkanibalizuje“ mi potichu data, když se v poli potká "042" a " 42"? Nemusíte nic zkoušet.

  • Funkce array_unique() má jako výchozí nastavení SORT_STRING
  • Podívám se na průsečík těchto hodnot.
  • Vidím symbol <
  • Co to znamená: Dopadne do dobře, hodnoty se liší (protože se vše převede na string)

Díky tabulce nemusíte hádat. Okamžitě vidíte, kdy musíte přepnout flag, aby aplikace dělala přesně to, co chcete.

(A ano, žádný flag pro striktní porovnávání bez type juggling v PHP neexistuje 😤)

Fajnšmekroviny: DateTime a Closures

Aneb co nejspíš nevíte o porovnávání objektů v PHP.

Vezměte si takový DateTime. Mnoho vývojářů má zafixováno, že objekty se porovnávat nedají, a tak data zoufale převádí na timestampy nebo formátované stringy typu 'Y-m-d H:i:s', jen aby zjistili, co nastalo dřív. Zbytečně! Třídy DateTime a DateTimeImmutable mají implementovanou logiku pro běžné porovnávací operátory. Můžete se ptát na větší/menší stejně přirozeně jako u čísel. Žádné helpery, žádné formátování, čistá syntaxe. Proto si to zasloužilo vlastní sekci DateTime v tabulce.

Ještě větší zábava začíná u rovnosti. Zatímco === je u objektů nekompromisní a zajímá ho, jestli držíte v ruce identickou instanci, operátor == je u data mnohem pragmatičtější a porovnává časovou hodnotu. Díky tomu můžete porovnat dva různé objekty, a pokud ukazují stejný čas, PHP řekne „ano, to se rovná“. A co víc – funguje to i křížem mezi DateTime a DateTimeImmutable!

A třešnička na dortu? Closures. I anonymní funkce jsou objekty. Kdy jsou dvě closures rovny? Podívejte se do tabulky!

Pipe Operátor v PHP 8.5 je navoněná bída

Konečně! Boucháme šampaňské, trháme konfety a rituálně pálíme učebnice procedurálního programování. PHP 8.5 přináší legendární Pipe Operátor |>. Svatý grál všech, kdo se po nocích modlí k bohům funkcionálního programování a tajně závidí hipstrům v Elixiru nebo F#.

Už žádné vnořování funkcí do sebe jako ruská matrjoška. Žádné pomocné proměnné typu $tmp1, $tmp2, $tmp47. Píšeme tok dat zleva doprava, přesně tak, jak přirozeně myslíme!

Marketingové oddělení PHP by vám na slidech ukázalo tohle:

$vysledek = " Ahoj " |> trim(...) |> strtoupper(...);

„Wow! To je čistota! To je elegance!“ křičí dav a hází podprsenky na pódium.

Jenže pak se probudíte a zjistíte, že realita je úplně jiná. Vítejte v pekle závorek, anonymních funkcí a výkonnostního masochismu. Pojďme se podívat, proč je tahle novinka skvělá asi tak jako nepromokavý čajový sáček.

Case Study: Jak napsat to samé, ale složitěji

Představte si klasický scénář: Chcete normalizovat text pro anglické titulky. Postup: oříznout mezery, rozsekat na slova, každému slovu dát velké počáteční písmeno a zase to slepit dohromady.

Srovnejte sami:

// Tradiční vnořování - nečitelná hrůza (Matrjoška style)
$result = implode(' ', array_map(ucfirst(...), preg_split('/\s+/', trim($input))));

// S pipe operátorem - WOW! 🎉
$result = $input
    |> trim(...)
    |> preg_split('/\s+/', ...)
    |> array_map(ucfirst(...), ...)
    |> implode(' ', ...);

Na první pohled je to zenová zahrada. Vidíte, jak data tečou shora dolů jako vodopád. Váš mozek vrní blahem, protože nemusí luštit závorky od středu ven. Je to jako číst recept: „Vezmi vstup, ořízni ho, rozsekej na slova, uprav, slep.“ Nádhera. Feng-shui v praxi.

TAKLE TO ALE NEFUNGUJE!

Ten krásný příklad výše je totiž sprostá syntaktická lež. PHP parser by se při pokusu o zpracování tohoto kódu zakuckal a umřel s výkřikem SYNTAX ERROR.

Hned si vysvětlíme proč.

Jak se to dělalo dříve

Tradiční nečitelnou hrůzu se zanořováním jsme si už ukázali. Místo toho se podívejme na „sedlácký“ styl, který všichni tajně používáme, když se nikdo nedívá:

// Tradiční způsob s pomocnými proměnnými - jasný, funkční, nudný (110 znaků)
$_ = trim($input);                             // odstranění mezer
$_ = preg_split('/\s+/', $_);                  // rozdělení na slova
$_ = array_map(ucfirst(...), $_);              // zvětšení písmen
$processed = implode(' ', $_);                 // spojení zpět

Jasný, čitelný. Každý junior ví, co se děje. Pomocná proměnná $_ sice nevyhraje soutěž krásy, ale funguje, nic nestojí a nepřekáží.

A mimochodem, tento kód má 110 znaků. Zapamatujte si to číslo.

První facka: ... není Partial Application

Placeholder ... funguje JENOM tehdy, když pipujete do prvního a zároveň jediného parametru!

Takže zatímco trim(...) je v pohodě, cokoliv složitějšího narazí do zdi. PHP (na rozdíl od jazyků, kde to dělají pořádně) neumí říct „tady je funkce a tohle je díra pro argument“.

A protože většina funkcí v PHP má pořadí parametrů vybrané generátorem náhodných čísel (needle/haystack chaos), musíte použít arrow funkce. Připravte si prsty, budete psát hodně fn, $_ a šipek:

$processed = $input
    |> trim(...)                               // Jediný moment, kdy to funguje hezky
    |> fn($_) => preg_split('/\s+/', $_)       // Arrow fce. Proměnná.
    |> fn($_) => array_map(ucfirst(...), $_)   // Vnořená arrow funkce, mňam.
    |> fn($_) => implode(' ', $_);

Druhá facka: Závorkové peklo

Spustíte to a čekáte potlesk. Místo toho na vás PHP interpreter vyplázne:
Fatal error: Arrow functions on the right hand side of |> must be parenthesized.

Pardon? Musím dávat arrow funkce do závorek? Proč? Kvůli precedenci operátorů. Parser je zmatený jak lesní včela, takže mu musíte každou arrow funkci explicitně zabalit, aby pochopil, kde končí a kde začíná další trubka.

Takže váš „elegantní“ kód nyní vypadá takto:

$processed = $input
    |> trim(...)
    |> (fn($_) => preg_split('/\s+/', $_))     // Závorka. Arrow fce. Proměnná. Závorka.
    |> (fn($_) => array_map(ucfirst(...), $_)) // Další závorky...
    |> (fn($_) => implode(' ', $_));           // Proč si to děláme?

Gratuluji! Váš kód je nyní:

  • O 53 % delší než varianta s pomocnými proměnnými (nyní má 169 znaků).
  • Vizuálně připomíná LISP po lobotomii (samá závorka).
  • Má overhead z vytváření closure při každém kroku.

Pokrok nezastavíš!

K.O.: Reference? Zapomeňte

Tohle je část, kde se smích mění v pláč a skřípění zubů. Představte si, že chcete v textu něco nahradit a zajímá vás, kolikrát k nahrazení došlo (parametr &$count u str_replace).

V klasickém „zastaralém“ kódu byste prostě předali proměnnou odkazem.

$_ = str_replace('!', '', $_, count: $count); // $count se vesele inkrementuje

Ale v arrow funkcích uvnitř roury? Smůla. Arrow funkce (fn) v PHP nemůžou měnit vnější proměnné.

Podívejte se na tuhle past:

$count = 0;

// Očekáváme, že se $count zvýší...
$processed = $input
    |> (fn($_) => str_replace('!', '', $_, count: $count)) // Zrada!
    |> trim(...)
    ...

echo $count; // Výsledek je vždy 0. Nula. Zero.

Co se stalo?

Nic. Žádná chyba. Žádná Notice. Žádný Warning. PHP prostě mlčky vzalo kopii nuly, poslalo ji do funkce, ta ji vesele inkrementovala uvnitř své bubliny a pak ji zahodila do koše. Vaše původní proměnná $count zůstala nedotčena.

Pokud to chcete opravit, musíte použít starou syntaxi function($_) use (&$count) { return ... }, čímž jste právě ztratili poslední zbytky důstojnosti a elegance.

Co se děje pod kapotou? (Spoiler: Nic hezkého)

Možná si říkáte: „No dobře, je to hnusné, ale určitě je to super rychlé, optimalizované makro, ne?“

(Nikdo soudný si tohle neříká, ale předstírejme to.)

Pipe operátor není chytré makro, které by kód přepsalo (fn($_) => ...) na prosté volání. Každý ten krok reálně vytváří novou instanci objektu Closure. Pro každou operaci. Pro každý řádek.

Takže místo prostého zavolání funkce PHP interně dělá tohle:

  1. Vytvoř objekt Closure.
  2. Zavolej ho.
  3. Zahoď ho (a nech garbage collector, ať si to užije).
  4. Opakuj pro další řádek.

Je to, jako byste si na cestu do ledničky pro pivo pokaždé objednali Uber. Dostanete se tam, ale je to zbytečně drahé, trvá to déle a sousedi si o vás budou myslet svoje.

Typehintujeme, nebo ne?

Tohle je hamletovská otázka moderního PHP. V řetězci pipe operátorů se musíte rozhodnout:

Varianta A: Jsem poctivý masochista a napíšu (fn(string $_): array => ...).

Výsledek: Kód je tak dlouhý, že se nevejde na dva monitory vedle sebe. Upíšete si ruce a kolegové vás budou nenávidět při každém Code Review.

Varianta B: Jsem lenoch a punker a napíšu jen (fn($_) => ...).

Výsledek: Vaše IDE přestane našeptávat a přísně nastavená statická analýza (PHPStan) začne křičet „Mixed type everywhere!“

Je to volba mezi karpálním tunelem a programováním naslepo.

Verdikt

Pipe operátor v PHP 8.5 je jako drahý, designový odšťavňovač, co jste si koupili v lednu v záchvatu zdravého životního stylu. Vypadá hezky na lince, všem o něm vyprávíte, ale když ho máte reálně použít, zjistíte, že umytí těch sítek trvá třikrát déle než snězení celého pomeranče i se slupkou.

Pipe operátor dává smysl pouze tehdy, když:

  1. Všechny funkce berou jeden parametr. ✅
  2. Nebo vás nezajímá výkon. ✅
  3. Nebo milujete závorky. ✅

Čili… je to skvělé do tutoriálů a na konference!

Doporučení: Zůstaňte u pomocných proměnných. Jsou levné, fungují, neodstíní reference a nemusíte kvůli nim psát (fn($_) => ...) desetkrát za sebou.


P.S.: V PHP 8.6 to vyřeší Partial Function Application. Ale utěšovat se tím teď, to je jako říct hladovému člověku: „Vydrž, příští rok už ten řízek bude i s masem.“

Jak nainstalovat Claude Code: Průvodce pro začátečníky

(Aktualizováno v lednu 2026) Claude Code je nástroj, který přináší schopnosti umělé inteligence do virtuálního programátora. Představte si kolegu, který sedí vedle vás a pomáhá vám s vašimi projekty. Na rozdíl od běžného chatování v prohlížeči, kde musíte kopírovat kód tam a zpět, Claude Code pracuje přímo s vašimi soubory a na vašem počítači.

Co s ním dokážete

Tady je pár příkladů, co všechno zvládnete:

  • 💡 Popíšete, jakou funkci potřebujete, a Claude ji napíše
  • 🐛 Hodíte na něj chybovou hlášku a necháte ho problém najít a opravit
  • 🔧 Refaktoruje existující kód, přidá testy, napíše dokumentaci
  • 🗺️ Když se potřebujete zorientovat v cizím projektu, prostě se zeptáte, jak to celé funguje

A co možná nevíte – Claude Code není jen pro programování. Protože má přístup k vašemu terminálu, můžete ho poprosit o leccos jiného:

  • 📋 Roztřídí vám vaše stažené soubory
  • ⚙️ Nainstaluje potřebné balíčky a nakonfiguruje systém
  • 📁 Dávkově přejmenuje stovky souborů nebo prohledá data

Prostě cokoli, co byste normálně dělali v příkazové řádce, jen místo googlování příkazů to popíšete lidsky a Claude to udělá za vás. Více si ukážeme v článku Co všechno umí Claude Code.

Pro koho je tento návod

Nepotřebujete být expert na umělou inteligenci ani na programování – Claude Code je navržený tak, aby s ním mohl pracovat každý. Ale nutno říct, že čím lepší jste programátor a čím víc svému oboru rozumíte, tím lepších výsledků dosáhnete.

Tento první článek je určen pro úplné začátečníky a provede vás instalací Claude Code. V dalších dílech se podíváme na praktické využití, ale nejprve musíme zvládnout ten první krok – zprovoznění. Po dokončení tohoto návodu budete mít vše připraveno a můžete si s Claude Code začít hrát.

…pokračování

100 minut je méně než 50? Paradoxy PHP při změně času

„Kdy se sejdeme?“ – „Zítra ve tři.“ „Kdy je ta schůzka?“ – „Příští měsíc.“ Pro běžný život jsou takové údaje o čase zcela postačující. Jenže zkuste totéž v programování a rychle zjistíte, že jste vstoupili do bludiště plného nástrah a neočekávaných překvapení.

Čas v programování je jako šelma, která vypadá krotce, dokud na ni nešlápnete. A jednou z nejmocnějších lstí této šelmy je letní čas a jeho zákeřné přechody. Systém, který měl údajně ušetřit svíčky, dnes způsobuje programátorům bezesné noci (pravděpodobně kolem 2:30 ráno, kdy najednou zjistí, že jejich servery dělají podivné věci).

Vydejme se na průzkum temných zákoutí přechodů na letní čas a zpět, jak je PHP (ne)zvládá a jak jsem se pokusil napravit toto šílenství v Nette Utils. Připravte se na momenty, kdy 1 + 1 ≠ 2 a kdy přidání delšího času vám paradoxně vrátí dřívější hodinu. Tohle by nevymyslel ani Einstein.

Nejprve si prosvištíme některá slovíčka

Než se ponoříme do problematiky, vysvětleme si několik klíčových pojmů:

  • UTC (Coordinated Universal Time) – koordinovaný světový čas, základní časový standard, od kterého se odvozují všechny ostatní časové zóny. Je to v podstatě „nulový bod“ pro měření času na celém světě.
  • Časový posun (offset) – kolik hodin je potřeba přičíst nebo odečíst od UTC, abychom dostali místní čas. Označuje se jako UTC+X nebo UTC-X.
  • CET (Central European Time) – středoevropský čas, který používáme v zimě. Má posun UTC+1, což znamená, že když je v UTC poledne, u nás je 13:00.
  • CEST (Central European Summer Time) – středoevropský letní čas, který používáme v létě. Má posun UTC+2, takže když je v UTC poledne, u nás je 14:00.
  • ČEST – komunistický pozdrav, něco, co patří doufám už pouze do starý časů
  • Letní čas – systém, kdy v určité části roku (obvykle v létě) posuneme hodiny o hodinu dopředu, abychom lépe využili denní světlo.

Ten okamžik trval celý světelný rok

Pojďme si sekundu po sekundě rozebrat, jak probíhá přechod na letní čas a zpátky. Jako příklad si vezměme nedávnou změnu času v České republice v neděli 30. března 2025:

…pokračování

Var, Let, Const: Přestaňte si komplikovat život v JavaScriptu

JavaScript nabízí tři způsoby, jak deklarovat proměnné: var, let a const. Pro mnoho programátorů není úplně jasné, kdy kterou z nich použít, většina tutoriálů a linterů vás nutí používat je špatně. Pojďme si ukázat, jak psát čistší a srozumitelnější kód bez zbytečných pravidel, která nám ve skutečnosti nepomáhají.

Začněme tím nejnebezpečnějším

JavaScript má jednu zákeřnou vlastnost: pouhým opomenutím deklarace proměnné můžete nevědomky používat globální proměnnou. Stačí zapomenout na var, let nebo const:

function calculatePrice(amount) {
	price = amount * 100;    // Opomenutí! Chybí 'let'
	return price;            // Používáme globální proměnnou 'price'
}

function processOrder() {
	price = 0;               // Používáme tu samou globální proměnnou!
	// ... nějaký kód volající calculatePrice()
	return price;            // Vracíme úplně jinou hodnotu, než čekáme
}

Tohle je noční můra každého vývojáře – kód funguje zdánlivě správně, dokud nezačne někde jinde v aplikaci něco záhadně selhávat. Debugování takových chyb může zabrat hodiny, protože globální proměnná může být přepsána kdekoliv v aplikaci.

Proto je naprosto zásadní vždy deklarovat proměnné pomocí let nebo const.

Zapomeňte na var

Klíčové slovo var je v JavaScriptu od jeho počátku v roce 1995 a nese s sebou pár problematických vlastností, které byly v době vzniku jazyka považovány za features, ale časem se ukázaly jako zdroj mnoha chyb. Po dvaceti letech vývoje jazyka se autoři JavaScriptu rozhodli tyto problémy řešit – ne opravou var (kvůli zachování zpětné kompatibility), ale představením nového klíčového slova let v ES2015.

Na internetu najdete spoustu článků rozebírajících problémy var do nejmenších detailů. Ale víte co? Není potřeba se v tom babrat. Berme var prostě jako překonaný archaismus a pojďme se soustředit na moderní JavaScript.

Kdy použít let

let je moderní způsob deklarace proměnných v JavaScriptu.

Příjemné je, že proměnná existuje vždy pouze uvnitř bloku kódu (tedy mezi složenými závorkami), kde byla definována. To dělá kód předvídatelnější a bezpečnější.

if (someCondition) {
	let temp = calculateSomething();
	// temp je dostupná jen zde
}
// temp už zde neexistuje

V případě cyklů je deklarace přísně vzato umístěna před složenými závorkami, ale nenechte si tím zmást, proměnná existuje jen v cyklu:

for (let counter = 0; counter < 10; counter++) {
	// Proměnná counter existuje jen v cyklu
}
// counter už zde nejsou dostupné

Kdy použít const

const slouží k deklarování konstant. Typicky jde o důležité hodnoty na úrovni modulu nebo aplikace, které se nikdy nemají měnit:

const PI = 3.14159;
const API_URL = 'https://api.example.com';
const MAX_RETRY_ATTEMPTS = 3;

Je ale důležité pochopit jeden klíčový detail: const pouze zabraňuje přiřazení nové hodnoty do proměnné – neřeší, co se děje s hodnotou samotnou. Tento rozdíl se projevuje zejména u objektů a polí (pole je ostatně také objekt) – const z nich nedělá immutable objekty, tj. nezabraňuje změnám uvnitř objektu:

const CONFIG = {
	url: 'https://api.example.com',
	timeout: 5000
};

CONFIG.url = 'https://api2.example.com';  // Toto funguje!
CONFIG = { url: 'https://api2.example.com' };  // Toto vyhodí TypeError!

Pokud potřebujete skutečně neměnný objekt, musíte jej nejprve zmrazit.

Dilema let vs const

Nyní se dostáváme k zajímavější otázce. Zatímco u var vs let je situace jasná, použití const je předmětem mnoha diskuzí v komunitě. Většina tutoriálů, style-guides a linterů prosazuje pravidlo „používej const všude, kde můžeš“. Takže použití const vídáme zcela běžně v tělech funkcí nebo metod.

Pojďme si vysvětlit, proč je tato populární „best practice“ ve skutečnosti anti-pattern, který dělá kód méně čitelný a zbytečně svazující.

Přístup „pokud se proměnná v kódu nepřepisuje, měla by být deklarována jako const“ se na první pohled jeví logický. Proč by jinak bůh stvořil const? Čím víc „konstant“, tím bezpečnější a předvídatelnější kód, že? A navíc rychlejší, protože ho kompilátor může lépe optimalizovat.

Jenže celý tento přístup je ve skutečnosti nepochopení toho, k čemu konstanty slouží. Jde především o komunikaci záměru – opravdu chceme sdělit ostatním vývojářům, že do této proměnné se už nesmí nic přiřadit, nebo do ní jen náhodou v současné implementaci nic nepřiřazujeme?

// Skutečné konstanty - hodnoty, které jsou konstantní ze své podstaty
const PI = 3.14159;
const DAYS_IN_WEEK = 7;
const API_ENDPOINT = 'https://api.example.com';

// vs.

function processOrder(items) {
	// Toto NEJSOU konstanty, jen náhodou je nepřepisujeme
	const total = items.reduce((sum, item) => sum + item.price, 0);
	const tax = total * 0.21;
	const shipping = calculateShipping(total);
	return { total, tax, shipping };
}

V prvním případě máme hodnoty, které jsou konstantami ze své podstaty – vyjadřují neměnné vlastnosti našeho systému nebo důležitá konfigurační data. Když někde v kódu vidíme PI nebo API_ENDPOINT, okamžitě chápeme, proč jsou tyto hodnoty konstanty.

V druhém případě používáme const jen proto, že zrovna teď náhodou hodnoty nepřepisujeme. Ale není to jejich podstatná vlastnost – jsou to běžné proměnné, které bychom v příští verzi funkce klidně mohli chtít změnit. A když to budeme chtít udělat, const nám v tom bude zbytečně bránit.

V dobách, kdy byl JavaScript jeden velký globální kód, mělo smysl snažit se zabezpečit proměnné proti přepsání. Ale dnes píšeme kód v modulech a třídách. Dnes je běžné a správné, že scope je malá funkce a v jejím rámci vůbec nemá smysl rozdíl mezi let a const řešit.

Protože to vytváří naprosto zbytečnou kognitivní zátěž:

  1. Programátor musí při psaní přemýšlet: „Budu tuhle hodnotu měnit? Ne? Tak musím dát const…“
  2. Čtenáře to ruší! Vidí v kódu const a ptá se: „Proč je tohle konstanta? Je to nějaká důležitá hodnota? Má to nějaký význam?“
  3. Za měsíc potřebujeme hodnotu změnit a musíme řešit: „Můžu změnit const na let? Nespoléhá na to někdo?“

Používejte jednoduše let a tyto otázky nemusíte vůbec neřešit.

Ještě horší je, když toto rozhodnutí dělá automaticky linter. Tedy když linter „opraví“ proměnné na const, protože vidí jen jedno přiřazení. Čtenář kódu pak zbytečně přemýšlí: „Proč tady musí být tyto proměnné konstanty? Je to nějak důležité?“ A přitom to není důležité – je to jen shoda okolností. Nepoužívejte v ESLint pravidlo prefer-const!

Mimochodem, argument o optimalizaci je mýtus. Moderní JavaScript engine (jako V8) dokáže snadno detekovat, zda je proměnná přepisována nebo ne, bez ohledu na to, jestli byla deklarována pomocí let nebo const. Takže používání const nepřináší žádný výkonnostní benefit.

Implicitní konstanty

V JavaScriptu existuje několik konstrukcí, které implicitně vytvářejí konstanty, aniž bychom museli použít klíčové slovo const:

// importované moduly
import { React } from 'react';
React = something; // TypeError: Assignment to constant variable

// funkce
function add(a, b) { return a + b; }
add = something; // TypeError: Assignment to constant variable

// třídy
class User {}
User = something; // TypeError: Assignment to constant variable

Je to logické – tyto konstrukce definují základní stavební bloky našeho kódu a jejich přepsání by mohlo způsobit chaos v aplikaci. Proto je JavaScript automaticky chrání proti přepsání, stejně jako kdyby byly deklarovány pomocí const.

Konstanty ve třídách

Třídy byly do JavaScriptu přidány relativně nedávno (v ES2015) a jejich funkcionalita teprve postupně dospívá. Například privátní členy označené pomocí # přišly až v roce 2022. Na podporu konstant ve třídách JavaScript stále čeká. Prozatím můžete používat static, který ale není zdaleka to samé – označuje hodnotu sdílenou mezi všemi instancemi třídy, nikoliv však neměnnou.

Závěr

  1. var nepoužívejte – je to přežitek
  2. const používejte pro skutečné konstanty na úrovni modulu
  3. Ve funkcích a metodách používejte let – je to čitelnější a jasnější
  4. Nenechte linter automaticky měnit let na const – není to o počtu přiřazení, ale o záměru

Jak vyřešit chaos s prázdnými řetězci a NULL hodnotami v MySQL?

Znáte to – vytvoříte dotaz WHERE street = '', ale systém nevrátí všechny záznamy, které byste čekali. Nebo vám nefunguje LEFT JOIN tak, jak má. Důvodem je častý problém v databázích: nekonzistentní používání prázdných řetězců a NULL hodnot. Pojďme si ukázat, jak tento chaos vyřešit jednou provždy.

Kdy použít NULL a kdy prázdný řetězec?

Teoreticky je rozdíl jasný: NULL znamená „hodnota není zadaná“, zatímco prázdný řetězec znamená „hodnota je zadaná a je prázdná“. Podívejme se na reálný příklad z e-shopu, kde máme tabulku objednávek. Každá objednávka má povinnou dodací adresu a volitelnou fakturační adresu pro případ, že zákazník chce fakturovat na jiné místo (typické zatržítko „Fakturovat na jinou adresu“):

CREATE TABLE orders (
    id INT PRIMARY KEY,
    delivery_street VARCHAR(255) NOT NULL,
    delivery_city VARCHAR(255) NOT NULL,
    billing_street VARCHAR(255) NULL,
    billing_city VARCHAR(255) NULL
);

Pole billing_city a billing_street jsou nullable, protože fakturační adresa nemusí být vyplněná. Ale je mezi nimi rozdíl. Zatímco ulice může být legitimně prázdná (obce bez ulic), nebo nezadaná (použije se dodací adresa), město musí být vždy vyplněné, pokud je fakturační adresa použita. Buď tedy billing_city obsahuje název města, nebo je NULL – v tomto případě se použije dodací adresa.

Realita velkých databází

V praxi ale často dochází k tomu, že se v databázi začnou míchat oba přístupy. Příčin může být několik:

  • Změny v aplikační logice v průběhu času (např. přechod z jednoho ORM na jiné)
  • Různé týmy nebo programátoři používající různé konvence
  • Buggy migrace dat při slučování databází
  • Legacy kód, který se chová jinak než nový
  • Chyby v aplikaci, které občas propustí prázdný řetězec místo NULL nebo naopak

Tohle vede k situacím, kdy máme v databázi mix hodnot a musíme psát složité podmínky:

SELECT * FROM tbl
WHERE foo = '' OR foo IS NULL;

Daleko horší je, že NULL se chová neintuitivně při porovnání:

SELECT * FROM tbl WHERE foo = ''; -- nezahrne NULL
SELECT * FROM tbl WHERE foo <> ''; -- taky nezahrne NULL

-- musíme použít
SELECT * FROM tbl WHERE foo IS NULL;
SELECT * FROM tbl WHERE foo <=> NULL;

Tato nekonzistence v chování porovnávacích operátorů je další důvod, proč je výhodnější používat v databázi jen jeden způsob reprezentace prázdné hodnoty.

Proč se vyhnout dvojímu přístupu

Podobná situace jako v MySQL existuje i v JavaScriptu, kde máme null a undefined. Po letech zkušeností mnoho JavaScript vývojářů dospělo k závěru, že rozlišování mezi těmito dvěma stavy přináší víc problémů než užitku a raději se rozhodli používat pouze systémově nativní undefined.

V databázovém světě je situace podobná. Místo toho, abychom stále řešili, jestli něco je prázdný řetězec nebo NULL, je často jednodušší zvolit jeden přístup a toho se držet. Například databáze Oracle prázdné řetězce a NULL hodnoty v podstatě ztotožňuje, čímž tento problém elegantně obchází. Je to jedno z míst, kde se Oracle odchyluje od SQL standardu, ale zároveň tím zjednodušuje práci s prázdnými/NULL hodnotami.

Jak něčeho podobného dosáhnout v MySQL?

Co vlastně chceme vynutit?

  1. U povinných polí (NOT NULL) chceme vynutit, aby vždy obsahovala smysluplnou hodnotu. Tedy zabránit vložení prázdného řetězce (nebo řetězce obsahujícího pouze mezery)
  2. U volitelných polí (NULL) chceme zabránit ukládání prázdných řetězců. Když je pole volitelné, měl by být NULL jedinou reprezentací „nevyplněné hodnoty“. Míchání obou přístupů v jednom sloupci vede k problémům s dotazováním a JOIN operacemi, které jsme si ukázali výše.

Řešení v MySQL

V MySQL dávalo historicky smysl naopak používat výhradně prázdné řetězce ('') místo NULL hodnot. Byl to totiž jediný přístup, který šlo vynutit pomocí NOT NULL constraintu. Pokud jsme chtěli automaticky konzistentní databázi, byla to jediná cesta.

Existuje ale jeden důležitý případ, kdy tento přístup selže – když potřebujeme nad sloupcem unikátní index. MySQL totiž považuje více prázdných řetězců za stejné hodnoty, zatímco více NULL hodnot za různé:

Nicméně od MySQL verze 8.0.16 můžeme použít CHECK constraint a mít tak větší kontrolu nad tím, jaké hodnoty povolíme. Můžeme například vynutit, že sloupec bude buď NULL, nebo bude obsahovat neprázdný řetězec:

CREATE TABLE users (
    id INT PRIMARY KEY,

    -- Povinné pole - musí obsahovat nějaký neprázdný text
    email VARCHAR(255) NOT NULL UNIQUE
        CONSTRAINT email_not_empty      -- název pravidla
        CHECK (email != ''),

    -- Nepovinné pole - buď NULL nebo neprázdný text
    nickname VARCHAR(255)
        CONSTRAINT nickname_not_empty
        CHECK (nickname IS NULL OR nickname != '')
);

Při vytváření CHECK constraintu je důležité dát mu smysluplný název pomocí klíčového slova CONSTRAINT. Díky tomu dostaneme v případě porušení pravidla srozumitelnou chybovou hlášku Check constraint ‚nickname_not_empty‘ is violated místo obecného oznámení o porušení constraintu. To výrazně usnadňuje debugging a údržbu aplikace.

Problém jsou nejen prázdné řetězce, ale i řetězce obsahující pouze mezery. Řešení pomocí CHECK constraintu můžeme vylepšit použitím funkce TRIM:

CREATE TABLE users (
    id INT PRIMARY KEY,
    email VARCHAR(255) NOT NULL UNIQUE
        CONSTRAINT email_not_empty
        CHECK (TRIM(email) != ''),
   ...
);

Nyní neprojdou ani tyto pokusy o obejití validace:

INSERT INTO users (email) VALUES ('   ');  -- samé mezery

Praktické řešení v Nette Framework

Konzistentní přístup k prázdným hodnotám je potřeba řešit i na úrovni aplikace. Pokud používáte Nette Framework, můžete využít elegantní řešení pomocí metody setNullable():

$form = new Form;
$form->addText('billing_street')
    ->setNullable(); // prázdný input se transformuje na NULL

Doporučení pro praxi

  1. Na začátku projektu se rozhodněte pro jeden přístup:
    • Buď používejte pouze NULL pro chybějící hodnoty
    • Nebo pouze prázdné řetězce pro prázdné/chybějící hodnoty
  2. Toto rozhodnutí zdokumentujte v dokumentaci projektu
  3. Používejte CHECK constrainty pro vynucení konzistence
  4. U existujících projektů:
    • Proveďte audit současného stavu
    • Připravte migrační skript pro sjednocení přístupu
    • Nezapomeňte upravit aplikační logiku

Tímto přístupem se vyhnete mnoha problémům s porovnáváním, indexováním a JOIN operacemi, které vznikají při míchání NULL a prázdných řetězců. Vaše databáze bude konzistentnější a dotazy jednodušší.

Přejmenování hodnot v ENUM bez ztráty dat: bezpečný návod

Přejmenování hodnot v MySQL ENUMu je operace, která může být zrádná. Mnoho vývojářů se pokouší o přímou změnu, což často vede ke ztrátě dat nebo chybám. Ukážeme si, jak na to správně a bezpečně.

Představme si typický scénář: Máte v databázi tabulku objednávek (orders) se sloupcem status, který je typu ENUM. Obsahuje hodnoty waiting_payment, processing, shipped a cancelled. Požadavek je přejmenovat waiting_payment na unpaid a shipped na completed. Jak to udělat bez rizika?

Co nefunguje

Nejprve se podívejme na to, co nefunguje. Mnoho vývojářů zkusí tento přímočarý přístup:

-- TOHLE NEFUNGUJE!
ALTER TABLE orders
MODIFY COLUMN status ENUM(
    'unpaid',      -- původně 'waiting_payment'
    'processing',  -- beze změny
    'completed',   -- původně 'shipped'
    'cancelled'    -- beze změny
);

Takový přístup je receptem na katastrofu. MySQL se v takovém případě pokusí mapovat existující hodnoty na nový ENUM, a protože původní hodnoty už v definici nejsou, nahradí je prázdným řetězcem nebo vrátí chybu Data truncated for column 'status' at row X. V produkční databázi by to znamenalo ztrátu důležitých dat.

Nejprve zálohujte!

Před jakoukoli změnou struktury databáze je naprosto klíčové vytvořit zálohu dat. Použijte MySQL-dump nebo jiný nástroj, kterému důvěřujete.

Správný postup

Správný postup se skládá ze tří kroků:

  1. Nejprve rozšíříme ENUM o nové hodnoty
  2. aktualizujeme data
  3. nakonec odstraníme staré hodnoty.

Pojďme si to ukázat:

1. Prvním krokem je přidání nových hodnot do ENUMu, zatímco ponecháme ty původní:

ALTER TABLE orders
MODIFY COLUMN status ENUM(
    'waiting_payment',  -- původní hodnota
    'processing',       -- zůstává stejná
    'shipped',         -- původní hodnota
    'cancelled',       -- zůstává stejná
    'unpaid',          -- nová hodnota (nahradí waiting_payment)
    'completed'        -- nová hodnota (nahradí shipped)
);

2. Nyní můžeme bezpečně aktualizovat existující data:

UPDATE orders SET status = 'unpaid' WHERE status = 'waiting_payment';
UPDATE orders SET status = 'completed' WHERE status = 'shipped';

3. A konečně, když jsou všechna data převedena na nové hodnoty, můžeme odstranit ty staré:

ALTER TABLE orders
MODIFY COLUMN status ENUM(
    'unpaid',
    'processing',
    'completed',
    'cancelled'
);

Proč tento postup funguje?

Je to díky tomu, jak MySQL pracuje s ENUM hodnotami. Když provádíme ALTER TABLE s modifikací ENUMu, MySQL se snaží mapovat existující hodnoty podle jejich textové podoby. Pokud původní hodnota v novém ENUMu neexistuje, dojde v závislosti na nastavení sql_mode buď k chybě (při zapnutém STRICT_ALL_TABLES) nebo k náhradě prázdným řetězcem. Proto je klíčové mít v ENUMu vždy současně jak staré, tak nové hodnoty.

V našem případě to znamená, že během přechodné fáze, kdy máme v ENUMu hodnoty jako 'waiting_payment' i 'unpaid', každý záznam v databázi najde svůj přesný textový protějšek. Teprve po UPDATE dotazech, kdy už víme, že všechna data používají nové hodnoty, můžeme bezpečně odstranit ty staré.

Property Hooks v PHP 8.4: Revoluce nebo Past?

Představte si, že by vaše PHP objekty mohly být čistší, přehlednější a lépe použitelné. Dobrá zpráva – už nemusíte snít! PHP 8.4 přichází s revoluční novinkou v podobě property hooks a asymetrické viditelnosti, které kompletně mění pravidla hry v objektově orientovaném programování. Zapomeňte na neohrabané gettery a settery – konečně máme k dispozici moderní a intuitivní způsob, jak kontrolovat přístup k datům objektů. Pojďme se podívat na to, jak tyto novinky mohou změnit váš kód k nepoznání.

Property hooks představují promyšlený způsob, jak definovat chování při čtení a zápisu vlastností objektu – a to mnohem čistěji a výkonněji než dosavadní magické metody __get/__set. Je to jako byste dostali k dispozici sílu magických metod, ale bez jejich typických nevýhod.

Podívejme se na jednoduchý příklad z praxe, který vám ukáže, proč jsou property hooks tak užitečné. Představme si běžnou třídu Person s veřejnou property age:

class Person
{
	public int $age = 0;
}

$person = new Person;
$person->age = 25;  // OK
$person->age = -5;  // OK, ale to je přece nesmysl!

PHP sice díky typu int zajistí, že věk bude celé číslo (to lze od PHP 7.4), ale co s tím záporným věkem? Dříve bychom museli sáhnout po getterech a setterech, property by musela být private, museli bychom doplnit spoustu kódu… S hooks to vyřešíme elegantně:

class Person
{
	public int $age = 0 {
		set => $value >= 0 ? $value : throw new InvalidArgumentException;
	}
}

$person->age = -5;  // Ups! InvalidArgumentException nás upozorní na nesmysl

Krása tohoto řešení spočívá v jeho jednoduchosti – navenek se property chová úplně stejně jako dřív, můžeme číst i zapisovat přímo přes $person->age. Ale máme plnou kontrolu nad tím, co se při zápisu děje. A to je teprve začátek!

Můžeme jít ještě dál a vytvořit třeba hook pro čtení. Hookům lze přidat atributy. A samozřejmě mohou obsahovat složitější logiku než jednoduchý výraz. Podívejte se na tento příklad práce se jménem:

class Person
{
	public string $first;
	public string $last;
	public string $fullName {
		get {
			return "$this->first $this->last";
		}
		set(string $value) {
			[$this->first, $this->last] = explode(' ', $value, 2);
		}
	}
}

$person = new Person;
$person->fullName = 'James Bond';
echo $person->first;  // vypíše 'James'
echo $person->last;   // vypíše 'Bond'

A něco důležitého: kdykoliv se přistupuje k proměnné (i uvnitř samotné třídy Person), vždy se využijí hooks. Jediná výjimka je přímý přístup k reálné proměnné uvnitř kódu samotného hooku.

Ohlédnutí do minulosti: Co nás naučil SmartObject?

Pro uživatele Nette může být zajímavé ohlédnout se do minulosti. Framework totiž podobnou funkcionalitu nabízel už před 17 lety ve formě SmartObject, který výrazně vylepšoval práci s objekty v době, kdy PHP v této oblasti značně zaostávalo.

Pamatuju si, že tehdy přišla vlna bezbřehého nadšení, kdy se properties používaly prakticky všude. Tu pak vystřídala vlna opačná – nepoužívat je nikde. Důvod? Chybělo jasné vodítko, kdy je lepší použít metody a kdy property. Ale dnešní nativní řešení je kvalitativně úplně jinde.Property hooks a asymetrická viditelnost jsou plnohodnotné nástroje, které nám dávají stejnou úroveň kontroly jako máme u metod. Proto dnes můžeme mnohem lépe rozlišit, kdy je property skutečně tím správným řešením.

…pokračování

Readonly vlastnosti v PHP a jejich skrytá úskalí

Představte si, že byste mohli svým datům dát pevnou půdu pod nohama – jednou je nastavíte a pak si můžete být jistí, že je nikdo nezmění. Přesně to přineslo PHP 8.1 s readonly vlastnostmi. Je to jako dát vašim objektům neprůstřelnou vestu – chrání jejich data před nechtěnými změnami. Pojďme se podívat, jak vám tento mocný nástroj může usnadnit život a na co si při jeho používání dát pozor.

Začněme jednoduchým příkladem:

class User
{
    public readonly string $name;

    public function setName(string $name): void
    {
        $this->name = $name;  // První nastavení - vše OK
    }
}

$user = new User;
$user->setName('John');      // Paráda, máme jméno
echo $user->name;            // "John"
$user->setName('Jane');      // BOOM! Výjimka: Cannot modify readonly property

Jakmile jednou jméno nastavíte, je to jako vytesané do kamene. Žádné náhodné přepsání, žádné nechtěné změny.

Kdy je uninitialized opravdu uninitialized?

Často se setkávám s mýtem, že readonly vlastnosti musí být nastaveny v konstruktoru. Ve skutečnosti je PHP mnohem flexibilnější – můžete je inicializovat kdykoliv během života objektu, ale pouze jednou! Před prvním přiřazením jsou ve speciálním stavu ‚uninitialized‘, což je takový limbo stav mezi nebytím a bytím.

A tady přichází zajímavý detail – readonly vlastnosti nemohou mít výchozí hodnotu. A proč? Kdyby měly výchozí hodnotu, staly by se de facto konstantami – hodnota by byla nastavena při vytvoření objektu a už by nešla změnit.

Vyžadují se typy

Readonly proměnné vyžadují explicitní definici datového typu. Je to proto, že stav ‚uninitialized‘, který využívají, existuje pouze u typovaných proměnných. Bez uvedení typu tedy readonly proměnnou nelze definovat. Pokud si nejste jistí typem, můžete použít mixed.

…pokračování


phpFashion © 2004, 2026 David Grudl | o blogu

Ukázky zdrojových kódů smíte používat s uvedením autora a URL tohoto webu bez dalších omezení.