PHP 5.4
Po téměř třech letech vyšla finální verze PHP 5.4, která přináší mnoho novinek. Tady jsou ty nejzajímavější.
Pole
Pole dostala novou kompaktní syntaxi:
[19, 5, 2013] ['Mortis Arytmia' => 7, 'Terminalita' => 41]
Konečně můžeme dereferencovat pole a už nemusíme laborovat s dočasnými proměnnými, když chceme použít jenom něco z vráceného pole
// postaru: $ex = explode(',', $str); $a = $ex[0]; // postaru, ale trochu vynalézavěji: list($a) = explode(',', $str); // nově: $a = explode(',', $str)[0];
Ale na druhou stranu nefunguje identická konstrukce s funkcemi. Takže currying musíme nechat u ledu.
func($arg)($arg2)
Funkce
Konečně můžeme vytvořit objekt a hned na něm zavolat nějakou metodu bez rošád s dočasnými proměnnými.
(new Person)->runAway();
Přibyl nový typehint callable
, který zahrnuje anonymní funkce (třída
Closure), všechny objekty mající metodu __invoke
, a pseudotyp callable ve
formách "functionName"
, array($object, 'method')
a array('Classs', 'method')
.
function map($collection, callable $f) { /* ... */ }
Syntaxe $f()
funguje i když je $f
pole ve tvaru array($obj, 'method')
. Minulá verze
PHP si v tomhle případě stěžovala a bylo se nutné uchýlit k obezličce call_user_func
, která má
mimořádný talent znepřehlednit kód (například v Atrox\Arr jsem na to
rezignoval s tím, že věci v 5.3 můžou můžou zlobit).
Velkou novinkou je, že anonymní funkce definované v těle třídy mají přístup k proměnné $this
aktuální instance. Nemusíme ji ručně importovat do scope
funkce a navíc máme přístup k privátním členům objektu i jeho třídy, tedy
přesně jako kdyby closure byla metodou třídy.
//dříve: $self = $this; function ($args) use($self) { return $self->method($args); } //teď: function ($args) { return $this->method($args); }
Třída Closure, která implementuje anonymní funkce, dostala novou metodu
bindTo
, pomocí, které můžeme změnit instanci na kterou je navázená proměnná
$this
uvnitř anonymní funkce. Nevím proč něco takového přidávali, protože se to
dá velice snadno zneužít pro přístup k soukromým proměnným libovolného objektu
bez použití reflexe.
class Person { private $name = "Karel", $surname = "Kalandra", $powerLevel = 9001; } $fuckEverything = function() { foreach (get_object_vars($this) as $prop => $val) $this->$prop = "U DUN GOOFED!"; }; $person = new Person; $fuckEverything = $fuckEverything->bindTo($person, $person); $fuckEverything(); var_dump($person); // U DUN GOOFED!
Traity
Poslední novinkou (a pravděpodobně tou největší v 5.4) jsou traity, které umožní znovupoužití kódu mimo strom dědičnosti. Nejde o žádné složitosti, jenom jazykem asistovaný copy-paste skupiny metod. Traity si s sebou nenesou žádný typ, nemají stav, neprobíhá žádná linearizace, takže se všechny konflikty se musejí vyřešit ručně a jeden trait nemůže „dekorovat“ metody jiného traitu.
trait PropertyAsMethod { function __get($name) { return $this->$name(); } } class Person { use PropertyAsMethod; // použijeme trait function runAway() { var_dump("Přes kopce a daleko, daleko, do Západních zemí."); } } $person = new Person; $person->runAway(); // normálně $person->runAway; // funkcionalita získaná z traitu PropertyAsMethod