web-dev-qa-db-ja.com

PHPで厳密な型は何をしますか?

PHP7でこの新しい行を見たことがありますが、それが何を意味するのか実際には説明していません。私はそれをグーグルで調べましたが、彼らが話しているのは、あなたがそれを有効にするか、投票タイプのものではないかということです。

declare(strict_types = 1);

それは何をするためのものか?コードにどのような影響がありますか?私はそれをすべきですか?いくつかの説明はいいでしょう。

71
sufuko

Treehouse blog から:

PHP 7では、スカラー型が追加されました。具体的には、int、float、string、およびbool。

スカラー型のヒントを追加し、厳密な要件を有効にすることで、より正確で自己文書化のPHPプログラムを作成できることが望まれます。また、コードをより細かく制御できるようになり、コードが読みやすくなります。

デフォルトでは、スカラー型宣言は厳密ではありません。つまり、元の型を変更して、型宣言で指定された型に一致させようとします。つまり、数値で始まる文字列をfloatを必要とする関数に渡すと、数値を最初から取得し、それ以外のすべてを削除します。 intを必要とする関数にfloatを渡すと、int(1)になります。

デフォルトでは、PHPは、可能であれば、間違った型の値を予想されるスカラー型にキャストします。たとえば、文字列を期待するパラメータに整数が与えられた関数は、文字列型の変数を取得します。

厳密なタイプは無効( 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)
  */

ファイルごとにストリクトモードを有効にすることができます。厳格モードでは、型宣言の正確な型の変数のみが受け入れられるか、TypeErrorがスローされます。この規則の唯一の例外は、floatを期待する関数に整数を与えることができるということです。内部関数内からの関数呼び出しは、strict_types宣言の影響を受けません。

厳格モードを有効にするには、declareステートメントをstrict_types宣言とともに使用します。

厳密なタイプが有効( 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

作業例:

<?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 on 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');
81
azjezz

strict_typesは、タイプ強制に影響します。

厳密な型の前は、int $xは「$xはintに対してsimilarを持たなければならないが、必ずしも int固有ではない」ことを意味していました。 int固有に強制できるものはすべて、型ヒントを渡します。

  • int固有(242)、
  • フロート(10.17)、
  • ブール(1)、
  • null、または
  • 先頭に数字がある文字列(13 Ghosts)。

ここで、strict_types=1を設定することで、エンジンにintが「正確かつ適切なintのみ」を意味する必要があることを伝えます。他に何もありません。変換と潜在的な損失なしに、与えられたものだけを正確に取得するという壮大で大きな保証があります。

例:

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

混乱を招く可能性のある結果をもたらします。

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

ほとんどの開発者は、intヒントが「intのみ」を意味することを期待していると思います。しかし、そうではなく、「intのようなもの」を意味します。厳密な型を有効にすると、予想される動作と期待される動作が得られます。

<?php declare(strict_types=1);

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

利回り:

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

型のヒントを使用する場合、ここには2つのレッスンがあると思います。

  • 常にstrict_types=1を使用してください。
  • strict_typesプラグマの追加を忘れた場合に備えて、通知を例外に変換します。
24
bishop