Hàm PHP trả về mảng đối tượng

Với PHP 7, bạn có thể chọn viết mã an toàn hơn nhiều so với trước đây, nhờ gợi ý kiểu vô hướng và kiểu trả về

function repeat[string $text, int $times] : string;

Nhưng còn mảng thì sao? . Đối với IDE, bạn có thể thêm nhận xét PhpDoc

/**
 * @return User[]
 */
function allUsers[] : array;

Giờ đây, các IDE như PhpStorm có thể giúp hoàn thành mã cho các mục trong mảng được trả về. Nhưng chúng tôi không thể hưởng lợi từ bất kỳ kiểm tra nào trong thời gian chạy, như với các gợi ý kiểu thực

Đối với các đối số, có một cách giải quyết một phần, sử dụng các đối số biến đổi. Thực hiện chức năng sau

/**
 * @param User[] $users
 */
function deleteUsers[array $users];

Với các đối số matrixdic, chúng ta có thể viết lại nó thành

function deleteUsers[User ...$users];

Cách sử dụng cũng thay đổi, thành

/**
 * @param User[] $users
 */
function deleteUsers[array $users];
1 Trong lệnh gọi này, đối số
/**
 * @param User[] $users
 */
function deleteUsers[array $users];
2 sẽ được “giải nén” thành các biến đơn lẻ và trong chính phương thức đó, nó được “đóng gói” lại thành một mảng
/**
 * @param User[] $users
 */
function deleteUsers[array $users];
2. Mỗi mặt hàng được xác nhận thuộc loại
/**
 * @param User[] $users
 */
function deleteUsers[array $users];
4.
/**
 * @param User[] $users
 */
function deleteUsers[array $users];
2 cũng có thể là một iterator, nó sẽ được chuyển đổi thành một mảng

Thật không may, không có cách giải quyết tương tự cho các kiểu trả về và nó chỉ hoạt động cho đối số cuối cùng

Xem thêm. Nhập gợi ý trong PHP 7 – mảng đối tượng

Tôi đã sử dụng kỹ thuật này rất nhiều trong mã PHP 7, nhưng tôi đã tìm thấy một kỹ thuật khác thậm chí còn tốt hơn và không có các lỗi đã đề cập

đối tượng bộ sưu tập

Mỗi khi tôi cần một mảng đối tượng, tôi tạo một lớp thay thế. Đây là một ví dụ đơn giản

class Users extends ArrayIterator
{
    public function __construct[User ...$users]
    {
        parent::__construct[$users];
    }
    public function current[] : User
    {
        return parent::current[];
    }
    public function offsetGet[$offset] : User
    {
        return parent::offsetGet[$offset];
    }
}

Bộ sưu tập này kéo dài

/**
 * @param User[] $users
 */
function deleteUsers[array $users];
6, vì vậy nó có thể được sử dụng gần giống như một mảng. lặp lại với
/**
 * @param User[] $users
 */
function deleteUsers[array $users];
7 và truy cập các phần tử với
/**
 * @param User[] $users
 */
function deleteUsers[array $users];
8. Hàm mảng không dùng được nhưng với
/**
 * @param User[] $users
 */
function deleteUsers[array $users];
9 thì có thể chuyển thành mảng bình thường

Lưu ý rằng bạn chỉ có thể thay đổi gợi ý kiểu trả về để hạn chế hơn trong lớp cha. Vì vậy, việc ghi đè

function deleteUsers[User ...$users];
0 sẽ không hoạt động và đối tượng sẽ ở trạng thái chưa được xác thực cho đến khi từng mục được truy cập

Nếu chúng ta không cần giao diện

function deleteUsers[User ...$users];
1 để truy cập các phần tử với
/**
 * @param User[] $users
 */
function deleteUsers[array $users];
8, thì có một giải pháp cho điều đó. đóng gói trình lặp mảng và chỉ hiển thị những gì bạn cần

class Users extends IteratorIterator
{
    public function __construct[User ...$users]
    {
        parent::__construct[new ArrayIterator[$users]];
    }
    public function current[] : User
    {
        return parent::current[];
    }
}

[bạn có bao giờ tự hỏi, tại sao

function deleteUsers[User ...$users];
3 lại tồn tại không? Ở đây tôi đã tìm thấy một trường hợp sử dụng. ]

Đối tượng

function deleteUsers[User ...$users];
4 này chỉ có thể được tạo với các phần tử
/**
 * @param User[] $users
 */
function deleteUsers[array $users];
4, nhờ các đối số hàm tạo biến đổi. Chuyển bất cứ thứ gì khác cho hàm tạo sẽ dẫn đến một
function deleteUsers[User ...$users];
6 có thể bắt được

new Users[$user1, $user2, $user3];

