k47.cz  — každý den dokud se vám to nezačne líbit
výběr foto Praha povídky kultura
TECH ▞▞ kolo | twitter RSS

PHP 5.4

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

Po téměř třech letech vyšla fi­nální verze PHP 5.4, která při­náší mnoho no­vi­nek. Tady jsou ty nej­za­jí­ma­vější.


Pole

Pole do­stala novou kom­paktní syn­taxi:

[19, 5, 2013]
['Mortis Arytmia' => 7, 'Terminalita' => 41]

Ko­nečně můžeme de­re­fe­ren­co­vat pole a už ne­mu­síme la­bo­ro­vat s do­čas­nými pro­měn­nými, když chceme použít jenom něco z vrá­ce­né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 ne­fun­guje iden­tická kon­strukce s funk­cemi. Takže curry­ing musíme nechat u ledu.

func($arg)($arg2)

Funkce

Ko­nečně můžeme vy­tvo­řit objekt a hned na něm za­vo­lat ně­ja­kou metodu bez rošád s do­čas­nými pro­měn­nými.

(new Person)->runAway();

Přibyl nový ty­pehint callable, který za­hr­nuje ano­nymní funkce (třída Clo­sure), všechny ob­jekty mající metodu __invoke, a pseu­do­typ calla­ble ve for­mách "functionName", array($object, 'method')array('Classs', 'method').

function map($collection, callable $f) { /* ... */ }

Syn­taxe $f() fun­guje i když je $f pole ve tvaru array($obj, 'method'). Minulá verze PHP si v tomhle pří­padě stě­žo­vala a bylo se nutné uchý­lit k obe­z­ličce call_user_func, která má mi­mo­řádný talent zne­pře­hled­nit kód (na­pří­klad v Atrox\Arr jsem na to re­zig­no­val s tím, že věci v 5.3 můžou můžou zlobit).

Velkou no­vin­kou je, že ano­nymní funkce de­fi­no­vané v těle třídy mají pří­stup k pro­měnné $this ak­tu­ální in­stance. Ne­mu­síme ji ručně im­por­to­vat do scope funkce a navíc máme pří­stup k pri­vát­ním členům ob­jektu i jeho třídy, tedy přesně jako kdyby clo­sure byla me­to­dou třídy.

//dříve:
$self = $this;
function ($args) use($self) {
  return $self->method($args);
}

//teď:
function ($args) {
  return $this->method($args);
}

Třída Clo­sure, která im­ple­men­tuje ano­nymní funkce, do­stala novou metodu bindTo, pomocí, které můžeme změnit in­stanci na kterou je na­vá­zená pro­měnná $this uvnitř ano­nymní funkce. Nevím proč něco ta­ko­vého při­dá­vali, pro­tože se to dá velice snadno zne­u­žít pro pří­stup k sou­kro­mým pro­měn­ným li­bo­vol­ného ob­jektu bez po­u­žití re­flexe.

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

Po­slední no­vin­kou (a prav­dě­po­dobně tou nej­větší v 5.4) jsou traity, které umožní zno­vupo­u­žití kódu mimo strom dě­dič­nosti. Nejde o žádné slo­ži­tosti, jenom ja­zy­kem asis­to­vaný copy-paste sku­piny metod. Traity si s sebou ne­ne­sou žádný typ, nemají stav, ne­pro­bíhá žádná li­nea­ri­zace, takže se všechny kon­flikty se musejí vy­ře­šit ručně a jeden trait nemůže „de­ko­ro­vat“ 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 & hosté, ascii@k47.cz