Klávesové zkratky na tomto webu - rozšířené Na obsah stránky

porucha není na vašem přijímači

Laděnka, jak se vám líbí?

Laděnka je užitečnou každodenní pomocnicí PHP programátora. Její oficiální jméno zní Nette::Debug.

Upozornění: Aktuální informace najdete na webu Nette Framework.

Každý ladič je dobrým kamarádem s funkcí var_dump, která podrobně vypíše obsah proměnné. Bohužel v prostředí HTML výpis pozbude formátování a slije se do jednoho řádku, o sanitizaci HTML kódu ani nemluvě. V praxi je nezbytné var_dump nahradit šikovnější funkcí. Tou je právě Debug::dump()

$arr = array(10, 20.2, TRUE, NULL, 'hello');

Debug::dump($arr);
// včetně jmenného prostoru Nette::Debug::dump($arr);

vygeneruje výstup:

array(5) {
  [0] => int(10)
  [1] => float(20.2)
  [2] => bool(true)
  [3] => NULL
  [4] => string(5) "hello"
}

Dalším užitečným nástrojem ladiče jsou stopky s přesností na mikrosekundy:

Debug::timer();

// princi můj malinký spi, ptáčkové sladce již sní...
sleep(2);

$elapsed = Debug::timer();
// $elapsed ≈ 2

Tohle všechno jsou sice užitečné drobnosti, skutečným killerem je však jiná Laděnčina vlastnost. Zpráva o nezachycené výjimce nebo chybě poskytuje vývojáři důležité informace o tom, kde a proč k ní došlo. Standardní výstup v PHP vypadá asi takto:

Standardní podoba nezachycené výjimky

Pusťme však ke slovu Laděnku. Po aktivaci příkazem Debug::enable() nám předvede svou nejvíce sexy polohu:

Nezachycená výjimka v provedení NDebug

Takto vypadá výjimka, takto vypadá vygenerovaná chyba. To je pak jiné ladění, co?

Snad nemusím dodávat, že vypisování chyb se nesmí nikdy dostat na produkční server. Je to výborná společnice na pracovišti, ale nikdy ji nesmíme brát sebou ven. Je totiž děsně ukecaná a vyzradí na vás úplně všechno (nicméně kdyby k tomu náhodou došlo, má integrovaný systém pro skrytí citlivých políček, např. hesel). Na produkčním serveru je však možné nechat výpisy ukládat do adresáře nebo odesílat administrátorovi emailem.

→ Download: Nette::Debug.zip, licence, překlad

(doplněno: mám na vás prosbu…)

clock 30. 1. 2008 pencil Texy! – Nette – Dibi comments


Závěrem dibitýdne...

…tu mám ještě několik novinek. Především, nyní je možné do řetězce zapsat více modifikátorů najednou a teprve poté uvést jejich hodnoty:

dibi::query('
SELECT * FROM [table]
WHERE id = %i AND added > %d', $id, $time
);

Tímto se z modifikátorů stávají takové chytré „placeholders“. Už ani nemusí být umístěny zcela na konci řetězce.

Zároveň zavádím několik nových modifikátorů:

  • %ex pro expanzi pole do argumentů (Rubysté znají jako *[1,2,3])
  • %or a %and před polem spojí jeho prvky s oddělovačem ‚AND‘ nebo ‚OR‘
  • %lmt a %ofs pro přenositelné a možná snadnější nastavení LIMITOFFSET

Příklady použití:

$where[] = '[age] > 20';
$where[] = '[email] IS NOT NULL';
dibi::query('SELECT * FROM [table] WHERE %and', $where);
// SELECT * FROM [table] WHERE [age] > 20 AND [email] IS NOT NULL

nebo také

$where['age'] = 20;
$where['email'] = 'franta@example.com';
dibi::query('SELECT * FROM [table] WHERE %and', $where);
// SELECT * FROM [table] WHERE [age]=20 AND [email]='franta@example.com'

Limity a ofsety:

// with limit = 30, offset = 90
dibi::query('SELECT * FROM [products] %lmt %ofs', 30, 90);
// SELECT * FROM [products] LIMIT 30 OFFSET 90

// with offset = 100
dibi::query('SELECT * FROM [products] %ofs', 100);
// pro SQLite:
// SELECT * FROM [products] LIMIT -1 OFFSET 100
// pro MySQL:
// SELECT * FROM [products] LIMIT 18446744073709551615 OFFSET 100
// pro PostgreSQL:
// SELECT * FROM [products] OFFSET 100

Funkčnost modifikátorů %and & %or považujte za experimentální. Očekávám vaše připomínky a podle nich ji případně upravím. Jinak změny si vyžádaly větší zásah do zdrojového kódu dibi-překladače a ačkoliv jsem všechno velmi důkladně otestoval, buďte při nasazování pozorní.

clock 18. 1. 2008 pencil Texy! – Nette – Dibi comments


Experiment DibiTable

Upozornění: Knihovna se neustále vyvíjí, aktuální informace najdete na webu dibiphp.com.