Và nó thậm chí là bất biến, nó không thể thay đổi sau khi khởi tạo. Nhưng nếu chúng ta cần thay đổi nó, bây giờ chúng ta có thể thêm các phương thức an toàn cho điều đó, như

public function add[User $user]
{
    $this->getInnerIterator[]->append[$user];
}
public function set[int $key, User $user]
{
    $this->getInnerIterator[]->offsetSet[$key, $user];
}

Bạn cũng có thể làm cho nó có thể đếm được [vì chúng tôi biết, trình vòng lặp bên trong thực hiện

function deleteUsers[User ...$users];
7]

    public function count[] : int
    {
        return $this->getInnerIterator[]->count[];
    }

Hàm mảng

Như đã đề cập trước đây, nếu bạn cần các hàm mảng, bạn luôn có thể chuyển đổi đối tượng thành một mảng bằng

/**
 * @param User[] $users
 */
function deleteUsers[array $users];
9. Nhưng có một giải pháp khác thường hợp lý hơn. di chuyển chức năng vào lớp bộ sưu tập. Đối với các hàm sắp xếp, thật dễ dàng vì chúng đã là một phần của
/**
 * @param User[] $users
 */
function deleteUsers[array $users];
6, vì vậy chúng ta có thể thực hiện tương tự như với
class Users extends ArrayIterator
{
    public function __construct[User ...$users]
    {
        parent::__construct[$users];
    }
    public function current[] : User
    {
        return parent::current[];
    }
    public function offsetGet[$offset] : User
    {
        return parent::offsetGet[$offset];
    }
}
0 ở trên

Nhưng hãy lấy một ví dụ khác và hợp nhất hai bộ sưu tập người dùng

public function merge[Users $other]
{
    return new Users[
        array_merge[
            iterator_to_array[$this],
            iterator_to_array[$other]
        ]
    ];
}

Bây giờ nó có thể được sử dụng như

/**
 * @return User[]
 */
function allUsers[] : array;
0

Khi thêm các phương thức vào các đối tượng bộ sưu tập, hãy càng cụ thể càng tốt để chuyển logic vào bộ sưu tập thuộc về đó. Ví dụ: thay vì tạo một phương thức

class Users extends ArrayIterator
{
    public function __construct[User ...$users]
    {
        parent::__construct[$users];
    }
    public function current[] : User
    {
        return parent::current[];
    }
    public function offsetGet[$offset] : User
    {
        return parent::offsetGet[$offset];
    }
}
1 chung chung, hãy tạo chính xác [các] phương thức sắp xếp mà bạn cần

/**
 * @return User[]
 */
function allUsers[] : array;
1

Điều đó làm cho mã máy khách rõ ràng hơn nhiều [điều không thể thực hiện được với mảng]

/**
 * @return User[]
 */
function allUsers[] : array;
2

Với các phương thức lọc/ánh xạ/thu nhỏ, chúng tôi cũng có tùy chọn để làm việc với các đường ống thu thập, như tôi đã giải thích trong một bài đăng trên blog trước đây. Đường ống thu thập trong PHP

Lôgic tên miền

Khi tôi cần một tập hợp các đối tượng, trước tiên tôi thường tạo một lớp đơn giản, mở rộng

function deleteUsers[User ...$users];
3, như trong ví dụ trên. Ưu điểm rõ ràng là an toàn kiểu, nhưng nó cũng giúp dễ dàng thêm logic miền vào đúng chỗ sau này. Ngay khi tôi có các phương thức hoạt động trên một tập hợp các đối tượng, tôi có thể thêm chúng trực tiếp vào lớp tập hợp, nơi chúng thuộc về một cách tự nhiên. Nếu không, chúng có thể kết thúc trong một số lớp tiện ích hoặc trình trợ giúp [Ngừng sử dụng Trình trợ giúp. ] hoặc thậm chí trong mã máy khách sử dụng bộ sưu tập

Hãy coi đây là một phần của trò chơi bài

/**
 * @return User[]
 */
function allUsers[] : array;
3

Nó kết hợp logic trò chơi cấp cao với các chi tiết triển khai cấp thấp. Với một đối tượng bộ sưu tập thẻ, chúng ta có thể di chuyển các phương thức hoạt động trên thẻ ở đó và giữ lớp Game ở một mức trừu tượng

/**
 * @return User[]
 */
function allUsers[] : array;
4

giao diện

Trước tiên, việc xác định bộ sưu tập là giao diện thường hữu ích. Nó mở rộng giao diện

