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

[1] Martin
2009-07-08 13:16:47

Ad 4: Toto ovšem vyvolá notice: Use of undefined constant b - assumed 'b'

Na tento komentář odpověděl [2] Vojtech Vondra
2009-07-08 14:56:51

#1 Martin: Mimochodem je to i mnohem pomalejší volání než použít řetězec jako index.

2009-07-08 15:11:49

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.

2009-07-08 15:16:00

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? ;-)

Na tento komentář odpověděl [5] Dundee
[5] Dundee
2009-07-08 17:12:33

#4 Marek Soldát: Když mě ještě něco napadne, tak klidně :)

2009-07-08 19:34:33

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'}"

Na tento komentář odpověděl [7] Dundee
Na tento komentář odpověděl [11] paranoiq
[7] Dundee
2009-07-08 19:50:05

#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

2009-07-08 21:02:08

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? ;)

Na tento komentář odpověděl [9] Jan Tichý
Na tento komentář odpověděl [10] Dundee
2009-07-08 21:03:39

#8 Jan Tichý: Vlastně stačí i E_NOTICE...

2009-07-08 23:42:56

#8 Jan Tichý: Hahá, to je ale chyták co? :) Díky, opravím.

2009-07-09 10:33:36

#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

[12] Matej
2009-07-09 20:38:51

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...

2009-07-09 23:27:46

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í.

Na tento komentář odpověděl [14] Hrach
[14] Hrach
2009-07-10 16:24:46

#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.

[15] Bochi
2009-07-12 06:32:03

K tomu 5. příkladu by bylo asi dobré říct, že tato vlastnost byla zavedena až v PHP5.

[16] vasava
2009-07-12 19:29:36

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.

Na tento komentář odpověděl [17] vasava
[17] vasava
2009-07-12 19:31:22

#16 vasava: - príspevok má pokračovanie, zvyšok sa nezobrazil...

[18] eMan
2009-07-16 19:00:05

K příkladu 5 by bylo dobré říct že nefunguje od PHP 5.2

Na tento komentář odpověděl [20] Dundee
[19] Petr
2009-07-18 10:52:27

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ě:-))

2009-07-19 21:11:33

#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;

Na tento komentář odpověděl [21] Hrach
Na tento komentář odpověděl [22] Hrach
[21] Hrach
2009-07-20 11:16:35

#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.

[22] Hrach
2009-07-20 11:18:36

#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 :)

[23] eMan
2009-08-13 12:55:24

Dundee: ale už nemusíš uvaděn znak rerence & .... takže ten příklad takhle jak je fungovat nebude...

Na tento komentář odpověděl [24] Dundee
2009-08-13 14:11:34

#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.

2009-11-10 21:50:22

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

Komentáře již nelze přidávat