Zkusil jsem do dibi přidat takovou hračku:

/*
CREATE TABLE [albums] (
[id] INTEGER  NOT NULL PRIMARY KEY,
[artist] VARCHAR(100) NOT NULL,
[title] VARCHAR(100) NOT NULL)
*/

class Albums extends DibiTable
{
}

Třída Albums reprezentuje databázovou tabulku (pokud jméno tabulky neurčíme, bude se detekovat z názvu třídy). Nad ní můžeme vykonávat třeba tyto operace:

$albums = new Albums;

// přečtení jednoho záznamu podle primárního klíče:
$key = 5;
$data = $albums->fetch($key);

// smazání záznamu č. 7
$albums->delete(7);

// smazání více záznamů
$count = $albums->delete(array(1, 2, 4));

// úprava záznamu č. 4
$data->title = 'new title';
$albums->update(4, $data);
// obdobně jako u delete lze měnit více záznamů

// vložení záznamu
$id = $albums->insert($data);

Dále lze provádět jednoduché výběry:

// řádky s klíčem 2, 3 a 5
foreach ($albums->find(2, 3, 5) as $row) {
   ...
}

// vypiš celou tabulku v HTML
$albums->findAll()->dump();

// výběr s řazením podle artist, title
$albums->findAll('artist', 'title');

Jde o velmi jednoduchého pomocníka (tzv. helper) pro rutinní operace nad tabulkou. Tedy žádné složité ORM nebo ActiveRecords. Tuším se tomu říká Table Data Gateway. Funkce je čerstvá a ve stádiu experimentování.

Ještě drobnost. Dibi je už ze své podstaty zcela imunní vůči SQL injection, takže se jich nemusíte obávat:

$key = '3 OR 1=1'; // podvrh
$albums->delete($key);
// --> DELETE FROM [albums] WHERE [product_id] = 3

clock 15. 1. 2008 pencil Texy! – Nette – Dibi comments


Extrémě rychlý "load SQL file"

Tak hele, v šest ráno po mně nemůžete chtít kultivovaný titulek, spokojte se i s tímto.

Upozornění: Aktuální informace najdete na webu dibiphp.com.

K zálohování nebo přenášení databází mezi více servery se používá tzv. SQL dump. Jde o textový soubor obsahující popis struktury i obsahu tabulek ve formě série SQL příkazů. K jeho generování z příkazové řádky je určen nástroj mysqldump, na hostingu se obvykle používá interaktivní phpMyAdmin.

Aplikaci phpMyAdmin lze použít i k obnovení ze zálohy, tj. načtení SQL dumpu. Bohužel se s tím neskutečně párá a proces trvá moc dlouho. Databáze obsahující jen pár tisíc záznamů nelze takto vůbec importovat – to dřív vyprší časový limit běhu PHP skriptu.

Pokusil jsem se kdysi napsat rychlejší importér a povedlo se. Co phpMyAdmin louská dlouhé minuty, zvládne tento za zlomek sekundy. Nástroj jsem nyní začlenil do dibi a používá se takto:

dibi::connect();
dibi::loadFile('dump.sql');

Lze načítat i komprimovaný soubor:

dibi::loadFile('compress.zlib://dump.sql.gz');

Soubor se čte postupně, takže nevadí, když je větší než dostupná paměť.

Metoda vrací počet vykonaných příkazů. V případě chyby vyhodí výjimku. Ještě zdůrazňuji, že je určen pro SQL dump ve formátu, který generují zmíněné nástroje.

Tip: SQL dump generujte se zaškrtnutou volbou „Rozšířené inserty“ (Extended inserts), má to zásadní vliv na rychlost načítání, ať už používáte jakýkoliv importér.

clock 12. 1. 2008 pencil Texy! – Nette – Dibi comments


Nette::Object - taťka všech objektů

Je známo, že objekty se do jazyka PHP dostaly spíš jako nezvaní hosté. Docela příznačným rozdílem mezi jazykem, který byl jako objektový již navrhován, a jazykem, který se jím stal k velkému překvapení samotných tvůrců, je v absenci resp. přítomnosti společného předka všech tříd. Object Pascal deklaruje TObject, DOT.NET má System.Object a v Javě nebo Ruby stojí v hierarchii nejvýše Object (je delikátní, že nejzákladnější třída bývá pojmenována objekt). V PHP nic takového neexistuje.

Základní třída obvykle deklaruje metody pro sebereflexi. Například metodu vracející název třídy. Je to sice detail, ale vždycky mi připadalo tuze ošklivé mixovat hezký objektový kód s voláním pro-objektové funkce get_class:

$a = $obj->myMethod();
$class = $obj->getClass(); // hezké
$class = get_class($obj); // ošklivé

continuepokračování...

clock 1. 12. 2007 pencil Texy! – Nette – Dibi comments


La Trine © 2004, 2008 David Grudl – o webu
provozuje Pachollini.

Jakékoliv užití obsahu, včetně převzetí článků nebo jejich částí, je bez předchozího písemného svolení autora zakázáno.

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