class Status
{
const DRAFT = 'draft';
const PUBLISHED = 'published';
const ARCHIVED = 'archived';
}
function acceptStatus(string $status) {...}enum Status
{
case Draft;
case Published;
case Archived;
}
function acceptStatus(Status $status) {...}class BlogData
{
private Status $status;
public function __construct(Status $status)
{
$this->status = $status;
}
public function getStatus(): Status
{
return $this->status;
}
}class BlogData
{
public readonly Status $status;
public function __construct(Status $status)
{
$this->status = $status;
}
}Readonly თვისებების შეცვლა შეუძლებელია ინიციალიზაციის შემდეგ (ანუ მას შემდეგ რაც მათ მიენიჭება მნიშვნელობა).
ისინი ძალიან სასარგებლო იქნება ისეთი ობიექტების განხორციელებისას, როგორიცაა VO და DTO.
$foo = [$this, 'foo'];
$fn = Closure::fromCallable('strlen');$foo = $this->foo(...);
$fn = strlen(...);ახალი სინტაქსით, ნებისმიერ ფუნქციას შეუძლია იმოქმედოს როგორც პირველი კლასის ობიექტი. ამრიგად, ის ჩაითვლება როგორც ჩვეულებრივი მნიშვნელობა, რომელიც შეიძლება, მაგალითად, შევინახოთ ცვლადში.
class Service
{
private Logger $logger;
public function __construct(
?Logger $logger = null,
) {
$this->logger = $logger ?? new NullLogger();
}
}class Service
{
private Logger $logger;
public function __construct(
Logger $logger = new NullLogger(),
) {
$this->logger = $logger;
}
}ახლა ობიექტები შეიძლება გამოყენებულ იქნას როგორც ნაგულისხმევი პარამეტრის მნიშვნელობები, სტატიკური ცვლადებისა და გლობალური კონსტანტებში, და ასევე ატრიბუტების არგუმენტებში.
ამრიგად, შესაძლებელი გახდა ჩაშენებული არგუმენტების გამოყენება.
class User
{
/**
* @Assert\All({
* @Assert\NotNull,
* @Assert\Length(min=5)
* })
*/
public string $name = '';
}class User
{
#[\Assert\All(
new \Assert\NotNull,
new \Assert\Length(min: 5))
]
public string $name = '';
}function count_and_iterate(Iterator $value) {
if (!($value instanceof Countable)) {
throw new TypeError('value must be Countable');
}
foreach ($value as $val) {
echo $val;
}
count($value);
}function count_and_iterate(Iterator&Countable $value) {
foreach ($value as $val) {
echo $val;
}
count($value);
}გამოიყენეთ კვეთის ტიპები, როდესაც მნიშვნელობას სჭირდება ერთდროულად მრავალი ტიპის შეზღუდვის დაკმაყოფილება.
ამ დროისთვის, ტიპის კვეთა არ შეიძლება გამოყენებულ იქნას გაერთიანებულ ტიპებთან ერთად., მაგალითად, A&B|C.
function redirect(string $uri) {
header('Location: ' . $uri);
exit();
}
function redirectToLoginPage() {
redirect('/login');
echo 'Hello'; // <- dead code
}function redirect(string $uri): never {
header('Location: ' . $uri);
exit();
}
function redirectToLoginPage(): never {
redirect('/login');
echo 'Hello'; // <- dead code detected by static analysis
}ფუნქცია ან მეთოდი, რომელიც გამოცხადებულია never ტიპთან ერთად, მიუთითებს იმაზე, რომ ისინი არ დააბრუნებენ მნიშვნელობას და ან გამოიტანს გამონაკლისს, ან დაასრულებს სკრიპტის შესრულებას ფუნქციის die(), exit(), trigger_error() გამოძახებით, ან რაიმე მსგავსით.
class Foo
{
public const XX = "foo";
}
class Bar extends Foo
{
public const XX = "bar"; // No error
}class Foo
{
final public const XX = "foo";
}
class Bar extends Foo
{
public const XX = "bar"; // Fatal error
}უკვე, კლასის კონსტანტები შესაძლებელია გამოცხადდეს როგორც საბოლოო (final), რათა მათი ხელახლა გამოცხადება არ მოხდეს შვილ კლასებში.
016 === 16; // false because `016` is octal for `14` and it's confusing
016 === 14; // true 0o16 === 16; // false — not confusing with explicit notation
0o16 === 14; // true ახლა თქვენ შეგიძლიათ ჩაწეროთ რვაობითი რიცხვები აშკარა პრეფიქსით 0o prefix.
$httpClient->request('https://example.com/')
->then(function (Response $response) {
return $response->getBody()->buffer();
})
->then(function (string $responseBody) {
print json_decode($responseBody)['code'];
});$response = $httpClient->request('https://example.com/');
print json_decode($response->getBody()->buffer())['code'];ფაიბერები - ეს არის პრიმიტივები მსუბუქი საერთო კონკურენციის განსახორციელებლად. ისინი წარმოადგენენ კოდის ბლოკების შექმნის საშუალებას, რომელიც შეიძლება შეჩერდეს და განახლდეს, გენერატორების მსგავსად, მაგრამ სტეკის ნებისმიერი წერტილიდან. ფაიბერები თავისთავად არ იძლევა ამოცანების ასინქრონულად შესრულების შსაძლებლობას, მაინც უნდა არსებობდეს მოვლენის მართვის ციკლი. თუმცა, ისინი საშუალებას აძლევენ მბლოკავ და არამბლოკავ რეალიზაციება გამოიყენონ ერთი და იგივე იგივე API.
ფაიბერები საშუალებას გაძლევთ თავიდან აიცილოთ შაბლონური კოდი, რომელსაც ადრე იყენებდნენ Promise::then() გამოყენებით ან გენერატორზე დაფუძნებული კორუტინები. ბიბლიოთეკები ჩვეულებრივ ქმნიან დამატებით აბსტრაქციებს ფაიბერების ირგვლივ, ამიტომ არ არის საჭირო მათთან უშუალო ურთიერთობა.
$arrayA = ['a' => 1];
$arrayB = ['b' => 2];
$result = array_merge(['a' => 0], $arrayA, $arrayB);
// ['a' => 1, 'b' => 2]$arrayA = ['a' => 1];
$arrayB = ['b' => 2];
$result = ['a' => 0, ...$arrayA, ...$arrayB];
// ['a' => 1, 'b' => 2]PHP ადრე გამოიყენება მასივების ჩამოქაფებას ოპერატორის ... დახმარებით, მაგრამ მხოლოდ იმ შემთხვევაში, თუ მასივები იყო მთელი რიცხვების გასაღებით. ახლა თქვენ ასევე შეგიძლიათ ჩამოქაფოთ მასივები სტრიქონიანი გასაღებებით.
timelib და ext/date.serialize()/unserialize() ფუნქციების ოპტიმიზაცია.#[ReturnTypeWillChange].fsync და fdatasync.array_is_list.NULL მნიშვნელობების ჩაშენებული ფუნქციის პარამეტრებზე გადაცემა, მოძველებულია.Serializable ინტერფეისი მოძველებულია.$GLOBALS ცვლადის გამოყენების შეზღუდვები.file_info რესურსები ახლა წარმოდგენილია როგორც finfo ობიექტი.imap რესურსები ახლა წარმოდგენილია როგორც IMAP\Connection ობიექტი.Connection რესურსები ახლა წარმოდგენილია როგორც FTP\Connection ობიექტი.Font identifiers тახლა წარმოდგენილია როგორც GdFont ობიექტი.LDAP\Connection, LDAP\Result, და LDAP\ResultEntry objects.PgSql\Connection, PgSql\Result, და PgSql\Lob.pspell, pspell config წარმოდგენილია როგორც ობიექტი PSpell\Dictionary, PSpell\Config