Các loại nghiêm ngặt làm gì trong PHP?


147

Tôi đã thấy dòng mới sau đây trong PHP 7, nhưng không ai thực sự giải thích ý nghĩa của nó. Tôi đã googled nó và tất cả những gì họ nói là bạn sẽ kích hoạt nó hay không giống như một loại thăm dò ý kiến.

declare(strict_types = 1);

Nó làm gì? Nó ảnh hưởng đến mã của tôi như thế nào? Tôi có nên làm điều đó?

Một số lời giải thích sẽ tốt đẹp.



5
.take một cái nhìn lúc này quá php.net/manual/en/... cho strict_types thị
scaisEdge

Câu trả lời:


153

Từ blog của Treehouse :

Với PHP 7, chúng ta đã thêm các kiểu vô hướng. Cụ thể: int, float, chuỗi và bool.

Bằng cách thêm các gợi ý kiểu vô hướng và cho phép các yêu cầu nghiêm ngặt, hy vọng rằng các chương trình PHP tự viết chính xác và chính xác hơn có thể được viết. Nó cũng cho phép bạn kiểm soát nhiều hơn mã của mình và có thể làm cho mã dễ đọc hơn.

Theo mặc định, khai báo kiểu vô hướng là không nghiêm ngặt, có nghĩa là chúng sẽ cố gắng thay đổi loại ban đầu để phù hợp với loại được chỉ định bởi khai báo kiểu. Nói cách khác, nếu bạn chuyển một chuỗi bắt đầu bằng một số vào một hàm yêu cầu float, nó sẽ lấy số đó ngay từ đầu và loại bỏ mọi thứ khác. Truyền một float vào một hàm yêu cầu int sẽ trở thành int (1).

Theo mặc định, PHP sẽ chuyển các giá trị của loại sai thành loại vô hướng dự kiến ​​nếu có thể. Ví dụ, một hàm được cung cấp một số nguyên cho một tham số dự kiến ​​một chuỗi sẽ nhận được một biến kiểu chuỗi.

Các loại nghiêm ngặt bị vô hiệu hóa ( eval ):

<?php

  function AddIntAndFloat(int $a, float $b) : int
  {
      return $a + $b;
  }

  echo AddIntAndFloat(1.4, '2');
  /*
  * without strict typing, PHP will change float(1.4) to int(1)
  * and string('2') to float(2.0) and returns int(3)
  */

Có thể kích hoạt chế độ nghiêm ngặt trên cơ sở mỗi tệp. Trong chế độ nghiêm ngặt, chỉ một biến có kiểu khai báo chính xác sẽ được chấp nhận hoặc TypeError sẽ được ném. Ngoại lệ duy nhất cho quy tắc này là một số nguyên có thể được trao cho một hàm mong đợi một số float. Các lệnh gọi hàm từ bên trong các hàm bên trong sẽ không bị ảnh hưởng bởi khai báorict_types.

Để bật chế độ nghiêm ngặt, câu lệnh khai báo được sử dụng với khai báorict_types:

Các loại nghiêm ngặt được kích hoạt ( eval ):

<?php declare(strict_types=1);

  function AddIntAndFloat(int $a, float $b): int
  {
      return (string) $a + $b;
  }

  echo AddIntAndFloat(1.4,'2');
  // Fatal error: Uncaught TypeError: Argument 1 passed to AddIntAndFloat() must be of the type int, float given
  echo AddIntAndFloat(1,'2');
  // Fatal error: Uncaught TypeError: Argument 2 passed to AddIntAndFloat() must be of the type float, string given

  // Integers can be passed as float-points :
  echo AddIntAndFloat(1,1);
  // Fatal error: Uncaught TypeError: Return value of AddIntAndFloat() must be of the type integer, string returned

Ví dụ làm việc:

<?php

declare(strict_types=1);

function AddFloats(float $a, float $b) : float
{
    return $a+$b;
}

$float = AddFloats(1.5,2.0); // Returns 3.5

function AddFloatsReturnInt(float $a, float $b) : int
{
    return (int) $a+$b;
}

$int = AddFloatsReturnInt($float,1.5); // Returns 5

