Hướng dẫn php type hint associative array - mảng kết hợp gợi ý kiểu php

Tôi đang cố gắng để có được lợi thế của cách xử lý thông minh của Netbeans, vì vậy tôi gợi ý về loại bình luận của mọi đối tượng.

Vấn đề là, tôi muốn gợi ý một mảng kết hợp của (String => ObjectClass).

Tôi đã thử tất cả các phần sau nhưng không có gì hoạt động:

/** 
 * @var [string => ObjectClass]
 */
private $myAssociativeArray;

/** 
 * @var string|ObjectClass[]
 */
private $myAssociativeArray;

Làm thế nào tôi có thể nhận được NetBeans để biết rằng tôi đang gợi ý về bản đồ chuỗi thành ObjectClass?

Cảm ơn trước.

Hỏi ngày 5 tháng 10 năm 2013 lúc 6:30Oct 5, 2013 at 6:30

Hướng dẫn php type hint associative array - mảng kết hợp gợi ý kiểu php

1

Cách tốt nhất tôi có thể đạt được điều này là một khi bạn bắt đầu lặp lại thông qua mảng kết hợp, bạn có thể gõ gợi ý biến tại thời điểm đó. Điều này sẽ chỉ hoạt động nếu mảng giữ tất cả các loại cùng loại.

<?php
    foreach($myAssociativeArray as $item){
       /* @var $item ObjectClass */
       Some code here...
    }

Điều này sẽ vượt qua đúng loại gợi ý loại đối tượng đến $ Item. Một lần nữa, nếu bạn sẽ giữ nhiều loại lớp thì giải pháp này sẽ không hoạt động.

Đã trả lời ngày 3 tháng 9 năm 2014 lúc 17:17Sep 3, 2014 at 17:17

Câu hỏi hỗ trợ

Có cách nào để gõ các thành viên mảng liên kết gợi ý không?

Đưa ra mảng sau:

$model = [
  'id' => 123,
  'name' => 'Some name',
];

________ 6/________ 7 cho điều này trông như thế nào? Nếu tôi có một phương thức lấy một mảng như một tham số và chỉ cần thêm @param array $data, tôi sẽ gặp lỗi sau:

Method Model::doSomething() has parameter $data with no value type specified in iterable type array.

Như đã thấy trong đoạn này: https://phpstan.org/r/588f79de-fe0a-4dfd-A21F-D69498D7F601.

Hãy gây tranh cãi: Trong PHP hiện đại, bạn không bao giờ nên gõ một mảng.

Trước khi bạn bắt đầu ném cà chua, hãy nghe tôi nói.

PHP cho phép bạn chỉ định loại tham số chức năng/phương thức hoặc giá trị trả về. Các giá trị trả về này có thể là bất kỳ loại PHP pháp lý nào, bao gồm bất kỳ loại lớp hoặc giao diện nào, các vô hướng khác nhau và một số loại giả lạ mắt như callable

/** 
 * @var string|ObjectClass[]
 */
private $myAssociativeArray;
0.

PHP có một kiểu dữ liệu mà nó gọi

/** 
 * @var string|ObjectClass[]
 */
private $myAssociativeArray;
1, mặc dù nó không thực sự là một mảng như bất kỳ ngôn ngữ nào khác sẽ xác định nó. Nó kết hợp những gì hầu hết các ngôn ngữ sẽ gọi là một vectơ (một chuỗi có độ dài biến) với một từ điển (một danh sách các cặp khóa/giá trị). Do đó, nó thường được sử dụng như một cấu trúc ẩn danh giá rẻ cho dữ liệu phức tạp mà nhà phát triển cảm thấy không đáng để xác định một lớp.

Và bạn hầu như không bao giờ nên sử dụng

/** 
 * @var string|ObjectClass[]
 */
private $myAssociativeArray;
1 như một gợi ý loại. Tại sao? Bởi vì luôn có một lựa chọn tốt hơn, chung chung hơn.

Hãy xem xét ba trường hợp:

Một giá trị phức tạp duy nhất

