PHP 5.4 přináší změny a nové jazykové konstrukce

PHP5

Vyšlo PHP 5.4.0, a i když je zatím ve verzi alpha, podíváme se na novinky v tomto jazyce, na nové konstrukce, odstraněné konstrukce a další změny, kterých sice není tolik jako ve verzi 5.3, ale jsou zajímavé. Změny pro čtenáře Zdrojáku sumarizoval a okomentoval Jakub Vrána.

PHP 5.4 nepřinese tolik novinek jako PHP 5.3, změny mi ale povětšinou dělají radost.

Odstranění zastaralých obratů

PHP 5.3 označilo řadu obratů jako zastaralých, takže jejich odstranění z PHP 5.4 není žádným překvapením. Co zmizelo?

  1. Konstrukce break $var;
  2. Konfigurační direktiva safe_mode a související
  3. Konfigurační direktivy register_globals a register_long_arrays
  4. Konfigurační direktiva allow_call_time_pass_reference
  5. Konfigurační direktiva highlight.bg
  6. Konfigurační direktivy session.bug_compat_42 a session.bug_compat_warn
  7. Konfigurační direktiva y2k_compliance
  8. Funkce session_is_registered, session_register a session_unregister
  9. Funkce import_request_variables
  10. Funkce define_syslog_variables a stejnojmenná konfigurační direktiva

Žádný z těchto obratů už léta nepoužívám, takže jejich odstranění vítám, protože do budoucna umožní zjednodušení aplikací nebo snížení nároků na jejich konfiguraci. Konfigurační direktivy magic_quotes_gpc a magic_quotes_runtime kupodivu přežily, i když pro první jmenovanou existuje náhrada na úrovni konfigurace a druhá se prakticky nikdy nepoužívala.

Bez náhrady zdá se zmizela i užitečná direktiva  safe_mode_exec_dir.

Nové vlastnosti

  • $_SERVER['REQUEST_TIME'] nově obsahuje i mikročas (dříve jen čas s přesností na sekundy).
  • Výchozí hodnota konfigurační direktivy default_charset v dodávaném php.ini je UTF-8 (dříve  ISO-8859-1).
  • array_combine(array(), array()) vrací array() (dříve false).
  • Třetí parametr funkce preg_match_all je nepovinný. To se hodí pro zjištění počtu výskytů regulárního výrazu.
  • $a = null; $a->a = 1; nyní vyvolá varování (dříve potichu prošlo).
  • <?= funguje nezávisle na nastavení short_open_tag.
  • Podpora nepřímého volání metod: $f = array($obj, 'method'); $f();.
  • Přístup k prvku pole vráceného funkcí: f()[0].
  • Možnost použít $this uvnitř anonymních funkcí (netřeba uvádět v  use).
  • Možnost zpracovat zdrojáky ve vícebajtovém kódování pomocí zend.multibyte (bohužel zatím není povoleno ve verzi pro Windows).
  • Funkce http_response_code vracející momentální HTTP status.
  • Funkce header_register_callback dovoluje zaregistrovat callback zavolaný těsně před posláním hlaviček.
  • Parametr $limit u funkcí debug_backtrace a debug_print_backtrace.
  • Smysl konstrukce $string[1][0] mi sice uniká, ale aspoň už nevyvolá chybu.
  • Některé funkce dříve specifické pro Apache jsou nyní k dispozici i pod FastCGI.
  • Funkce number_format už dokáže zpracovat i delší oddělovače desetin a tisíců. To dovoluje použít vícebajtové kódování (např. pevnou mezeru v UTF-8) a HTML entity (např.  &nbsp;).
  • Funkce hex2bin($data) (jako protiklad k bin2hex) je funkčně totožná s  pack("H*", $data).

I v této části jde převážně o čištění jazyka a se změnami souhlasím. Mírně kontroverzní může být <?=, XML validita PHP skriptů ale stejně zaručena nikdy nebyla i při vypnutém short_open_tag (např. kód <?php echo "?><"; ?> je platný PHP skript, ale neplatný XML fragment).

Za zásadní změnu považuji zavedení konstrukce f()[0], která byla dlouho požadovaná a stejně dlouho odmítaná např. z důvodů horší čitelnosti. Možná se také ptáte, k čemu je z funkce vracet pole a použít z něj jediný prvek? Mně by se to kdysi hodilo v NotORM, kde byla původně metoda group dovolující provést třeba i více agregačních funkcí najednou: list($min_id, $max_id) = $table->group("MIN(id), MAX(id)"). Bohužel se ale neobešla bez dočasné proměnné ani v nejběžnějším případě, kdy se volala jen jedna agregační funkce. S PHP 5.4 by to šlo: $table->group("MIN(id)")["MIN(id)"]. Nové API $table->min("id") je ale stejně přehlednější.