function Say(string $message): void // As in PHP 7.2
{
    echo $message;
}

Say('Hello, World!'); // Prints "Hello, World!"

function ArrayToStdClass(array $array): stdClass
{
    return (object) $array;
}

$object = ArrayToStdClass(['name' => 'azjezz','age' => 100]); // returns an stdClass

function StdClassToArray(stdClass $object): array
{
    return (array) $object;
}

$array = StdClassToArray($object); // Returns array

function ArrayToObject(array $array): object // As of PHP 7.2
{
    return new ArrayObject($array);
}

function ObjectToArray(ArrayObject $object): array
{
    return $object->getArrayCopy();
}

var_dump( ObjectToArray( ArrayToObject( [1 => 'a' ] ) ) ); // array(1 => 'a');

3
Lỗi nghiêm trọng đầu tiên được đề cập trong ví dụ về loại nghiêm ngặt của bạn là sai. Như đã đề cập trong tài liệu: "Ngoại lệ duy nhất cho quy tắc này là một số nguyên có thể được trao cho một hàm mong đợi một số float." Cuộc gọi chức năng sẽ không thất bại trên int. Nó sẽ trên chuỗi mặc dù.
Paul

63

strict_types ảnh hưởng đến sự ép buộc kiểu.

Sử dụng gợi ý loại mà không strict_typescó thể dẫn đến lỗi tinh tế.

Trước các loại nghiêm ngặt, int $xcó nghĩa là " $xphải có giá trị cưỡng chế đối với một int." Bất kỳ giá trị nào có thể bị ép buộc intsẽ vượt qua gợi ý loại, bao gồm:

  • một int thích hợp ( 242),
  • một cái phao ( 10.17),
  • một bool ( true),
  • null, hoặc là
  • một chuỗi có các chữ số hàng đầu ( "13 Ghosts").

Bằng cách cài đặt strict_types=1, bạn nói với công cụ int $xcó nghĩa là "$ x chỉ phải là một int đúng, không cho phép ép buộc kiểu". Bạn có sự đảm bảo tuyệt vời rằng bạn sẽ nhận được chính xác và chỉ những gì đã được đưa ra, mà không có bất kỳ chuyển đổi và tổn thất tiềm năng nào.

Thí dụ:

<?php
function get_quantity(): int {
    return '100 apples';
}
echo get_quantity() . PHP_EOL;

Mang lại một kết quả có thể gây nhầm lẫn:

Notice: A non well formed numeric value encountered in /Users/bishop/tmp/pmkr-994/junk.php on line 4
100

Hầu hết các nhà phát triển đều mong đợi, tôi nghĩ, một intgợi ý có nghĩa là "chỉ một int". Nhưng nó không, nó có nghĩa là "bất cứ điều gì như một int". Việc kích hoạtrict_types mang lại hành vi mong muốn và mong muốn:

<?php declare(strict_types=1);

function get_quantity(): int {
    return '100 apples';
}
echo get_quantity() . PHP_EOL;

Sản lượng:

Fatal error: Uncaught TypeError: Return value of get_quantity() must be of the type int, string returned in example.php:4

Tôi nghĩ có hai bài học ở đây, nếu bạn sử dụng gợi ý loại:

  • Sử dụng strict_types=1, luôn luôn.
  • Chuyển đổi các thông báo thành ngoại lệ, trong trường hợp bạn quên thêm strict_typespragma.

1
Điều này đã được trả lời tốt như gần một năm trước;)
emix 14/12/18

6
Thật vậy, tôi đã bỏ phiếu cho câu trả lời khác @emix. Tuy nhiên, tôi cảm thấy câu hỏi "tôi có nên làm điều đó không". Tôi cũng cảm thấy một ví dụ nhỏ gọn và gây sốc hơn sẽ khuyến khích mọi người sử dụng strict_types.
giám mục

1
Tôi nghĩ rằng câu hỏi này ngắn gọn giải quyết "Tôi có nên làm điều đó?" một phần câu hỏi của OP. Trở lại PHP sau một thời gian gián đoạn và điều này rất hữu ích.
Darragh Enright
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.