Đôi khi các mảng PHP được sử dụng như một cấu trúc ẩn danh. Đó là, tôi sẽ tranh luận, luôn luôn sai. Cách tiếp cận tốt hơn là đi trước và xác định một lớp học. Thực sự, trong Php 7 không có lý do chính đáng để không định nghĩa một lớp.

  • Một lớp có hiệu quả gấp đôi bộ nhớ như một mảng.
  • Một lớp cho phép bạn xác định trước các thuộc tính dự kiến ​​của giá trị phức tạp là gì, điều này làm cho nó tự ghi chép hơn.
  • IDE có thể cung cấp tự động hoàn thành cho các thuộc tính bạn đã xác định.
  • Nếu bạn muốn hạn chế quyền truy cập vào một số thuộc tính nhất định, bạn có thể khiến chúng được bảo vệ hoặc riêng tư và chỉ phơi bày các phương thức để truy cập chúng.
  • Nếu bạn muốn thêm hành vi bổ sung cho đối tượng dữ liệu phức tạp đó, bạn chỉ cần thêm nhiều phương thức vào đối tượng.

Lợi thế duy nhất mà một mảng kết hợp có so với một đối tượng là bạn không cần xác định cấu trúc của nó, đó là một vấn đề vì sau đó bạn không nhận được bất kỳ lợi ích tự tài liệu nào mà chúng tôi đã đề cập. Ngay cả một lớp tài sản hoàn toàn công cộng cũng vượt trội so với một mảng kết hợp theo mọi cách.

Nếu bạn đang xác định một lớp, bạn sẽ muốn nhập gợi ý về lớp cho cả hai tham số và loại trả về. Không phải trên một mảng.

Một tập hợp các giá trị phức tạp

Việc sử dụng khác cho các mảng là một chuỗi các giá trị (đặt hàng). Mảng có thể làm việc cho điều đó, nhưng thường thì bạn muốn có một bộ sưu tập có cấu trúc hơn. PHP khá dễ dàng để viết một đối tượng là một tập hợp các đối tượng khác; Bộ sưu tập chỉ cần thực hiện

/** 
 * @var string|ObjectClass[]
 */
private $myAssociativeArray;
3 hoặc
/** 
 * @var string|ObjectClass[]
 */
private $myAssociativeArray;
4 và nó có thể được
/** 
 * @var string|ObjectClass[]
 */
private $myAssociativeArray;
5ed giống như một mảng.

Một đối tượng bộ sưu tập chính thức cũng có thể thực thi, thông qua các gợi ý loại, nó chỉ chứa một loại dữ liệu duy nhất (một số đối tượng khác hoặc một chuỗi, hoặc bất cứ điều gì), cũng như cung cấp các phương thức khác có ý nghĩa cho kiểu dữ liệu đó. Nó cũng có thể cung cấp chất tẩy rửa

/** 
 * @var string|ObjectClass[]
 */
private $myAssociativeArray;
6,
/** 
 * @var string|ObjectClass[]
 */
private $myAssociativeArray;
7,
/** 
 * @var string|ObjectClass[]
 */
private $myAssociativeArray;
8,
/** 
 * @var string|ObjectClass[]
 */
private $myAssociativeArray;
9 và nhiều phương pháp định hướng bộ sưu tập khác.

Tất nhiên, nếu bạn đang sử dụng một đối tượng bộ sưu tập chính thức, bạn sẽ muốn gõ gợi ý chống lại điều đó. Không phải trên một mảng.

Một tập hợp các giá trị đơn giản

Trong thực tế, tất nhiên, hầu hết các trường hợp không cần một đối tượng thu thập chính thức. Họ có cách sử dụng của họ nhưng họ không phải lúc nào cũng cần thiết. Tuy nhiên, nếu bạn chuyển một tập hợp các giá trị được đặt hàng đơn giản cho một thói quen hoặc trả lại một tập hợp các giá trị được đặt hàng đơn giản từ một thói quen ... bạn vẫn không nên nhập gợi ý trên một mảng.

Điều đó không có nghĩa là bạn không nên sử dụng một mảng. Sử dụng một mảng là tốt. Tuy nhiên, khi bạn giao dịch với một bộ, bạn không nên giới hạn người dùng mã khác của mình để tương tác qua các mảng. PHP thực sự có một số loại dữ liệu ____ 15 có khả năng:

  • Mảng
  • Các đối tượng thực hiện
    <?php
        foreach($myAssociativeArray as $item){
           /* @var $item ObjectClass */
           Some code here...
        }
    
    1 (thông qua
    /** 
     * @var string|ObjectClass[]
     */
    private $myAssociativeArray;
    
    3 hoặc
    /** 
     * @var string|ObjectClass[]
     */
    private $myAssociativeArray;
    
    4 hoặc các kiểu con của chúng)
  • Máy phát điện

