k47.cz
mastodon twitter RSS
bandcamp explorer

PHP 5.4

23. 3. 2012 (před 11 lety) — k47 (CC by-nc-sa)

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')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
píše k47, ascii@k47.cz