#1 Martin: Mimochodem je to i mnohem pomalejší volání než použít řetězec jako index.
Deset vlastností PHP, o kterých jste možná nevěděli
Jazyk PHP obsahuje celou řadu vlastností, které nejsou každému známé. Proto jsem připravil tento minitestík, kde si některé z nich můžete připomenout. Předpokládám, že většinu znát budete, ale co kdyby ne...
Zadání
1.příklad
{ $a = 'ab'; }
2.příklad
#aaa
3.příklad
$a = 'abcd'; echo $a{0};
4.příklad
$x = array('a'=>1, 'b'=>2); echo $x[b];
5.příklad
$x = array('a'=>1, 'b'=>2); foreach($x as &$y) $y = 0; echo $x['a'];
6.příklad
$x = 'aaa'; echo ++$x;
7.příklad
$x = (object) array('a'=>1, 'b'=>2); echo $x->a;
8.příklad
$x = new StdClass(); $i = 1; $x->{'bbb' . $i} = 1;
9.příklad
echo (5 == '5abc');
10.příklad
$className = 'StdClass'; $obj = new $className();
Řešení
1.příklad
Blok kódu nemusí být pouze součástí nějáké konstrukce (switch, while), ale může existovat i zcela samostatně. Smysluplné využití mě ale nenapadá.
2.příklad
Komentáře mohou mít nejen sytaxi C (/* */) a C++ (//), ale i syntaxi shellovou (#).
3.příklad
Jednotlivé znaky řetězce můžeme v PHP adresovat podobně jako u pole znaků.
4.příklad - UPDATE
Řetězcový index do pole ($x['ab']) můžeme sice zapsat i bez použití uvozovek/apostrofů, ale může to způsobit velmi nepříjemné chyby. Neohraničený řetězec je totiž považován za konstantu, a proto se PHP pokusí nahradit její jméno obsahem. Když žádná taková konstanta neexistuje, je převedena na řetezec a je vyhozena E_NOTICE chyba.
5.příklad
Při použití operátoru reference v příkazu foreach můžeme měnit obsah iterovaného pole.
6.příklad
Ano, i řetězec lze inkrementovat. Řetězec se chová jako číslo, takže dochází i k přenosu do vyššího řádu ('abz' => 'aca'). Nesmí být ale použita diakritika.
7.příklad
PHP umožňuje přetypovat pole na objekt. Prvky pole se pak stávají členskými proměnnými objektu.
8.příklad
Adresaci členských proměnných můžeme provádět i pomocí rozšířeného zápisu ($x->{'a'}). Alternativou je použití pomocné proměnné ($x->$y).
9.příklad
Pokud porovnáváme řetězec a číslo, snaží se PHP přetypovat řetězec na číslo. To udělá tak, že pokud na začátku řetězce je číslo, je výsledkem přetypování toto číslo. V ostatních případech je výsledkem konverze nula.
10.příklad
Jméno třídy může být zadáno implicitně pomocí proměnné.
Hodnocení
Komentáře
Příklad 4 je prachsprostá chyba. A může se velmi krutě vymstít.
například
define('b', 'cha cha cha, tuhle chybu budete hledat dlouho!');
// ... dlouho nic, mnoho řádků
echo $x[b];
Ono totiž to, když napíšete řetězec bez uvozovek (jednoduchých || dvojitých), ono to neznamená ten samý řetězec! Ono to jenom hledá konstantu stejného jména, a když jí najde, použije jí – jako v mém případě, když ne, rezignuje s chybovou hláškou a TEĎ V TUTO CHVÍLI php dosadí ten samý řetězec. Ale týmu php se nelíbí zneužívání této vlastnosti a zanášení skrytých chyb tímto způsobem, tak velmi přemýšlejí na zabránění.
Takže používejte si řetězce bez uvozovek, ale nesmíte se divit, až Vám kód nebude chodit a budete dlouho hledat chybu.
V PHP se dá dělat spousta podobných fíglů, čili jejich shrnutí (byť částečné) je ku prospěchu věci. Jen tak dál. Bude další díl? ;-)
#4 Marek Soldát: Když mě ještě něco napadne, tak klidně :)
díky!
příklad 4 je opravdu fuj :P
k číslu 8 dodávám, že to funguje nejen se členskými proměnnými. jméno jakékoliv proměnné lze zadat jako výraz ve složených závorkách. a to třeba i tak: "${foo().'bar'}"
#6 paranoiq: Tak na tenhle způsob sestavení jména proměnné jsem už zapomněl.
Další hezkou věcí je vícečetná "dereference":
$$var
Bod číslo 4 není vlastnost, alébrž pochybné chování PHPčka, které neexistující konstantu přetypovává na řetězec. E_STRICT na Tebe!
K bodu číslo 10 - píšeš, že "jméno třídy může být zadáno implicitně pomocí proměnné nebo konstanty". Pomocí proměnné si to představit umím, to je přímo v Tvé ukázce. Jak to ale bude prosím pěkně vypadat s pomocí konstanty? ;)
#8 Jan Tichý: Vlastně stačí i E_NOTICE...
#8 Jan Tichý: Hahá, to je ale chyták co? :) Díky, opravím.
#6 paranoiq: samozřejmě bez těch zp. lomítek
ještě k bodu 4:
nedefinované konstanty ve jmenných prostorech už PHP řeší správně fatal errorem. doufám, že časem přitvrdí i u globálních konstant
Vyuziti 1#
private void Delej() { { if (xx) break; if (yy) break; if (ff) break; } dalsi kod } // konec metody
aneb pri return se ukonci metoda, zatimco v tomhle pouziti se jeste vykona nakej kod.
Aspn myslim, ze by to tak mohlo fungovat...
K prvnímu příkladu: Složené závorky a cokoli v nich nahrazují jeden příkaz. Kdekoli a kdykoli. To znamená blok jde použít všude, kde lze použít jeden příkaz. To, že blok jde napsat kdekoli, kde příkaz je důsledek syntaktické čistoty a jednoduchosti.
Bylo to převzato z jazyka C, kde blok měl ještě dodatečné vlastnosti. Určoval oblast platnosti proměnných (scope), což php nepřevzalo, a namísto toho vytvořilo pouze jednoduché scopes – global, module, function, superglobal – that's all folks.
Nicméně to neznamená, že blok nedostane žádnou další funkci v budoucnu.
K třetímu příkladu: Na přístup ke znakům pomocí složených závorek bych raději zapomněl. Je to deprecated už řadu let a v PHP6 to zmizí úplně.
K šestému příkladu: Je to prasečina, a dobrý programátor se tomu raději vyhne.
K trikování pomocí řetězců a sestavování názvů proměnných / objektů přes řetězce: Až PHP vylepší optimalizaci, což se dá v příštích verzích očekávat, budete za toto trikování odměněni velkou rychlostní penalizací, neboť tyto triky budou klidně zpomalovat skript i třeba stonásobně. Je jenom otázkou času, kdy PHP zavede překlad předem známých názvů a proměnných na adresy paměti už ve fázi překladu byte kódu. Že k tomu dojde někdy dojde je jisté, neboť to umožní akcelerovat rychlost PHP skriptů do docela velmi závratných výšin, které jsou na hranici fantazie. A zároveň velmi snížit zátěž serverů s PHP. Běh skriptu se velmi zryhlí až na místa … na místa, kde trikujete s tvořením proměnných a objektů pomocí řetězců – tato místa extrémně zpomalí.
#13 Miloslav Ponkrác: IMHO není rychlost php vůbec na pořadu dne. zpomalení se děje na jiných úrovních - jako je komunikace s db (tvoření spojení), čtení z disku, apod.
K tomu 5. příkladu by bylo asi dobré říct, že tato vlastnost byla zavedena až v PHP5.
Neexistuje aj niečo ako $var = <<< ...? Niekde som znaky <<< v súvislosti s php už videl, len už neviem kedy sa dajú použiť. Google bez výsledku.
Za prípadnú odpoveď ďakujem.
#16 vasava: - príspevok má pokračovanie, zvyšok sa nezobrazil...
K příkladu 5 by bylo dobré říct že nefunguje od PHP 5.2
Díky za článek. Něco jsem věděl, něco ne, ale každopádně to dokazuje, že PHP je zajímavý jazyk (teda, pokud bych to chtěl vyjádřit slušně:-))
#18 eMan: Proč by to nemělo v PHP 5.2 fungovat? Funguje to stále a dle mého mínění je to velmi dobrý způsob úpravy obsahu pole při iteraci.
Daleko lepší než
for($i=0; $i < count($arr); $arr++) $arr[$i] = 0;nebo
foreach($arr as $i => $val) $arr[$i] = 0;
#20 Dundee: hovoří tak "php manuál":http://us3.php.net/manual/en/control-structures.foreach.php
> As of PHP 5, you can easily modify array's elements by preceding $value with &. This will assign reference instead of copying the value.
#20 Dundee: omlouvám se, je vidět, že čtu jen to, co sem číst chtěl. Měl sem za to, že eman píše o tom, že to nefunguje v php < 5. :D prosím, raději obojí smazat :)
Dundee: ale už nemusíš uvaděn znak rerence & .... takže ten příklad takhle jak je fungovat nebude...
#23 eMan: Pokud chceš měnit obsah toho pole, tak znak reference uvádět musíš.
Viz třeba PHP 5 Power Programming (http://www.informit.com/content/images/013147149X/downloads/013147149X_book.pdf) strana 8 nahoře.
Ad 1 - vlastnost často používám například u checkboxů.
V šabloně mám něco jako
<input type=checkbox value="ID" {checkedID}>A v php po tom dělám něco jako:
$sablona->{"checked".$id} = "checked";
Vojta
Ad 4: Toto ovšem vyvolá notice: Use of undefined constant b - assumed 'b'