Từ quan điểm của mã đọc dữ liệu đó và lặp lại nó, nó không thực sự quan trọng. Tất cả đều tương đương, nhưng gợi ý loại

/** 
 * @var string|ObjectClass[]
 */
private $myAssociativeArray;
1 sẽ chỉ cho phép đầu tiên. Một gợi ý loại
<?php
    foreach($myAssociativeArray as $item){
       /* @var $item ObjectClass */
       Some code here...
    }
1 sẽ chỉ cho phép thứ hai và thứ ba. Nếu bạn muốn cho phép cả ba tùy chọn (và bạn làm), bạn cần gõ gợi ý là ____10. Một
/** 
 * @var string|ObjectClass[]
 */
private $myAssociativeArray;
0 sẽ cho phép bất kỳ giá trị ____ 15 có khả năng nào.

Điều đó cho phép người gọi của bạn (cho một tham số) hoặc bạn hoặc ai đó thực hiện giao diện (cho loại trả về) rất nhiều tính linh hoạt. Đôi khi mã chỉ là sạch hơn và dễ đọc hơn nếu được triển khai với trình tạo. Đôi khi bạn thực sự cần khả năng tạo ra sự lười biếng của một người lặp. Nếu bạn nhập gợi ý trên

/** 
 * @var string|ObjectClass[]
 */
private $myAssociativeArray;
1, bạn luôn buộc người dùng khác sử dụng các cấu trúc mã trung tâm mảng, thay vì bất kỳ cấu trúc nào tạo ra mã sạch nhất cho họ. Điều đó rất có thể là một mảng, và điều đó hoàn toàn ổn, nhưng bạn không nên buộc quyết định đó đối với họ.

Vì vậy, nếu bạn muốn một bộ sưu tập chính thức các giá trị loại gợi ý với

/** 
 * @var string|ObjectClass[]
 */
private $myAssociativeArray;
0. Không phải trên một mảng.

Hoạt động mảng

Một cảnh báo đáng tiếc là PHP có một số lượng lớn các chức năng hữu ích hoạt động trên các mảng ... và không phải trên các phép lặp khác. Các hoạt động như

$model = [
  'id' => 123,
  'name' => 'Some name',
];
1,
$model = [
  'id' => 123,
  'name' => 'Some name',
];
2 hoặc
$model = [
  'id' => 123,
  'name' => 'Some name',
];
3 về mặt khái niệm có ý nghĩa đối với bất kỳ sự khác biệt nào nhưng vì chúng có trước các phép lặp không phải trong ngôn ngữ chỉ hoạt động trên các cấu trúc mảng. Nếu chúng ta không chỉ làm một
/** 
 * @var string|ObjectClass[]
 */
private $myAssociativeArray;
5 đơn giản, chúng ta có cần chỉ định một mảng một cách rõ ràng không?

Không thực sự. Các phiên bản thân thiện với các hoạt động đó rất đơn giản để viết. Có một số thư viện PHP hiện tại cung cấp chúng và nhiều thư viện khác trên các đối tượng thu thập hoặc các vòng lặp tùy ý mà bạn có thể tải xuống, nhưng chúng tầm thường để tự viết. Đây là một số phiên bản đơn giản:

function iterable_map(iterable $list, callable $operation) : iterable
{
  foreach ($list as $k => $v) {
    yield $operation($k, $v);
  }
}

function iterable_filter(iterable $list, callable $filter) : iterable 
{
  foreach ($list as $k => $v) {
    if ($filter($v)) {
      yield $k => $v;
    }
  }
}

function iterable_reduce(iterable $list, callable $reducer, $acc)
{
  foreach ($list as $v) {
   $acc = $reducer($acc, $v);
  }
  return $acc;
}

Điều chỉnh khi cần thiết.

Mảng vẫn ổn. Mảng là hữu ích. Mảng không còn là thứ bạn cần gõ gợi ý. Nếu bạn cảm thấy cần phải gõ gợi ý một mảng, hãy coi đó là mùi mã và tự hỏi mình sử dụng trường hợp nào bạn đang xử lý. Bạn muốn một bộ sưu tập hay một cấu trúc? Nhập gợi ý cho những gì bạn thực sự muốn nói. Người dùng của bạn sẽ cảm ơn bạn.