Traits

Asi největší novinkou v PHP 5.4 je podpora takzvaných traits. Ty dovolují zmírnit nevýhody jednonásobné dědičnosti tím, že do třídy umožňují vložit definice metod ze společného zdroje nezávislého na dědičnosti. Hodí se to v situaci, kdy chci mít stejnou funkčnost ve více třídách bez společného rodiče. Někdy se to dá vyřešit pomocí metody  __call:

class C {
    public $common;
    function __call($name, $args) {
        if (method_exists($this->common, $name)) {
            return call_user_func_array(array($this->common, $name), $args);
        }
        trigger_error("Call to undefined method " . __CLASS__ . "::$name()", E_USER_ERROR);
    }
}

Zdaleka to ale nejde vždy, např. při implementaci rozhraní s tímto přístupem nepochodíme, protože tam musí být metody definované přímo. Pak nezbývá nic jiného, než je ve třídě všechny potupně zopakovat. PHP 5.4 řeší tento problém pomocí tzv. horizontal reuse:

trait T {
    function getIterator() {
        echo "T::getIterator()n";
        return new ArrayIterator($this->data);
    }
}

class C implements IteratorAggregate {
    public $data = array();
    use T;
}

$c = new C;
var_dump($c instanceof T); // bool(false)
foreach ($c as $val) { // T::getIterator()
}

Změnu považuji za největší i proto, že přidává nové klíčové slovo. Možnosti jsou ještě širší, především lze definovat řešení kolizí. Zatím je funkčnost popsaná v RFC, píše se ale už i dokumentace.

Jsem zvědav, který framework začne traits využívat jako první. A také který dokumentační nástroj a které IDE se s touto novou vlastností dokáže se ctí vypořádat.

Zákaz změny parametrů u abstraktních konstruktorů

Poměrně zásadní zpětně nekompatibilní změna se týká sjednocení chování při dědění abstraktních konstruktorů s ostatními metodami. Jde o to, že když v potomkovi definujeme abstraktní metodu, musíme zachovat její parametry (můžeme jim přidat výchozí hodnotu, můžeme přidat další parametry s výchozí hodnotou, ale nemůžeme parametry odebrat nebo jim změnit typ):

abstract class A {
    abstract function __construct($a);
}
class C extends A {
    function __construct() {
    }
}
// v PHP < 5.4 prošlo, nově vyvolá
// Fatal error: Declaration of C::__construct() must be compatible with that of A::__construct()

Na konstruktory se toto omezení nevztahovalo, což nová verze opravuje (a tím zároveň sjednocuje chování s deklarováním konstruktoru pomocí rozhraní). Tento obrat se přitom občas používal, do dokumentace první alpha verze se ale popis této změny bohužel nedostal.

Informace o průběhu uploadu souborů

Už delší dobu se dají informace o průběhu nahrávání souborů od uživatele zobrazovat pomocí extenze APC. Nově to jde i jen pomocí session proměnných. Vzniklo k tomu několik konfiguračních direktiv začínajících na session.upload_progress., pomocí kterých se dá chování ovlivnit.

Pokud je sledování průběhu nahrávání povoleno, tak už stačí jen metodou POST poslat pole s názvem ini_get("session.upload_progress.name"). To způsobí vytvoření proměnné $_SESSION[ini_get("session.upload_progress.prefix") . $_POST[ini_get("session.upload_progress.name")]], která bude obsahovat pole se všemi dostupnými informacemi. Detailně to rozebírá příklad.

Změny v extenzích

V extenzi JSON, která je v poslední době velmi populární, je změn více:

Změny příkazové řádky

  • Přibyla volba --rz poskytující informace o Zend extenzích (obdoba třídy  ReflectionZendExtension).
  • Dále vznikly konfigurační direktivy cli.pagercli.prompt.
  • interaktivním režimu by také mělo fungovat nastavování konfiguračních direktiv pomocí #inisetting=value, platí to ale jen při práci přes Readline.

Další novinky

Kromě těchto změn, které jsou důležité při vytváření aplikací, došlo také k řadě vylepšení ve výkonnosti a paměťové náročnosti PHP. V méně používaných extenzích došlo k několika dalším změnám, které tento článek nepopisuje.

Co mi ještě chybí

Když už lze volat f()[], tak bych také ocenil obrat (new C)->f(), který by se hodil u fluent interface. Nemožnost pracovat s výsledkem operátoru new se dá různými způsoby obejít, je to ale značně krkolomné:

// první možnost
function identity($x) {
    return $x;
}
identity(new C)->f();

// druhá možnost
class C {
    static function create() {
        return new self;
    }
}
C::create()->f();

Této vlastnosti bychom se v PHP 5.4 měli ještě dočkat.

