PHP Development. Komponent konsoli Symfony - porady i wskazówki
Ten artykuł został stworzony w celu pokazania najbardziej przydatnych i przydatnych wskazówek i sztuczek dotyczących rozwoju konsoli Symfony.
Nowa wersja PHP jest tuż za rogiem. Jakie są nowe implementacje, o których powinieneś wiedzieć? Sprawdź ten artykuł, aby się dowiedzieć!
PHP 8.2 wkrótce zostanie wydana. Być może będzie to wersja, która sprawi, że aktualizacja do PHP 8 wyda się atrakcyjna dla wszystkich. Porozmawiajmy o tym, czego deweloperzy mogą oczekiwać dzięki PHP 8.2 i przygotować się na jego najnowszą wersję. Ale najpierw szybko przejrzyjmy wszystkie wersje PHP i zmiany na przestrzeni lat.
<?php
class Użytkownik {
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
class A {}
class B extends A {}
class Producer {
public function method(): A {}
}
class ChildProducer extends Producer {
public function method(): B {}
}
?>
<?php
$array['key'] ??= computeDefault();
// jest z grubsza równoważne
if (!isset($array['key'])) {
$array['key'] = computeDefault();
}
?>
<?php
$parts = ['apple', 'pear'];
$fruits = ['banan', 'pomarańcza', ...$parts, 'arbuz'];
// ['banan', 'pomarańcza', 'jabłko', 'gruszka', 'arbuz'];
?>
<?php
// Zwraca tablicę zawierającą wszystkie niezbędne stany obiektu.
public function __serialize(): array;
// Przywraca stan obiektu z podanej tablicy danych.
public function __unserialize(array $data): void;
?>
Wydany w listopadzie 2020 roku PHP 8.0 przyniósł nam najlepsze jak dotąd funkcje, które obejmują:
htmlspecialchars($string, double_encode: false);
class PostsController
{
#[Route("/api/posts/{id}", methods: ["GET"])]
public function get($id) { /* ... */ }
}
class Punkt {
public function __construct(
public float $x = 0.0,
public float $y = 0.0,
public float $z = 0.0,
) {}
}
class Number {
public function __construct(
private int|float $number
) {}
}
new Number('NaN'); // TypeError
echo match (8.0) {
'8.0' => "O nie!",
8.0 => "Tego się spodziewałem",
};
//> Tego się spodziewałem
$country = $session?->user?->getAddress()?->country;
enum Status
{
case Draft;
case Opublikowano;
przypadek Zarchiwizowany;
}
function acceptStatus(Status $status) {...}
class BlogData
{
public readonly Status $status;
public function __construct(Status $status)
{
$this->status = $status;
}
}
$foo = $this->foo(...);
$fn = strlen(...);
klasa Serwis
{
private Logger $logger;
public function __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 wprowadza kolejne zmiany mające na celu ułatwienie życia deweloperom i jeszcze większą optymalizację ich pracy. Poniżej znajduje się lista nowości.
Jednym z największych usprawnień w nowej wersji PHP jest możliwość bezpośredniego utworzenia tylko do odczytu
class. Klasa opisana za pomocą tej funkcji będzie automatycznie propagować ją dla swoich zmiennych. Klasy DTO będą teraz wyglądać schludnie i czysto!
readonly class InvoiceDTO
{
public function __construct(
public UUID $uuid,
public Issuer $issuer,
public DateTime $issuedAt,
) {}
}
Drugą ogromną zmianą jest wycofanie zmiennych dynamicznych w klasach. Poniższa implementacja rzuci deprecation w PHP 8.2 i Wyjątek ErrorException
w przyszłej wersji PHP.
class MyUser
{
public string $name;
}
(...)
$myUser->name = 'Name'; // OK
$myUser->surname = 'Surname'; // deprecated / errorexception
Warto wspomnieć, że klasy implementujące __get
i __set
metody i klasy bezpośrednio dziedziczące z stdClass
nadal może bez przeszkód wdrażać magiczne metody.
Tutaj również odsyłam do interesujący wątek na GitHub, gdzie programiści PHP-CS omawiają tę zmianę i potrzebę modyfikacji ich popularnego narzędzia dla nowej wersji języka.
Wreszcie, można wyłączyć to zachowanie za pomocą adnotacji.
#[AllowDynamicProperties]
class MyUser
{
public string $name;
}
$myUser->surname = 'Surname'; // OK
null
, prawda
oraz fałszywy
Do tej pory funkcje, które zawsze zwracały wartość prawda
lub fałszywy
wartość musiała być opisana za pomocą bool
typ.
function alwaysTrue(): bool { return true; }
Od teraz możemy używać prawda
i fałszywy
jako typy proste w zwracanych wartościach funkcji.
function alwaysTrue(): true { return true; }
(DNF) jest standardowym sposobem organizowania wyrażeń logicznych. W szczególności oznacza to strukturyzację wyrażenia logicznego w serię ORed AND. W przypadku zastosowania do deklaracji typów, pozwala to na standardowy sposób pisania połączonych typów Union i Intersection, które mogą być obsługiwane przez parser.
To duża zmiana, ponieważ teraz możemy mieć na przykład typy przecięć o wartości null:
function getFullName((HasName&HasSurname)|null $user) { ... }
Nie jestem wielkim zwolennikiem korzystania z cech i taka zmiana jest dla mnie czysto kosmetyczna, zwłaszcza że nie pozwala na używanie wartości cech bez inicjalizacji obiektu.
cecha 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 'Otrzymałem flagę 1';
}
if ($flags & self::FLAG_2) {
echo 'Mamy flagę 2';
}
if ($flags & self::FLAG_3) {
echo 'Mamy flagę 3';
}
}
}
Jedna z najważniejszych zmian, na którą czekam z niecierpliwością. W najnowszej wersji PHP będziemy mogli oznaczać zmienne jako SensitiveParameterValue
. Dlaczego powinniśmy?
Ślady stosu w wyjątkach PHP są bardzo przydatne do debugowania, jednak pozwalają na podgląd wartości parametrów. Dla przykładu, wyobraźmy sobie PDO kod używany do łączenia się z bazą danych. Ślad debugowania wyglądałby następująco:
PDOException: SQLSTATE[HY000] [2002] Brak takiego pliku lub katalogu w /var/www/html/test.php:3
Ślad stosu:
#0 /var/www/html/test.php(3): PDO->__construct('mysql:host=loca...', 'root', 'password')
#1 {main}
Po użyciu adnotacji #[SensitiveParameter]
nasz ślad stosu nie będzie już pokazywał wartości zmiennej.
function test(
$foo,
#[SensitiveParameter] $bar,
$baz
) {
throw new Exception('Error');
}
test('foo', 'bar', 'baz');
/*
Błąd krytyczny: Niewykryty wyjątek: Błąd w test.php:8
Ślad stosu:
#0 test.php(11): test('foo', Object(SensitiveParameterValue), 'baz')
#1 {main}
rzucony w test.php w linii 8
*/
Jak autor mówi
Główną motywacją dla tej zmiany jest umożliwienie pobierania nazwy i wartości właściwości w miejscach, w których obiekty wyliczeniowe nie są dozwolone, takich jak klucze tablic. Moglibyśmy popracować nad tablicami, aby można je było rozszerzyć, aby umożliwić wyliczenia lub wszystkie obiekty jako klucze, ale umożliwienie pobierania właściwości wyliczeń jest prostsze.
enum A: string {
case B = 'B';
const C = [self::B->value => self::B];
}
Wcześniej metody statyczne działały w ten sposób:
DateTime::createFromImmutable(): DateTime
DateTimeImmutable::createFromMutable(): DateTimeImmutable
W PHP 8.2 zostanie zmieniony na:
DateTime::createFromImmutable(): static
DateTimeImmutable::createFromMutable(): statyczny
Jest to przełomowa zmiana dla twórców bibliotek i/lub wszystkich niestandardowych implementacji DateTime.
Były to dwie funkcje, które nie spełniały swojego zadania, ponieważ konwertowały tylko między ISO-8859-1
i UTF-8
. Instrukcja PHP sugeruje użycie mb_convert_encoding
zamiast tego.
Wrażliwość na ustawienia regionalne jest najlepiej opisana przez autora RFC:
Przed PHP 8.0, locale PHP były ustawiane z poziomu środowiska. Gdy użytkownik instaluje Linuksa, system pyta, w jakim języku ma być zainstalowany. Użytkownik może nie zdawać sobie sprawy z konsekwencji tej decyzji. Nie tylko ustawia język interfejsu użytkownika dla wbudowanych poleceń, ale także zmienia sposób obsługi ciągów znaków w bibliotece C. Na przykład, użytkownik wybierający język "turecki" podczas instalacji Linuksa odkryłby, że aplikacje wywołujące toupper('i') otrzymałyby kropkowaną wielką literę I (U+0130, "İ").
W erze ustandaryzowanych protokołów tekstowych, język naturalny jest mniejszościowym zastosowaniem konwersji wielkości liter. Ale nawet gdyby użytkownik chciał konwersji wielkości liter w języku naturalnym, raczej nie osiągnąłby sukcesu za pomocą funkcji strtolower(). Dzieje się tak dlatego, że przetwarza ona ciąg znaków po jednym bajcie na raz, przekazując każdy bajt do funkcji tolower() biblioteki C. Jeśli wejściem jest UTF-8, zdecydowanie najpopularniejszy współczesny wybór, strtolower() zmanipuluje ciąg, zazwyczaj dając na wyjściu nieprawidłowy UTF-8.
PHP 8.0 przestał respektować zmienne środowiskowe locale. Tak więc locale jest zawsze "C", chyba że użytkownik wyraźnie wywoła setlocale(). Oznacza to, że większość zmian związanych z niekompatybilnością wsteczną jest już za nami. Wszelkie aplikacje zależne od locale systemu do konwersji wielkości liter starszych 8-bitowych zestawów znaków zostałyby zepsute przez PHP 8.0.
Oznacza to, że wszystkie poniższe funkcje wykonają konwersję wielkości liter ASCII z PHP.8.2:strtolower
, strtoupper
, stristr
, stripos
, strripos
, lcfirst
, ucfirst
, ucwords
, str_ireplace
W PHP mamy wiele sposobów na osadzanie zmiennych w łańcuchach:
- Bezpośrednie osadzanie zmiennych ("$foo")
- Nawiasy poza zmienną ("{$foo}")
- Nawiasy po znaku dolara ("${foo}")
- Zmienne zmienne ("${expr}", odpowiednik (string) ${expr})
Aby uniknąć nieporozumień i nadużyć, nie będą one już działać:
"Witaj ${świat}";
Przestarzałe: Używanie ${} w ciągach znaków jest przestarzałe
"Hello ${(world)}";
Przestarzałe: Używanie ${} (zmiennych zmiennych) w łańcuchach jest przestarzałe
To nie wszystkie zmiany, które PHP 8.2 nam zaoferuje. Niestety, nadal nie otrzymaliśmy wsparcia dla typów generycznych, zgodnie z tym, co powiedział Nikita, monomorfizowane typy generyczne dodałyby zbyt duży narzut wydajnościowy, a reifikowane typy generyczne wymagają wielu zmian w całej bazie kodu. To co jest jednak zauważalne, to dyscyplina i wizja zespołu. produkt. Zmiany wprowadzane w kolejnych wersjach języka stają się coraz wyraźniejsze, a zainteresowani zauważą, że PHP zmierza w dobrym kierunku zarówno w obszarze upraszczania składni, jak i wsparcia dla nowości. Spodziewam się, że już w przyszłym roku zobaczymy wywoływalny
jako prawidłowy typ.