Hướng dẫn php 8.2 features - tính năng php 8.2

Thật tốt khi có mức tăng hiệu suất, nhưng tại thời điểm này là phiên bản cận biên đến phiên bản. Những người mà thiên đường đã nhảy từ 5.x là những người sẽ thấy sự khác biệt lớn, đặc biệt là về mặt ngôn ngữ.

Tôi tự hỏi nếu bước tiếp theo cho hiệu suất PHP là sử dụng các hướng dẫn phần cứng thường xuyên hơn, hoặc tối ưu hóa việc biên dịch để tận dụng một cái gì đó. Ai biết được, trong tương lai, PHP sẽ sử dụng AVX hoặc thậm chí GPU để tận dụng một số nhiệm vụ nặng nề.

Giảm sự phụ thuộc vào ngữ cảnh của các thiết bị gọi là mục tiêu thứ yếu của RFC này. Sau RFC này, sự phụ thuộc phạm vi duy nhất vẫn còn lại là khả năng hiển thị của phương thức: "FOO :: Bar" có thể được nhìn thấy trong một phạm vi, nhưng không phải là một phạm vi khác. Nếu các thiết bị gọi được giới hạn trong các phương thức công khai trong tương lai (trong khi các phương thức riêng tư sẽ phải sử dụng các thiết bị gọi hạng nhất hoặc đóng: được sử dụng như một loại tài sản. Tuy nhiên, những thay đổi trong xử lý khả năng hiển thị không được đề xuất như là một phần của RFC này.

Giảm sự phụ thuộc vào ngữ cảnh của các thiết bị gọi là mục tiêu thứ yếu của RFC này. Sau RFC này, sự phụ thuộc phạm vi duy nhất vẫn còn lại là khả năng hiển thị của phương thức: "FOO :: Bar" có thể được nhìn thấy trong một phạm vi, nhưng không phải là một phạm vi khác. Nếu các thiết bị gọi được giới hạn trong các phương thức công khai trong tương lai (trong khi các phương thức riêng tư sẽ phải sử dụng các thiết bị gọi hạng nhất hoặc đóng cửa :: fromcallable () để được thực hiện độc lập với phạm vi) được sử dụng như một loại tài sản. Tuy nhiên, những thay đổi trong xử lý khả năng hiển thị không được đề xuất như là một phần của RFC này.

Php 8.2 đang giới thiệu hỗ trợ cho các lớp chỉ đọc (đọc), một hàm để đặt lại theo dõi sử dụng cực đại bộ nhớ, phân tách giá trị tham số nhạy cảm trong dấu vết ngăn xếp, không dùng tính chất động và các thay đổi khác. Một số thử nghiệm vào cuối tuần của Php 8.2 Git đã diễn ra tốt đẹp và không có kết quả.

Từ hộp phát triển AMD Ryzen 9 5950X, tôi đã chạy một số điểm chuẩn khi thấy Php 8.2 Git đã so sánh với bản phát hành Php 8.1.6 mới nhất trên cùng một hệ thống với một số điểm chuẩn rất sơ bộ cho điểm khoảng nửa đường này qua chu kỳ Php 8.2 .

Phpbench đã cho thấy mức tăng khoảng 2,5% trong hiệu suất PHP 8.2 so với Php 8.1, không lớn như trong một số bản phát hành trước đây, nhưng hãy nhớ rằng chúng tôi vẫn còn xa so với bản phát hành Php 8.2.0 thực tế .. . Và nó nằm trên cùng với nhiều mức tăng hiệu suất đã vượt qua loạt Php 7.x và 8.x.

Có những cải tiến nhỏ nhưng có thể đo lường được trong một số điểm chuẩn hiệu suất của bộ thử nghiệm Phoronix của riêng tôi cho các nhiệm vụ PHP CLI khác nhau.

Giống như thời gian để tạo ra nhiều biểu đồ SVG tiếp tục được cải thiện với PHP 8.2.

Việc sử dụng bộ nhớ cực đại trên PHP 8.2 GIT cũng thấp hơn Php 8.1.

Vì vậy, ít nhất từ ​​thử nghiệm ban đầu của tôi, PHP 8.2 tiếp tục di chuyển theo đúng hướng nhanh hơn mặc dù trong một vài phần trăm trong các thử nghiệm khác nhau cho đến nay và với mức sử dụng bộ nhớ cực đại thấp hơn một chút. Tất nhiên, một khi bản phát hành ổn định PHP 8.2 đang đến gần, tôi sẽ quay lại với nhiều điểm chuẩn hơn và quay lại so sánh hiệu suất với các bản phát hành PHP5 và PHP7 lịch sử hơn.

Scout APM giúp các nhà phát triển PHP xác định các truy vấn N+1, rò rỉ bộ nhớ và nhiều hơn nữa để bạn có thể khắc phục sự cố nhanh chóng và quay lại mã hóa nhanh hơn. Bắt đầu dùng thử 14 ngày miễn phí của bạn ngay hôm nay.

Giảm sự phụ thuộc vào ngữ cảnh của các thiết bị gọi là mục tiêu thứ yếu của RFC này. Sau RFC này, sự phụ thuộc phạm vi duy nhất vẫn còn lại là khả năng hiển thị của phương thức: "FOO :: Bar" có thể được nhìn thấy trong một phạm vi, nhưng không phải là một phạm vi khác. Nếu các thiết bị gọi được giới hạn trong các phương thức công khai trong tương lai (trong khi các phương thức riêng tư sẽ phải sử dụng các thiết bị gọi hạng nhất hoặc đóng cửa :: fromcallable () để được thực hiện độc lập với phạm vi) được sử dụng như một loại tài sản. Tuy nhiên, những thay đổi trong xử lý khả năng hiển thị không được đề xuất như là một phần của RFC này. In this post, we'll go through all features, performance improvements, changes and deprecations one by one.

# Lớp học Readonly RFC

Các thuộc tính readonly đã được giới thiệu trong Php 8.1. RFC này được xây dựng trên đầu chúng và thêm đường cú pháp để làm cho tất cả các thuộc tính của lớp một cách sẵn sàng cùng một lúc. Thay vì viết bài này:

class Post
{
    public function __construct(
        public readonly string $title, 
        public readonly Author $author,
        public readonly string $body,
        public readonly DateTime $publishedAt,
    ) {}
}

Bây giờ bạn có thể viết cái này:

readonly class Post
{
    public function __construct(
        public string $title, 
        public Author $author,
        public string $body,
        public DateTime $publishedAt,
    ) {}
}

Về mặt chức năng, việc làm cho một lớp đọc hoàn toàn giống như làm cho mọi tài sản sẵn sàng; Nhưng nó cũng sẽ ngăn chặn các thuộc tính động được thêm vào trong một lớp:

$post = new Post(/* … */);

$post->unknown = 'wrong';

Uncaught Error: Cannot create dynamic property Post::$unknown

Lưu ý rằng bạn chỉ có thể mở rộng từ các lớp đọc lại nếu lớp con cũng đọc được.

PHP đã thay đổi khá nhiều, và các lớp đọc là một bổ sung đáng hoan nghênh. Bạn có thể xem video của tôi về sự tiến hóa của PHP nếu bạn cũng muốn:


# DEVENATE ĐỘNG SẢN RFC

Tôi muốn nói đây là một sự thay đổi tốt hơn, nhưng nó sẽ đau một chút. Các thuộc tính động được không dùng nữa trong Php 8.2 và sẽ ném

$post = new Post(/* … */);

$post->unknown = 'wrong';

Uncaught Error: Cannot create dynamic property Post::$unknown
1 vào Php 9.0:

class Post
{
    public string $title;
}

// …

$post->name = 'Name';

Hãy nhớ rằng các lớp thực hiện

$post = new Post(/* … */);

$post->unknown = 'wrong';

Uncaught Error: Cannot create dynamic property Post::$unknown
2 và
$post = new Post(/* … */);

$post->unknown = 'wrong';

Uncaught Error: Cannot create dynamic property Post::$unknown
3 vẫn sẽ hoạt động như dự định:

class Post
{
    private array $properties = [];
    
    public function __set(string $name, mixed $value): void
    {
        $this->properties[$name] = $value;
    }
}

// …

$post->name = 'Name';

Nếu bạn muốn tìm hiểu thêm về lý do tại sao khấu hao là hữu ích và cách đối phó với chúng, bạn có thể đọc bài đăng tiếp theo này về cách đối phó với việc khấu hao hoặc bạn có thể kiểm tra vlog của tôi:


# RFC tiện ích mở rộng ngẫu nhiên mới

Php 8.2 bổ sung một trình tạo số ngẫu nhiên mới khắc phục nhiều vấn đề với số trước: nó có hiệu suất hơn, an toàn hơn, nó dễ dàng hơn để duy trì và không dựa vào trạng thái toàn cầu; Loại bỏ một loạt các lỗi khó phát hiện khi sử dụng các chức năng ngẫu nhiên của PHP.

Có một lớp mới gọi là

$post = new Post(/* … */);

$post->unknown = 'wrong';

Uncaught Error: Cannot create dynamic property Post::$unknown
4, chấp nhận một công cụ ngẫu nhiên. Bây giờ bạn có thể thay đổi động cơ đó, tùy thuộc vào nhu cầu của bạn. Ví dụ, để phân biệt giữa môi trường sản xuất và thử nghiệm.

$rng = $is_production
    ? new Random\Engine\Secure()
    : new Random\Engine\Mt19937(1234);
 
$randomizer = new Random\Randomizer($rng);
$randomizer->shuffleString('foobar');

# null, true và false như các loại độc lập rfc

Php 8.2 thêm ba loại mới - hoặc một cái gì đó trông giống như nó. Chúng tôi sẽ tránh đi xuống lỗ thỏ an toàn trong bài đăng này, nhưng về mặt kỹ thuật

$post = new Post(/* … */);

$post->unknown = 'wrong';

Uncaught Error: Cannot create dynamic property Post::$unknown
5,
$post = new Post(/* … */);

$post->unknown = 'wrong';

Uncaught Error: Cannot create dynamic property Post::$unknown
6 và
$post = new Post(/* … */);

$post->unknown = 'wrong';

Uncaught Error: Cannot create dynamic property Post::$unknown
7 có thể được coi là các loại hợp lệ. Các ví dụ phổ biến là các chức năng tích hợp của PHP, trong đó
$post = new Post(/* … */);

$post->unknown = 'wrong';

Uncaught Error: Cannot create dynamic property Post::$unknown
7 được sử dụng làm loại trả về khi xảy ra lỗi. Ví dụ: trong
$post = new Post(/* … */);

$post->unknown = 'wrong';

Uncaught Error: Cannot create dynamic property Post::$unknown
9:

file_get_contents(/* … */): string|false

Trước Php 8.2, bạn đã có thể sử dụng

$post = new Post(/* … */);

$post->unknown = 'wrong';

Uncaught Error: Cannot create dynamic property Post::$unknown
7 cùng với các loại khác như một liên minh; Nhưng bây giờ nó cũng có thể được sử dụng như một loại độc lập:

function alwaysFalse(): false
{
    return false;
}

Bây giờ cũng giống như

$post = new Post(/* … */);

$post->unknown = 'wrong';

Uncaught Error: Cannot create dynamic property Post::$unknown
6 và
$post = new Post(/* … */);

$post->unknown = 'wrong';

Uncaught Error: Cannot create dynamic property Post::$unknown
5.


# Loại hình thức bình thường khác nhau RFC

Các loại DNF cho phép chúng tôi kết hợp các loại liên minh và giao điểm, tuân theo một quy tắc nghiêm ngặt: khi kết hợp các loại liên minh và giao điểm, các loại giao nhau phải được nhóm lại với dấu ngoặc. Trong thực tế, trông như thế này:

function generateSlug((HasTitle&HasId)|null $post) 
{
    if ($post === null) {
        return '';
    }

    return 
        strtolower($post->getTitle()) 
        . $post->getId();
}

Trong trường hợp này,

class Post
{
    public string $title;
}

// …

$post->name = 'Name';
3 là loại DNF.

Đó là một bổ sung tốt đẹp, đặc biệt là vì nó có nghĩa là giờ đây chúng ta có thể có các loại giao điểm có thể vô hiệu hóa, có lẽ là trường hợp sử dụng quan trọng nhất cho tính năng này.


# Hằng số trong các đặc điểm RFC

Bây giờ bạn có thể sử dụng các hằng số trong các đặc điểm:

trait Foo 
{
    public const CONSTANT = 1;
 
    public function bar(): int 
    {
        return self::CONSTANT;
    }
}

Bạn sẽ không thể truy cập vào hằng số thông qua tên của đặc điểm, từ bên ngoài đặc điểm hoặc từ bên trong nó.

readonly class Post
{
    public function __construct(
        public string $title, 
        public Author $author,
        public string $body,
        public DateTime $publishedAt,
    ) {}
}
0

Tuy nhiên, bạn có thể truy cập hằng số thông qua lớp sử dụng đặc điểm, cho rằng nó là công khai:

readonly class Post
{
    public function __construct(
        public string $title, 
        public Author $author,
        public string $body,
        public DateTime $publishedAt,
    ) {}
}
1

# Tái cấu trúc các tham số trong dấu vết trở lại RFC

Một thông lệ phổ biến trong bất kỳ cơ sở mã nào là gửi lỗi sản xuất đến một dịch vụ theo dõi chúng và sẽ thông báo cho các nhà phát triển khi có sự cố xảy ra. Thực tiễn này thường liên quan đến việc gửi dấu vết ngăn xếp qua dây đến dịch vụ của bên thứ ba. Tuy nhiên, có trường hợp những dấu vết ngăn xếp đó có thể bao gồm thông tin nhạy cảm như biến môi trường, mật khẩu hoặc tên người dùng.

Php 8.2 cho phép bạn đánh dấu "các tham số nhạy cảm" như vậy bằng một thuộc tính, do đó bạn không cần phải lo lắng về việc chúng được liệt kê trong dấu vết ngăn xếp của bạn khi có sự cố. Đây là một ví dụ từ RFC:

readonly class Post
{
    public function __construct(
        public string $title, 
        public Author $author,
        public string $body,
        public DateTime $publishedAt,
    ) {}
}
2

# Tìm nạp thuộc tính của enums trong các biểu thức const RFC

Từ RFC:

RFC này đề xuất cho phép sử dụng ________ 34/________ 35 để tìm nạp các thuộc tính của các enum trong các biểu thức không đổi. Động lực chính cho thay đổi này là cho phép tìm nạp tên và các thuộc tính giá trị ở những nơi không được phép đối tượng, như các phím mảng

Điều đó có nghĩa là mã sau đây có hiệu lực:

readonly class Post
{
    public function __construct(
        public string $title, 
        public Author $author,
        public string $body,
        public DateTime $publishedAt,
    ) {}
}
3

# Trả về Loại thay đổi cho DateTime :: createdFromimMutable () và datetimeMtable :: createFrommutable () Breaking

Trước đây, các phương pháp này trông như thế này:

readonly class Post
{
    public function __construct(
        public string $title, 
        public Author $author,
        public string $body,
        public DateTime $publishedAt,
    ) {}
}
4

Trong PHP 8.2, những chữ ký phương pháp đó được thay đổi như vậy:

readonly class Post
{
    public function __construct(
        public string $title, 
        public Author $author,
        public string $body,
        public DateTime $publishedAt,
    ) {}
}
5

Sự thay đổi này có ý nghĩa hơn rất nhiều, vì nó cải thiện khả năng hiểu biết tĩnh cho các lớp kéo dài từ

class Post
{
    public string $title;
}

// …

$post->name = 'Name';
6 và
class Post
{
    public string $title;
}

// …

$post->name = 'Name';
7. Tuy nhiên, về mặt kỹ thuật, đây là một sự thay đổi phá vỡ có thể ảnh hưởng đến việc triển khai tùy chỉnh mở rộng từ một trong hai lớp đó.


# utf8_encode () và utf8_decode ()

Trong Php 8.2, sử dụng

class Post
{
    public string $title;
}

// …

$post->name = 'Name';
8 hoặc
class Post
{
    public string $title;
}

// …

$post->name = 'Name';
9 sẽ kích hoạt các thông báo từ chối này:

readonly class Post
{
    public function __construct(
        public string $title, 
        public Author $author,
        public string $body,
        public DateTime $publishedAt,
    ) {}
}
6

RFC lập luận rằng các chức năng này có tên không chính xác thường gây ra sự nhầm lẫn: các chức năng này chỉ chuyển đổi giữa

class Post
{
    private array $properties = [];
    
    public function __set(string $name, mixed $value): void
    {
        $this->properties[$name] = $value;
    }
}

// …

$post->name = 'Name';
0 và
class Post
{
    private array $properties = [];
    
    public function __set(string $name, mixed $value): void
    {
        $this->properties[$name] = $value;
    }
}

// …

$post->name = 'Name';
1, trong khi tên hàm cho thấy sử dụng rộng hơn. Có một lời giải thích chi tiết hơn về lý do trong RFC.

Thay thế? RFC đề nghị sử dụng

class Post
{
    private array $properties = [];
    
    public function __set(string $name, mixed $value): void
    {
        $this->properties[$name] = $value;
    }
}

// …

$post->name = 'Name';
2 thay thế.


# STRTOLOWER () và strtouper () phá vỡ địa phương

Cả

class Post
{
    private array $properties = [];
    
    public function __set(string $name, mixed $value): void
    {
        $this->properties[$name] = $value;
    }
}

// …

$post->name = 'Name';
3 và
class Post
{
    private array $properties = [];
    
    public function __set(string $name, mixed $value): void
    {
        $this->properties[$name] = $value;
    }
}

// …

$post->name = 'Name';
4 không còn nhạy cảm với địa điểm. Bạn có thể sử dụng
class Post
{
    private array $properties = [];
    
    public function __set(string $name, mixed $value): void
    {
        $this->properties[$name] = $value;
    }
}

// …

$post->name = 'Name';
5 nếu bạn muốn chuyển đổi trường hợp cục bộ.


# Chữ ký thay đổi thành một số phương thức SPL

Một số phương pháp của các lớp SPL đã được thay đổi để thực thi đúng chữ ký loại của chúng:

readonly class Post
{
    public function __construct(
        public string $title, 
        public Author $author,
        public string $body,
        public DateTime $publishedAt,
    ) {}
}
7

# Công cụ sửa đổi n ne

Bây giờ bạn có thể sử dụng công cụ sửa đổi

class Post
{
    private array $properties = [];
    
    public function __set(string $name, mixed $value): void
    {
        $this->properties[$name] = $value;
    }
}

// …

$post->name = 'Name';
6 (
class Post
{
    private array $properties = [];
    
    public function __set(string $name, mixed $value): void
    {
        $this->properties[$name] = $value;
    }
}

// …

$post->name = 'Name';
7) trong các hàm
class Post
{
    private array $properties = [];
    
    public function __set(string $name, mixed $value): void
    {
        $this->properties[$name] = $value;
    }
}

// …

$post->name = 'Name';
8.


# Tên người dùng và mật khẩu ODBC

Từ hướng dẫn nâng cấp:

Tiện ích mở rộng

class Post
{
    private array $properties = [];
    
    public function __set(string $name, mixed $value): void
    {
        $this->properties[$name] = $value;
    }
}

// …

$post->name = 'Name';
9 hiện thoát khỏi tên người dùng và mật khẩu cho trường hợp khi cả chuỗi kết nối và tên người dùng/mật khẩu được truyền và chuỗi phải được thêm vào.

Điều tương tự áp dụng cho

$rng = $is_production
    ? new Random\Engine\Secure()
    : new Random\Engine\Mt19937(1234);
 
$randomizer = new Random\Randomizer($rng);
$randomizer->shuffleString('foobar');
0.

Nhận thấy một tpyo? Bạn có thể gửi PR để sửa nó. Nếu bạn muốn cập nhật những gì đang xảy ra trên blog này, bạn có thể theo dõi tôi trên Twitter hoặc đăng ký nhận bản tin của tôi:


# DEVELATE $ {} Chuỗi nội suy RFC

PHP có một số cách nhúng các biến trong chuỗi. RFC này phản đối hai cách làm như vậy, vì chúng hiếm khi được sử dụng và thường dẫn đến sự nhầm lẫn:

readonly class Post
{
    public function __construct(
        public string $title, 
        public Author $author,
        public string $body,
        public DateTime $publishedAt,
    ) {}
}
8

Để rõ ràng: Hai cách nội suy chuỗi phổ biến vẫn hoạt động:

readonly class Post
{
    public function __construct(
        public string $title, 
        public Author $author,
        public string $body,
        public DateTime $publishedAt,
    ) {}
}
9

# Khởi động các thiết bị gọi được hỗ trợ một phần RFC

Một thay đổi khác, mặc dù một thay đổi có tác động nhỏ hơn một chút, là các thiết bị gọi được hỗ trợ một phần hiện cũng không được chấp nhận. Các thiết bị gọi được hỗ trợ một phần là các thiết bị gọi có thể được gọi bằng

$rng = $is_production
    ? new Random\Engine\Secure()
    : new Random\Engine\Mt19937(1234);
 
$randomizer = new Random\Randomizer($rng);
$randomizer->shuffleString('foobar');
1, nhưng không phải bằng cách gọi trực tiếp
$rng = $is_production
    ? new Random\Engine\Secure()
    : new Random\Engine\Mt19937(1234);
 
$randomizer = new Random\Randomizer($rng);
$randomizer->shuffleString('foobar');
2. Nhân tiện, danh sách các loại bảng gọi này khá ngắn, nhân tiện:

$post = new Post(/* … */);

$post->unknown = 'wrong';

Uncaught Error: Cannot create dynamic property Post::$unknown
0

Lý do để làm điều này? Đó là một bước đi đúng hướng để có thể sử dụng

$rng = $is_production
    ? new Random\Engine\Secure()
    : new Random\Engine\Mt19937(1234);
 
$randomizer = new Random\Randomizer($rng);
$randomizer->shuffleString('foobar');
3 cho các thuộc tính được đánh máy. Nikita giải thích nó rất tốt trong RFC:

Tất cả các thiết bị gọi này phụ thuộc vào ngữ cảnh. Phương pháp mà "Tự :: Phương thức" đề cập đến phụ thuộc vào lớp kiểm tra cuộc gọi hoặc khả năng gọi được thực hiện từ đó. Trong thực tế, điều này cũng thường giữ cho hai trường hợp cuối cùng, khi được sử dụng dưới dạng [mới foo, "cha mẹ :: phương pháp"].

Giảm sự phụ thuộc vào ngữ cảnh của các thiết bị gọi là mục tiêu thứ yếu của RFC này. Sau RFC này, sự phụ thuộc phạm vi duy nhất vẫn còn lại là khả năng hiển thị của phương thức: "FOO :: Bar" có thể được nhìn thấy trong một phạm vi, nhưng không phải là một phạm vi khác. Nếu các thiết bị gọi được giới hạn trong các phương thức công khai trong tương lai (trong khi các phương thức riêng tư sẽ phải sử dụng các thiết bị gọi hạng nhất hoặc đóng: được sử dụng như một loại tài sản. Tuy nhiên, những thay đổi trong xử lý khả năng hiển thị không được đề xuất như là một phần của RFC này.


Đó là tất cả những gì bây giờ, tôi sẽ cập nhật danh sách này trong suốt cả năm. Bạn có thể đăng ký nhận bản tin của tôi nếu bạn muốn nhận các bản cập nhật không thường xuyên!

Nhận thấy một tpyo? Bạn có thể gửi PR để sửa nó. Nếu bạn muốn cập nhật những gì đang xảy ra trên blog này, bạn có thể theo dõi tôi trên Twitter hoặc đăng ký nhận bản tin của tôi:

# DEVELATE $ {} Chuỗi nội suy RFC

PHP có một số cách nhúng các biến trong chuỗi. RFC này phản đối hai cách làm như vậy, vì chúng hiếm khi được sử dụng và thường dẫn đến sự nhầm lẫn:

Để rõ ràng: Hai cách nội suy chuỗi phổ biến vẫn hoạt động:

# Khởi động các thiết bị gọi được hỗ trợ một phần RFC

Một thay đổi khác, mặc dù một thay đổi có tác động nhỏ hơn một chút, là các thiết bị gọi được hỗ trợ một phần hiện cũng không được chấp nhận. Các thiết bị gọi được hỗ trợ một phần là các thiết bị gọi có thể được gọi bằng

$rng = $is_production
    ? new Random\Engine\Secure()
    : new Random\Engine\Mt19937(1234);
 
$randomizer = new Random\Randomizer($rng);
$randomizer->shuffleString('foobar');
1, nhưng không phải bằng cách gọi trực tiếp
$rng = $is_production
    ? new Random\Engine\Secure()
    : new Random\Engine\Mt19937(1234);
 
$randomizer = new Random\Randomizer($rng);
$randomizer->shuffleString('foobar');
2. Nhân tiện, danh sách các loại bảng gọi này khá ngắn, nhân tiện:

Lý do để làm điều này? Đó là một bước đi đúng hướng để có thể sử dụng

$rng = $is_production
    ? new Random\Engine\Secure()
    : new Random\Engine\Mt19937(1234);
 
$randomizer = new Random\Randomizer($rng);
$randomizer->shuffleString('foobar');
3 cho các thuộc tính được đánh máy. Nikita giải thích nó rất tốt trong RFC:

Tất cả các thiết bị gọi này phụ thuộc vào ngữ cảnh. Phương pháp mà "Tự :: Phương thức" đề cập đến phụ thuộc vào lớp kiểm tra cuộc gọi hoặc khả năng gọi được thực hiện từ đó. Trong thực tế, điều này cũng thường giữ cho hai trường hợp cuối cùng, khi được sử dụng dưới dạng [mới foo, "cha mẹ :: phương pháp"].