Mai exact, ce parere aveti despre noile “functionalitati”? Sau daca mai stie si altcineva chestii asemanatoare?
Ce-mi place (și ce voi folosi):
- Că poți declara ce ar trebui să întoarcă o metodă:
function foobar(): int { return 1; }
; - Condițiile ternare simplificate:
$foo = $bar ?? 'default value'
(în loc de$foo = isset($bar) ? $bar : 'default value
; - un
use
grupat: în loc deuse foo\Foo; use foo\Bar; use foo\Baz
poți folosiuse foo\{Foo, Bar, Baz}
Ce mi se pare o idee… mai puțin bună:
- clasele anonime;
nici traits nu sunt f populare, desi au aparut de ceva vreme in peisaj, si sunt mai bune ca abstract classes pe anumite situatii; eu sper sa nu fie folosite clasele anonime de programatorii mai putin experimentati pt ca ar putea obfusca functionalitate importanta si ar face-o greu de mentinut
Singura utilitate pe care o vad pentru clasele alea anonime este atunci cand scrii testele si ai nevoie de mock-up objects rapid (si nu ai nevoie sa le reutilizezi, ca sa ai de ce sa le dai un nume).
In rest, inca nu am trecut la PHP 7 in productie. Astept sa se mai aseze putin praful, mai multe detalii aici: https://bugs.launchpad.net/ubuntu/+source/php5/+bug/1522422
TL;DR PHP7 in urmatoare versiune LTS de Ubuntu:
I could afford to run PPAs with multiple PHP versions, because I have the liberty of saying: “upstream bug, bummer” and do nothing about it if I don’t have time or motivation to fix it. That’s the freedom Ubuntu folks don’t have, so I am at their side. Just look at the PHP bug lists (both in Debian and Ubuntu).
[quote=“iamntz, post:2, topic:2751”]Ce mi se pare o idee… mai puțin bună:
clasele anonime;[/quote]
Eu aia aștept cel mai mult! Pentru creare de test doubles e o gură de aer proaspăt man. Hai să îți dau un exemplu:
Să zicem că testez o clasă Money(int $amount, Currency $currency)
, care reprezintă o sumă de bani, într-o anumită monedă. Și vreau să testez metoda convert
, care are următoarea semnătură:
public function convert(Currency $to_currency, DateTime $on_date): Money
Intern, clasa Money
se folosește de serviciul de exchange pentru a prelua rata de conversie în data respectivă, și a o aplica sumei. Serviciul de exchange are următoarea interfață:
interface ExchangeRateProvider
{
public function getRate(Currency $from, Currency $to, DateTime $date): float
}
Acum, pentru că eu testez clasa Money
, nu am nevoie de un serviciu de exchange real (care se uită în baza de date, face call-uri în API-uri, whatever), ci de un stub. Iar ca să nu stau să definesc o clasă întreagă (fișier separat, nume unic, etc.) pentru un singur test, îmi este mult mai ușor să îi dau clasei Money
un stub construit pe loc, direct în test:
Money::setExchangeRateProvider(
new class() implements ExchangeRateProvider {
public function getRate(Currency $from, Currency $to, DateTime $date) {
return 5;
}
}
);
Iar apoi pot testa că, atunci când apelez convert
, rezultatul este într-adevăr amount-ul respectiv, înmulțit cu rata de conversie 5
.
Edit: La fel de ușor pot implementa un spy, care doar să îmi confirme că Money
a apelat serviciul de exchange când apelez convert
, fără să mă intereseze rezultatul conversiei:
$provider = new class() implements ExchangeRateProvider {
public $get_rate_called = false;
public function getRate(Currency $from, Currency $to, DateTime $date) {
$this->get_rate_called = true;
return 0;
}
};
Money::setExchangeRateProvider($provider);
// Apelat $money->convert([...])
$this->assertTrue($provider->get_rate_called);
Sunt convins că există utilizări legitime, dar cât crezi că va dura până se va abuza de ele în producție, nu în teste?
Crezi că mult? Gândește-te doar la callback hell din JS
Tinand cont ca “all the cool kids” invata Node as zice ca riscul ca aceasta situatie sa fie des intalnita e ceva mai mic. Am avut o temere similara legata de Traits si modul in care putea fi “abuzate”.
Pe de alta parte am gasit perle monumentale si PHP 5.3, asa ca ma astept la orice.
Continuand intrebarea, folosind 3v4l.org (nu am HHVM instalat) si folosind o parte din exemplul #4 din manual
<?php
class Foo
{
static function bar()
{
echo "bar\n";
}
function baz()
{
echo "baz\n";
}
function __construct()
{
echo "construct\n";
}
}
$func = array("Foo","__construct");
$func();
$func = array(new Foo,"__construct");
$func();
$func = "Foo::__construct";
$func();
In hhvm-3.11.0 - 3.12.0 se pare ca merg toate call-urile, sunt 4 calluri la new Foo se apeleaza si constructorul.
In PHP 7 primul call si ultimul nu merg “Fatal error: Uncaught Error: Non-static method Foo::__construct() cannot be called statically”.
Ăsta nu este exemplul #4 din manual, ci o versiune modificată. Exemplul #4 ar fi mers în PHP 7.
__construct()
nu este o metodă statică a clasei Foo
și este normal să nu poată fi apelată într-un context static. HHVM este altă mâncare de pește și nu poate fi considerat un punct de referință pentru PHP. Ori este un bug în HHVM care a permis rularea codului tău, ori metoda __construct()
este tratată diferit în HHVM decât în PHP.
Am spus “folosind o parte din exemplul #4”.
Exemplul respectiv oricum e gresit in manual, se foloseste $f la declalare si $func pentru apelare.
Am vrut sa subliniez posibilitatea ca un cod care merge pe HHVM sa nu mearga pe PHP7, si poate exista exemple si invers.
Poate am fost putin vag la inceput, sunt mai putin interesat de ce pot gasi in change log-uri, sunt mai mult interesat de exemple de cod care poate duce la buguri sau situatii ciudate.
Nu am gasit in manual exemplul cu string intre ghilimele si paranteze dupa si sa apeleze functia din string daca exista, probabil vor completa la sectiunea “variable functions”…
Nici nu ar trebui să încerci să rulezi cod Hack (limbajul HHVM) în interpretorul PHP. Doar reciproca este valabilă.
Hack este un un superset al PHP-ului. Codul PHP este cod valid Hack, dar codul Hack nu este neapărat valid PHP. Atâta timp cât te rezumi la cod valid PHP, acesta va rula identic în ambele interpretoare. Dacă încerci să folosești elemente specifice Hack/HHVM, atunci poți să-ți iei adio de la compatibilitatea cu PHP-ul.