PHP Utvikling. Symfony-konsollkomponent - tips og triks
Denne artikkelen ble opprettet med sikte på å vise deg de mest nyttige og nyttige tipsene og triksene om Symfony Console Development.
Den nye versjonen av PHP er rett rundt hjørnet. Hvilke nye implementeringer bør du vite om? Sjekk denne artikkelen for å finne ut av det!
PHP 8.2 er i ferd med å bli utgitt. Kanskje blir det den versjonen som gjør at en oppgradering til PHP 8 virker tiltalende for alle. La oss snakke om hva utviklere kan se frem til med PHP 8.2 og forberede seg på den nyeste versjonen. Men først, la oss raskt gå gjennom alle PHP-versjonene og endringene opp gjennom årene.
<?php
class Bruker {
public int $id;
public string $name;
}
?>
<?php
$factor = 10;
$nums = array_map(fn($n) => $n * $factor, [1, 2, 3, 4]);
// $nums = array(10, 20, 30, 40);
?>
<?php
klasse A {}
klasse B utvider A {}
class Produsent {
public function method(): A {}
}
class ChildProducer utvides til Producer {
public function method(): B {}
}
?>
<?php
$array['key'] ??= computeDefault();
// er omtrent ekvivalent med
if (!isset($array['key'])) {
$array['key'] = computeDefault();
}
?>
<?php
$parts = ['eple', 'pære'];
$fruits = ['banan', 'appelsin', ...$parts, 'vannmelon'];
// ['banana', 'orange', 'apple', 'pear', 'watermelon'];
?>
<?php
// Returnerer en matrise som inneholder all nødvendig tilstand for objektet.
public function __serialize(): array;
// Gjenoppretter objekttilstanden fra den gitte dataarrayen.
public function __unserialize(array $data): void;
?>
PHP 8.0 ble lansert i november 2020, og ga oss de beste funksjonene hittil, blant annet
htmlspecialchars($string, double_encode: false);
klasse PostsController
{
#[Route("/api/posts/{id}", methods: ["GET"])]
public function get($id) { /* ... */ }
}
class Point {
offentlig funksjon __construct(
public float $x = 0.0,
public float $y = 0.0,
public float $z = 0.0,
) {}
}
klasse Number {
offentlig funksjon __construct(
private int|float $number
) {}
}
new Number('NaN'); // TypeError
echo match (8.0) {
'8.0' => "Å nei!",
8.0 => "Dette er hva jeg forventet",
};
//> Dette er hva jeg forventet
$country = $session?->user?->getAddress()?->country;
enum Status
{
case Utkast;
case Publisert
case Arkivert;
}
function acceptStatus(Status $status) {...}
klasse BloggData
{
public readonly Status $status;
public function __construct(Status $status)
{
$this->status = $status;
}
}
$foo = $this->foo(...);
$fn = strlen(...);
klasse Service
{
private Logger $logger;
offentlig funksjon __construct(
Logger $logger = new NullLogger(),
) {
$this->logger = $logger;
}
}
function count_and_iterate(Iterator&Countable $value) {
foreach ($value as $val) {
echo $val;
}
count($value);
}
$response = $httpClient->request('https://example.com/');
print json_decode($response->getBody()->buffer())['code'];
PHP 8.2 introduserer ytterligere endringer som skal gjøre utviklerens liv enklere og optimalisere arbeidet hans enda mer. Nedenfor er listen over nye funksjoner.
En av de største forbedringene i den nye versjonen av PHP er muligheten til å opprette en skrivebeskyttet
klasse. En klasse som er beskrevet med denne funksjonen, vil automatisk forplante den til sine variabler. DTO-klasser vil nå se pene og rene ut!
readonly-klassen InvoiceDTO
{
offentlig funksjon __construct(
public UUID $uuid,
public Utsteder 1TP60Udsteder,
public DateTime $issuedAt,
) {}
}
Den andre store endringen er at dynamiske variabler i klasser ikke lenger skal brukes. Følgende implementering vil kaste en deprecation i PHP 8.2 og ErrorException
i fremtidig versjon av PHP.
klasse MyUser
{
public string $name;
}
(...)
$myUser->name = 'Navn'; // OK
$myUser->surname = 'Surname'; // deprecated / errorexception
Det er verdt å nevne at klasser som implementerer __get
og __set
metoder og klasser som arver direkte fra stdClass
kan fortsatt implementere magiske metoder uten hindringer.
Her henviser jeg også til en interessant tråd på GitHubhvor utviklerne av PHP-CS diskuterer denne endringen og behovet for å modifisere det populære verktøyet for den nye versjonen av språket.
Sist, men ikke minst, kan du deaktivere denne atferden via Annotation.
#[AllowDynamicProperties]
klasse MyUser
{
public string $name;
}
$myUser->surname = 'Etternavn'; // OK
null
, ekte
, og falsk
Frem til nå har funksjoner som alltid har returnert en ekte
eller falsk
verdien måtte beskrives med en bool
type.
function alwaysTrue(): bool { return true; }
Fra nå av kan vi bruke ekte
og falsk
som enkle typer i returverdiene til funksjoner.
function alwaysTrue(): true { return true; }
(DNF) er en standard måte å organisere boolske uttrykk på. Nærmere bestemt betyr det å strukturere et boolsk uttrykk i en OR-sekvens av AND-er. Når DNF brukes på typedeklarasjoner, gir det en standard måte å skrive kombinerte Union- og Intersection-typer på som parseren kan håndtere.
Det er en stor endring, ettersom vi nå for eksempel kan ha nullbare skjæringstyper:
function getFullName((HasName&HasSurname)|null $user) { ... }
Jeg er ikke en stor tilhenger av å bruke Traits, og en slik endring er rent kosmetisk for meg, spesielt siden den ikke lar deg bruke Trait-verdier uten å initialisere objektet.
trait Foo {
public const FLAG_1 = 1;
beskyttet const FLAG_2 = 2;
private const FLAG_3 = 2;
public function doFoo(int $flags): void {
if ($flags & self::FLAG_1) {
echo 'Fikk flagg 1';
}
if ($flags & self::FLAG_2) {
echo 'Fikk flagg 2';
}
if ($flags & self::FLAG_3) {
echo 'Fikk flagg 3';
}
}
}
En av de viktigste endringene jeg ser frem til. I den nyeste versjonen av PHP vil vi kunne merke variabler som SensitiveParameterValue
. Hvorfor skulle vi det?
PHPs stakkspor i unntak er svært nyttige for feilsøking, men de lar deg forhåndsvise parameterverdier. La oss for eksempel forestille oss PDO kode brukes til å koble til en database. Feilsøkingssporet vil se ut som følger:
PDOException: SQLSTATE[HY000] [2002] Ingen slik fil eller katalog i /var/www/html/test.php:3
Stack trace:
#0 /var/www/html/test.php(3): PDO->__construct('mysql:host=loca...', 'root', 'password')
#1 {main}
Etter bruk av Annotasjon #[SensitiveParameter]
vil ikke lenger vise verdien til variabelen.
funksjon test(
$foo,
#[SensitiveParameter] $bar,
$baz
) {
kast ny Exception('Feil');
}
test('foo', 'bar', 'baz');
/*
Fatal feil: Uncaught Exception: Feil i test.php:8
Stack trace:
#0 test.php(11): test('foo', Object(SensitiveParameterValue), 'baz')
#1 {main}
kastet i test.php på linje 8
*/
Som forfatteren sier
Den primære motivasjonen for denne endringen er å gjøre det mulig å hente navn- og verdiegenskaper på steder der enum-objekter ikke er tillatt, for eksempel matrisenøkler. Vi kan jobbe med matriser slik at de kan utvides til å tillate enumer eller alle objekter som nøkler, men det er enklere å tillate henting av egenskaper til enumer.
enum A: string {
case B = 'B';
const C = [self::B->verdi => self::B];
}
Tidligere fungerte statiske metoder slik:
DateTime::createFromImmutable(): DateTime
DateTimeImmutable::createFromMutable(): DateTimeImmutable
I PHP 8.2 ...skal det endres til:
DateTime::createFromImmutable(): static
DateTimeImmutable::createFromMutable(): statisk
Dette er en endring som vil være ødeleggende for bibliotekskapere og/eller alle tilpassede implementasjoner av DateTime.
Dette var to funksjoner som ikke tjente sitt formål, ettersom de bare konverterte mellom ISO-8859-1
og UTF-8
. PHP Manual foreslår at du bruker mb_konverter_koding
i stedet.
Locale-sensitivitet beskrives best av forfatteren av RFC:
Før PHP 8.0 ble PHPs språkinnstilling angitt fra miljøet. Når en bruker installerer Linux, spør den hvilket språk du vil at det skal være på. Det er ikke sikkert at brukeren helt forstår konsekvensene av dette valget. Ikke bare angir det brukergrensesnittets språk for innebygde kommandoer, men det endrer også hvordan strenghåndteringen i C-biblioteket fungerer. For eksempel vil en bruker som velger "tyrkisk" når han eller hun installerer Linux, oppleve at programmer som kaller toupper('i'), får den prikkete store I-en (U+0130, "İ").
I en tid med standardiserte tekstbaserte protokoller er naturlig språk en minoritetsapplikasjon for konvertering av store og små bokstaver. Men selv om brukeren ønsket konvertering av store og små bokstaver i naturlig språk, ville han eller hun neppe lykkes med strtolower(). Dette skyldes at den behandler strengen én byte om gangen, og sender hver byte til C-bibliotekets tolower(). Hvis inndataene er UTF-8, som er det desidert mest populære moderne valget, vil strtolower() mangle strengen, og typisk produsere ugyldig UTF-8 som utdata.
PHP 8.0 sluttet å respektere locale-miljøvariablene. Så locale er alltid "C" med mindre brukeren eksplisitt kaller setlocale(). Dette betyr at hoveddelen av den bakoverkompatible endringen allerede er bak oss. Alle programmer som er avhengige av systemets locale for å konvertere store og små bokstaver i eldre 8-bits tegnsett, ville ha blitt ødelagt av PHP 8.0.
Det betyr at alle funksjonene nedenfor vil konvertere ASCII-kasus fra PHP.8.2:strtolower
, strtoupper
, stristr
, stripoer
, strripos
, lcfirst
, ucfirst
, ucwords
, str_ireplace
Vi har mange måter å legge inn variabler i strenger på i PHP:
- Direkte innbygging av variabler ("$foo")
- Parenteser utenfor variabelen ("{$foo}")
- Parenteser etter dollartegnet ("${foo}")
- Variabelvariabler ("${expr}", tilsvarer (streng) ${expr})
For å unngå forvirring og misbruk vil disse ikke fungere lenger:
"Hallo ${verden}";
Foreldet: Bruk av ${} i strenger er foreldet
"Hallo ${(verden)}";
Utdatert: Bruk av ${} (variable variabler) i strenger er foreldet
Dette er ikke alle endringene som PHP 8.2 vil tilby oss. Dessverre fikk vi fortsatt ikke støtte for generiske typer, ifølge Nikita ville de monomorfiserte generiske typene gi for mye ytelsesoverhead, og reifiserte generiske typer krever mange endringer på tvers av hele kodebasen. Det som imidlertid er merkbart, er disiplinen og visjonen til produkt. Endringene som er innført i de etterfølgende versjonene av språket blir stadig tydeligere, og de som er interessert vil legge merke til at PHP beveger seg i riktig retning både når det gjelder forenkling av syntaks og støtte for nyheter. Jeg forventer at vi allerede neste år vil se kallbar
som en gyldig type.