PHP Kūrimas. "Symfony" konsolės komponentas - Patarimai ir gudrybės
Šis straipsnis buvo sukurtas siekiant parodyti jums naudingiausius ir naudingiausius patarimus ir gudrybes apie "Symfony" konsolės kūrimą.
Nauja PHP versija jau visai netoli. Apie kokias naujas įgyvendinimo naujoves turėtumėte žinoti? Peržiūrėkite šį straipsnį ir sužinokite!
PHP 8.2 netrukus bus išleistas. Galbūt tai bus versija, dėl kurios atnaujinimas į PHP 8 atrodys patrauklus visiems. Pakalbėkime apie tai, ko kūrėjai gali tikėtis su PHP 8.2 ir pasiruošti naujausiai jo versijai. Tačiau pirmiausia trumpai apžvelkime visas PHP versijas ir pokyčius per daugelį metų.
<?php
klasė User {
public int $id;
public string $name;
}
?>
<?php
$faktorius = 10;
$nums = array_map(fn($n) => $n * $faktorius, [1, 2, 3, 4]);
// $nums = array(10, 20, 30, 40);
?>
<?php
klasė A {}
klasė B išplečia A {}
klasė Producer {
public function method(): A {}
}
klasė ChildProducer plečia Producer {
public function method(): B {}
}
?>
<?php
$array['key'] ??= computeDefault();
// apytiksliai atitinka
if (!isset($array['key'])) {
$array['key'] = computeDefault();
}
?>
<?php
$dalys = ['obuolys', 'kriaušė'];
$fruits = ['bananas', 'apelsinas', ...$parts, 'arbūzas'];
// ['bananas', 'apelsinas', 'obuolys', 'kriaušė', 'arbūzas'];
?>
<?php
// Grąžina masyvą, kuriame yra visos būtinos objekto būsenos.
public function __serialize(): array;
// Atkuria objekto būseną iš pateikto duomenys masyvas.
public function __unserialize(array $data): void;
?>
2020 m. lapkričio mėn. išleista "PHP 8.0" atnešė mus geriausiomis funkcijomis, įskaitant:
htmlspecialchars($string, double_encode: false);
klasė PostsController
{
#[Route("/api/posts/{id}", methods: ["GET"])]
public function get($id) { /* ... */ }
}
klasė Point {
viešoji funkcija __construct(
public float $x = 0.0,
public float $y = 0.0,
public float $z = 0.0,
) {}
}
klasė Number {
viešoji funkcija __construct(
private int|float $number
) {}
}
new Number('NaN'); // TypeError
echo match (8.0) {
'8.0' => "O ne!",
8.0 => "To ir tikėjausi",
};
//> To ir tikėjausi
$country = $session?->user?->getAddress()?->country;
enum Status
{
case Draft;
case Publikuota;
case Archived;
}
funkcija acceptStatus(Status $status) {...}
klasė BlogData
{
public readonly Status $status;
viešoji funkcija __construct(Status $status)
{
$this->status = $status;
}
}
$foo = $this->foo(...);
$fn = strlen(...);
klasė Paslauga
{
private Logger $logger;
viešoji funkcija __construct(
Logger $logger = new NullLogger(),
) {
$this->logger = $logger;
}
}
funkcija count_and_iterate(Iterator&Countable $value) {
foreach ($value as $val) {
echo $val;
}
count($value);
}
$response = $httpClient->request('https://example.com/');
spausdinti json_decode($response->getBody()->buffer())['code'];
PHP 8.2 pristatomi papildomi pakeitimai, kuriais siekiama palengvinti kūrėjo gyvenimą ir dar labiau optimizuoti jo darbą. Toliau pateikiamas naujų funkcijų sąrašas.
Vienas didžiausių naujosios PHP versijos patobulinimų - galimybė tiesiogiai sukurti tik skaitymui klasė. Klasė, aprašyta su šia funkcija, automatiškai ją paskleis savo kintamiesiems. DTO klasės dabar atrodys tvarkingai ir švariai!
readonly klasė InvoiceDTO
{
public function __construct(
public UUID $uuid,
public Issuer $issuer,
public DateTime $issuedAt,
) {}
}
Antrasis didžiulis pokytis - klasėse atsisakyta dinaminių kintamųjų. Toliau pateikiamas įgyvendinimas bus išmesti deprecation PHP 8.2 ir ErrorException būsimoje PHP versijoje.
klasė MyUser
{
public string $name;
}
(...)
$myUser->name = 'Vardas'; // Gerai
$myUser->surname = 'Pavardė'; // deprecated / errorexception
Verta paminėti, kad klasės, įgyvendinančios __get ir __set metodus ir klases, tiesiogiai paveldimas iš stdClass vis dar gali be jokių kliūčių įgyvendinti magiškus metodus.
Čia taip pat pateikiu nuorodą į įdomi gija "GitHub, kuriame PHP-CS kūrėjai aptaria šį pokytį ir būtinybę modifikuoti savo populiarią priemonę, kad ji atitiktų naująją kalbos versiją.
Galiausiai, nors tai ne mažiau svarbu, galite išjungti šią elgseną naudodami anotaciją.
#[AllowDynamicProperties]
klasė MyUser
{
public string $name;
}
$myUser->surname = 'Pavardė'; // OK
null, tiesa, ir klaidingaIki šiol funkcijos, kurios visada grąžindavo tiesa arba klaidinga vertė turėjo būti aprašyta naudojant bool tipas.
funkcija alwaysTrue(): bool { return true; }
Nuo šiol galime naudoti tiesa ir klaidinga kaip paprasti tipai funkcijų grąžinamose reikšmėse.
funkcija alwaysTrue(): true { return true; }
(DNF) yra standartinis loginių išraiškų organizavimo būdas. Konkrečiai, tai reiškia, kad loginė išraiška struktūrizuojama į ORed seriją AND. Taikant šį metodą tipų deklaracijoms, jis leidžia standartiniu būdu užrašyti kombinuotus Union ir Intersection tipus, kuriuos gali apdoroti analizatorius.
Tai didelis pokytis, nes, pavyzdžiui, dabar galime turėti nulinius sankirtos tipus:
funkcija getFullName((HasName&HasSurname)|null $user) { ... }
Nesu didelis "Traits" naudojimo šalininkas, todėl toks pakeitimas man atrodo grynai kosmetinis, ypač todėl, kad jis neleidžia naudoti "Trait" reikšmių neinicializavus objekto.
bruožas Foo {
public const FLAG_1 = 1;
protected const FLAG_2 = 2;
private const FLAG_3 = 2;
public function doFoo(int $flags): void {
if ($flags & self::FLAG_1) {
echo 'Got flag 1';
}
if ($flags & self::FLAG_2) {
echo 'Got flag 2';
}
if ($flags & self::FLAG_3) {
echo 'Got flag 3';
}
}
}
Vienas iš svarbiausių pokyčių, kurių laukiu su nekantrumu. Naujausioje PHP versijoje galėsime žymėti kintamuosius kaip SensitiveParameterValue. Kodėl turėtume?
PHP stek traces išimtyse yra labai naudingos derinant, tačiau jos leidžia peržiūrėti parametrų vertes. Pavyzdžiui, įsivaizduokime, kad PDO kodas naudojamas prisijungti prie duomenų bazės. Derinimo eiga atrodytų taip:
PDOišimtis: Nėra tokio failo ar katalogo /var/www/html/test.php:3
Stack trace:
#0 /var/www/html/test.php(3): PDO->__construct('mysql:host=loca...', 'root', 'password')
#1 {main}
Panaudojus anotaciją #[SensitiveParameter] mūsų kamino ištraukoje nebebus rodoma kintamojo vertė.
funkcija testas(
$foo,
#[SensitiveParameter] $bar,
$baz
) {
mesti naują Išimtis('Klaida');
}
test('foo', 'bar', 'baz');
/*
Fatališka klaida: Neįvykusi išimtis: Klaida test.php:8
Stack trace:
#0 test.php(11): test('foo', Object(SensitiveParameterValue), 'baz')
#1 {main}
išmesta test.php 8 eilutėje
*/
Kaip autorius sako
, Pagrindinis šio pakeitimo motyvas - leisti gauti vardo ir vertės savybes tose vietose, kur enum objektų neleidžiama naudoti, pavyzdžiui, masyvų raktus. Galėtume dirbti su masyvais, kad juos būtų galima išplėsti ir leisti naudoti enumus arba visus objektus kaip raktus, tačiau leisti gauti enumų savybes yra paprasčiau.
enum A: string {
case B = 'B';
const C = [self::B->value => self::B];
}
Anksčiau statiniai metodai veikė taip:
DateTime::createFromImmutable(): DateTime
DateTimeImmutable::createFromMutable(): DateTimeImmutable
Svetainėje PHP 8.2 ji bus pakeista į:
DateTime::createFromImmutable(): statinis
DateTimeImmutable::createFromMutable(): static
Tai yra esminis pokytis bibliotekų kūrėjams ir (arba) visoms pasirinktinėms DateTime realizacijoms.
Tai buvo dvi funkcijos, kurios neatliko savo tikslo, nes jie tik konvertuojami tarp ISO-8859-1 ir UTF-8. PHP Vadovas siūlo naudoti mb_convert_encoding vietoj to.
Vietovės jautrumą geriausiai apibūdina RFC autorius:
Iki PHP 8.0 versijos PHP lokalizacija buvo nustatoma iš aplinkos. Kai naudotojas diegia “Linux”, jis klausia, kokia kalba norite, kad ji būtų. Vartotojas gali nevisiškai suvokti šio sprendimo pasekmes. Jis ne tik nustato vartotojo sąsajos kalbą integruotoms komandoms, bet ir iš esmės pakeičia eilutės tvarkymo C bibliotekoje būdą. Pavyzdžiui, vartotojas, diegdamas ‘Linux’ pasirinkęs “Turkish”, pamatys, kad programos, kviečiančios toupper('i'), gaus taškinę didžiąją raidę I (U+0130, "İ").
Standartizuotų tekstinių protokolų eroje natūralioji kalba yra mažuma bylų konvertavimo programų. Tačiau net jei naudotojas ir norėtų natūralios kalbos raidžių keitimo, vargu ar jam tai pavyktų padaryti naudojant strtolower(). Taip yra todėl, kad ji apdoroja eilutę po vieną baitą, kiekvieną baitą pateikdama C bibliotekos programai tolower(). Jei įvestis yra UTF-8 (tai bene populiariausias šiuolaikinis pasirinkimas), strtolower() iškraipys eilutę ir paprastai išvesties rezultatas bus negaliojantis UTF-8.
PHP 8.0 nustojo atsižvelgti į vietovės aplinkos kintamuosius. Taigi lokalizacija visada yra “C”, nebent naudotojas aiškiai iškviečia setlocale(). Tai reiškia, kad didžioji dalis atgalinio nesuderinamumo pakeitimų jau už nugaros. Visos programos, priklausančios nuo sistemos locale, kai reikia konvertuoti senųjų 8 bitų simbolių rinkinių bylas, PHP 8.0 būtų sugadintos.
Tai reiškia, kad visos toliau nurodytos funkcijos atliks ASCII raidžių konvertavimą iš PHP.8.2:strtolower, strtoupper, stristr, stripos, strripos, lcfirst, ucfirst, ucwords, str_ireplace
PHP turime daugybę būdų, kaip įterpti kintamuosius į eilutes:
- Tiesioginis kintamųjų įterpimas (“$foo”)
- Skliausteliai už kintamojo ribų (“{$foo}”)
- Skliausteliai po dolerio ženklo (“${foo}”)
- Kintamieji kintamieji (“${expr}”, lygiavertis (eilutė) ${expr})
Kad būtų išvengta painiavos ir netinkamo naudojimo, šios nuorodos nebeveiks:
"Hello ${world}";
Pasenęs: ${} naudojimas eilutėse yra pasenęs
"Hello ${(world)}";
Atmesta: ${} (kintamieji kintamieji) eilutėse nebetaikoma
Tai ne visi pakeitimai, kurie PHP 8.2 pasiūlys mums. Deja, vis dar negavome bendrinių tipų palaikymo, nes, kaip sakė Nikita, monomorfizuoti bendriniai tipai pridėtų per daug našumo pridėtinių išlaidų, o reifikuoti bendriniai tipai reikalauja daug pakeitimų visoje programinėje įrangoje. Tačiau pastebima disciplina ir vizija produktas. Vėlesnėse kalbos versijose padaryti pakeitimai tampa vis aiškesni, o besidomintys pastebės, kad PHP eina teisinga linkme tiek sintaksės supaprastinimo, tiek naujovių palaikymo srityje. Tikiuosi, kad jau kitais metais pamatysime kviečiamas kaip galiojantį tipą.