Občas by se mi také hodilo deklarovat návratový typ metod. Užitečné by to bylo hlavně u dědičnosti, kdy by se dalo odvozeným třídám přikázat, aby vracely stejný typ objektu. Této změny se podle mě zatím nedočkáme.

Závěr

Vydaná alpha na mě působí celkem vyzrálým dojmem. Pár chyb se sice již objevilo, ale věřím, že nebudou nijak závažné a další vývojová verze vyjde poměrně brzy. Změny na mě také působí poměrně uceleným dojmem, takže si myslím, že příliš dalších novinek se v PHP 5.4.0 už neobjeví.

Autor pracuje jako Software Engineer v týmu Gmail Security. V minulosti se zabýval především PHP, o kterém napsal knihu a podílel se na oficiální dokumentaci. Je autorem nástroje pro správu databáze Adminer. Poznámky si zapisuje na weblog PHP triky.

Věděli jste, že nám můžete zasílat zprávičky? (Jen pro přihlášené.)

Komentáře: 95

Přehled komentářů

lol safe mode
rooobertek Re: safe mode
hugo Re: safe mode
Jakub Vrána Re: safe mode
Hugo Re: safe mode
Jakub Vrána Re: safe mode
Leoš Re: safe mode
maryo Re: safe mode
Jakub Vrána Re: safe mode
HosipLan Re: PHP 5.4 přináší změny a nové jazykové konstrukce
Andrew Re: PHP 5.4 přináší změny a nové jazykové konstrukce
HosipLan Re: PHP 5.4 přináší změny a nové jazykové konstrukce
Jakub Vrána Re: PHP 5.4 přináší změny a nové jazykové konstrukce
kukulich Re: PHP 5.4 přináší změny a nové jazykové konstrukce
Jakub Vrána Re: PHP 5.4 přináší změny a nové jazykové konstrukce
notnotorm Re: PHP 5.4 přináší změny a nové jazykové konstrukce
adrive Re: PHP 5.4 přináší změny a nové jazykové konstrukce
Proki $this v closure
Jahudka Argh!
jlx Re: Argh!
blizz Re: Argh!
blizz Re: Argh!
Oldis Re: Argh!
blizz Re: Argh!
František Kučera Re: Argh!
blizz Re: Argh!
mrj Re: Argh!
wdolek Re: Argh!
František Kučera Re: Argh!
Oldis Re: Argh!
blizz Re: Argh!
Oldis Re: Argh!
blizz Re: Argh!
Oldis Re: Argh!
blizz Re: Argh!
Jakub Vrána Re: Argh!
Jahudka Re: Argh!
Jakub Vrána Re: Argh!
Jahudka Re: Argh!
Jakub Vrána Re: Argh!
Jahudka Re: Argh!
Nox Re: Argh!
Jahudka Re: Argh!
pravdokop Re: Argh!
Jakub Vrána Re: Argh!
wdolek Re: Argh!
David Grudl Re: Argh!
Oldis Re: Argh!
Jakub Vrána Re: Argh!
Nox Re: Argh!
wdolek Re: Argh!
anonym Re: Argh!
Jakub Vrána Re: Argh!
anonym Re: Argh!
Jakub Vrána Re: Argh!
anonym Re: Argh!
Jakub Vrána Re: Argh!
anonym Re: Argh!
Jakub Vrána Re: Argh!
wdolek Re: Argh!
Vrtak-CZ Re: Argh!
anonym Re: Argh!
Jakub Vrána Re: Argh!
paranoiq Re: Argh!
biggringo Bude finally
andrewN Re: Bude finally
HosipLan Re: Bude finally
andrewN Re: Bude finally
HosipLan Re: Bude finally
kukulich Re: Bude finally
Hufo Sejfmod
Jakub Vrána Re: Sejfmod
Hugo Re: Sejfmod
maertien Register_globals
Jakub Vrána Re: Register_globals
maertien Re: Register_globals
Nox spokojenost
adrive file upload progress
LM_ Re: file upload progress
Miloslav Hůla Traits a zapouzdření
Jakub Vrána Re: Traits a zapouzdření
Oldis Traits je chaba nahrada vicenasobne dedicnosti
wdolek Re: Traits je chaba nahrada vicenasobne dedicnosti
xxxObiWan Traits, k čemu vlastně?
tiso Re: Traits, k čemu vlastně?
lopata Re: Traits, k čemu vlastně?
tiso Re: Traits, k čemu vlastně?
Jakub Vrána Magic quotes nejspíš zmizí
kukulich Re: Magic quotes nejspíš zmizí
jos traits - syntaxe
expert PHP versus Python
Jakub Vrána Re: PHP versus Python
jos Re: PHP versus Python
Jakub Vrána Re: PHP versus Python
kukulich Další změny
Zdroj: http://www.zdrojak.cz/?p=3513