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