web-dev-qa-db-ja.com

PHP 7より前の「文字列のインスタンスでなければならない」の解決方法は?

ここに私のコードがあります:

function phpwtf(string $s) {
    echo "$s\n";
}
phpwtf("Type hinting is da bomb");

その結果、このエラーが発生します。

キャッチ可能な致命的エラー:phpwtf()に渡される引数1は、文字列のインスタンスである必要があります。

PHPが同じタイプの呼吸で目的のタイプを認識して拒否するのを見るのは、ほんの少しのオーウェル派以上です。 5つのライトがあります。気をつけてください

PHPの文字列のタイプヒントと同等のものは何ですか?ここで何が起こっているかを正確に説明する回答に対するボーナスの考慮。

206
leepowers

PHP 7より前 type hinting は、オブジェクトと配列のタイプを強制するためにのみ使用できます。スカラー型は型ヒント可能ではありません。この場合、クラスstringのオブジェクトが必要ですが、(スカラー)stringを指定しています。エラーメッセージはおかしいかもしれませんが、そもそも機能するはずはありません。動的型付けシステムを考えると、これは実際にはある種の異常な意味をなします。

manually「タイプヒント」スカラータイプのみ:

function foo($string) {
    if (!is_string($string)) {
        trigger_error('No, you fool!');
        return;
    }
    ...
}
190
deceze

PHPのマニュアル から:

タイプヒントは、オブジェクトと配列(PHP 5.1以降)タイプのみです。 intおよびstringを使用した従来のタイプヒンティングはサポートされていません。

あなたはそれを持っています。エラーメッセージはあまり役に立たないが、それを提供する。

** 2017編集**

PHP7ではより多くの関数データ型宣言が導入され、前述のリンクは 関数の引数:型宣言 に移動しました。そのページから:

有効なタイプ

  • クラス/インターフェース名:パラメーターは、指定されたクラスまたはインターフェース名のインスタンスでなければなりません。 (PHP 5.0.0以降)
  • self:パラメーターは、メソッドが定義されているクラスと同じクラスのインスタンスでなければなりません。これは、クラスおよびインスタンスメソッドでのみ使用できます。 (PHP 5.0.0以降)
  • array:パラメーターは配列でなければなりません。 (PHP 5.1.0以降)callableパラメーターは有効なcallableでなければなりません。 PHP 5.4.0
  • bool:パラメーターはブール値でなければなりません。 (PHP 7.0.0以降)
  • float:パラメーターは浮動小数点数でなければなりません。 (PHP 7.0.0以降)
  • int:パラメーターは整数でなければなりません。 (PHP 7.0.0以降)
  • string:パラメーターは文字列でなければなりません。 (PHP 7.0.0以降)
  • iterable:パラメーターは、配列またはTraversableのインスタンスのいずれかでなければなりません。 (PHP 7.1.0以降)

警告

上記のスカラー型のエイリアスはサポートされていません。代わりに、クラス名またはインターフェイス名として扱われます。たとえば、ブール値をパラメーターまたは戻り値の型として使用するには、bool型ではなく、クラスまたはインターフェイスのブール値のインスタンスである引数または戻り値が必要です。

<?php
   function test(boolean $param) {}
   test(true);
 ?>

上記の例は次を出力します:

 Fatal error: Uncaught TypeError: Argument 1 passed to test() must be an instance of boolean, boolean given, called in - on line 1 and defined in -:1

最後の警告は、「引数は型文字列でなければなりません」というエラーを理解するために実際に重要です。ほとんどの場合、クラス/インターフェイス名のみが引数の型として許可されているため、PHPはクラス名「string」を見つけようとしますが、プリミティブ型であるため見つからないため、この厄介なエラーで失敗します。

21
Yanick Rochon

PHPでは、オブジェクトを指定するクラスを提供する「ヒント」を使用できます。 PHPマニュアルによると、「タイプヒントはオブジェクトと配列(PHP 5.1以降)タイプのみです。intと文字列を使用した従来のタイプヒントはサポートされていません。」 「文字列」を選択したため、エラーはわかりにくいです-「myClass」をその場所に配置すると、エラーの読み方が異なります。「phpwtf()に渡される引数1は、myClassのインスタンスでなければなりません。」

8
Surreal Dreams

他の人がすでに述べたように、現在、タイプヒンティングはオブジェクトタイプに対してのみ機能します。しかし、トリガーした特定のエラーは、今後の文字列タイプ SplString の準備にある可能性があると思います。

理論的には、文字列のように動作しますが、オブジェクトであるため、オブジェクトタイプの検証に合格します。残念ながら、PHP 5.3ではまだ5.4ではないかもしれないので、これをテストしていません。

3
mario

Laravel ControllerからPHPファイルに関数を呼び出すと、このエラーが発生しました。

数時間後、問題が見つかりました。静的関数内から$ thisを使用していました。

0
ecairol

(元々 leepowers が彼の質問で投稿)

エラーメッセージは、1つの大きな理由で混乱を招きます。

プリミティブ型の名前はPHPでは予約されていません

以下はすべて有効なクラス宣言です。

class string { }
class int { }
class float { }
class double { }

私の間違いは、エラーメッセージが文字列プリミティブ型のみを参照していると考えることでした。Wordの「インスタンス」は一時停止するはずでした。さらに説明するための例:

class string { }
$n = 1234;
$s1 = (string)$n;
$s2 = new string();
$a = array('no', 'yes');
printf("\$s1 - primitive string? %s - string instance? %s\n",
        $a[is_string($s1)], $a[is_a($s1, 'string')]);
printf("\$s2 - primitive string? %s - string instance? %s\n",
        $a[is_string($s2)], $a[is_a($s2, 'string')]);

出力:

$ s1-プリミティブ文字列?はい-文字列インスタンス?番号

$ s2-プリミティブ文字列? no-文字列インスタンス?はい

PHPでは、実際にstringである場合を除き、stringstringにすることができます。暗黙的な型変換を使用する他の言語と同様に、コンテキストがすべてです。

0
vaxquis