class Users extends ArrayIterator
{
    public function __construct[User ...$users]
    {
        parent::__construct[$users];
    }
    public function current[] : User
    {
        return parent::current[];
    }
    public function offsetGet[$offset] : User
    {
        return parent::offsetGet[$offset];
    }
}
3 và chứa ít nhất phương thức
class Users extends ArrayIterator
{
    public function __construct[User ...$users]
    {
        parent::__construct[$users];
    }
    public function current[] : User
    {
        return parent::current[];
    }
    public function offsetGet[$offset] : User
    {
        return parent::offsetGet[$offset];
    }
}
4 với kiểu trả về được chỉ định

Ví dụ tối thiểu

/**
 * @return User[]
 */
function allUsers[] : array;
5

Với cách triển khai mặc định như được bao bọc

/**
 * @param User[] $users
 */
function deleteUsers[array $users];
6

/**
 * @return User[]
 */
function allUsers[] : array;
6

Tại sao nó hữu ích?

Thực hiện có thể trao đổi

Đầu tiên, nếu mã của bạn sẽ được sử dụng bởi các bên thứ ba, họ sẽ có thể hoán đổi việc triển khai. Ví dụ yêu thích của tôi là lười tải các bộ sưu tập với trình tạo để có hiệu suất tốt hơn với các bộ sưu tập lớn

/**
 * @return User[]
 */
function allUsers[] : array;
7

mà sau đó có thể được khởi tạo như thế này

/**
 * @return User[]
 */
function allUsers[] : array;
8

Ở đây, các đối tượng Người dùng không được tìm nạp từ cơ sở dữ liệu trước khi bạn thực sự lặp lại bộ sưu tập tải chậm. Vì các trình tạo chỉ có thể được lặp lại một lần, nên bộ sưu tập sẽ không giữ tất cả các đối tượng trong bộ nhớ cùng một lúc

Khả năng mở rộng với trang trí

Thứ hai, bạn sẽ có thể mở rộng lớp với các trình trang trí, bao bọc thể hiện ban đầu và triển khai cùng một giao diện, nhưng thêm hành vi bổ sung. Bạn thậm chí có thể sử dụng bộ sưu tập để trang trí tất cả các mặt hàng một cách nhanh chóng

Giả sử việc triển khai

class Users extends ArrayIterator
{
    public function __construct[User ...$users]
    {
        parent::__construct[$users];
    }
    public function current[] : User
    {
        return parent::current[];
    }
    public function offsetGet[$offset] : User
    {
        return parent::offsetGet[$offset];
    }
}
6 mặc định trong trò chơi bài tuyệt vời của chúng ta có một phương thức
class Users extends ArrayIterator
{
    public function __construct[User ...$users]
    {
        parent::__construct[$users];
    }
    public function current[] : User
    {
        return parent::current[];
    }
    public function offsetGet[$offset] : User
    {
        return parent::offsetGet[$offset];
    }
}
7 trả về quân bài phù hợp và xếp hạng dưới dạng văn bản thuần túy, đồng thời thêm một trình trang trí cho biểu diễn HTML

/**
 * @return User[]
 */
function allUsers[] : array;
9

Bây giờ chúng ta cũng có thể viết một trình trang trí cho bộ sưu tập, lấy bất kỳ bộ sưu tập

class Users extends ArrayIterator
{
    public function __construct[User ...$users]
    {
        parent::__construct[$users];
    }
    public function current[] : User
    {
        return parent::current[];
    }
    public function offsetGet[$offset] : User
    {
        return parent::offsetGet[$offset];
    }
}
8 nào và trang trí các phần tử của nó bằng
class Users extends ArrayIterator
{
    public function __construct[User ...$users]
    {
        parent::__construct[$users];
    }
    public function current[] : User
    {
        return parent::current[];
    }
    public function offsetGet[$offset] : User
    {
        return parent::offsetGet[$offset];
    }
}
9

Làm cách nào để trả về một mảng đối tượng trong PHP?

Phương pháp 1. Sử dụng phương thức json_decode và json_encode . Hàm json_decode chấp nhận chuỗi được mã hóa JSON và chuyển đổi nó thành một biến PHP, mặt khác, json_encode trả về một chuỗi được mã hóa JSON cho một giá trị nhất định. cú pháp. $myArray = json_decode[json_encode[$object], true];

Hàm PHP có thể trả về một mảng không?

Có thể trả về bất kỳ loại nào, kể cả mảng và đối tượng .

Làm cách nào để truy cập mảng đối tượng trong PHP?

Để truy cập một phần tử mảng trong một mảng con, bạn chỉ cần dùng nhiều dấu [] .

Bạn có thể có một mảng các đối tượng trong PHP không?

Tùy chọn2. Cách tạo một mảng đối tượng trong PHP dùng hàm array_push[] . Hàm array_push trong PHP nối các giá trị vào một mảng. Ví dụ sau sử dụng hàm này để thêm các đối tượng nhân viên vào mảng. //Khởi tạo một mảng.

Chủ Đề