PHP 7より前の「文字列のインスタンスでなければならず、文字列が指定されている」を解決するにはどうすればよいですか?


217

これが私のコードです:

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

これはこのエラーになります:

キャッチ可能な致命的なエラー:phpwtf()に渡される引数1は文字列のインスタンスでなければなりません

PHPが目的のタイプを同じように認識し、拒否するのを見るのは、少しオーウェル派以上です。5つのライトがあります。

PHPの文字列の型ヒントに相当するものは何ですか?ここで何が起こっているのかを正確に説明する答えに対するボーナス検討。


5
まあ、それはあなたが間違っているからです。そもそも、あなたのコードは機能しないはずです。PHPのドキュメントで型ジャグリングについて読んでください。PHPは動的型付けと弱い型付けです。(文字列)を使用して引数を文字列にキャストできます(ただし、関数本体のみ)。ただし、コードスニペットで行うように、オブジェクトと配列のみをヒントできます。
Richard Knop

7
問題は、あなたが小さな間違いを犯したことです。4つのライトがあります。
CJデニス

@ Gordon、5.6でテストしました。まだ運がない。
Pacerier、2015

@Pacerier 最新の開発については、wiki.php.net / rfcをフォローしてください。
Gordon

3
どうやら、スカラー型ヒンティングは(OPが直感的に上記のものになると予想される)最終的に従った* 7 * PHP用のRFCの下で承認されたソース。承認されたRFCは明らかに、パラメータ(引数)だけでなく、戻り値の型チェックのための構文シュガーも提供します。久しぶりです。
SeldomNeedy、2015年

回答:


204

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

手動で「タイプヒント」スカラー型のみを指定できます。

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

1
@deceze、逆型ヒントの構文はありますか?例えば配列以外のもの。
Pacerier、2015

@Pacerierいいえ、ありません。
だます

4
この回答はPHP 7では無効です
Jose Nobile

24

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以降)

警告

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

<?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はクラス名「文字列」を見つけようとしますが、プリミティブ型であるため検索できず、この厄介なエラーで失敗します。


8

PHPでは、クラスを指定してオブジェクトを指定する「ヒント」を使用できます。PHPマニュアルによると、「型ヒントはオブジェクトと配列(PHP 5.1以降)型のみです。intとstringを使用した従来の型ヒントはサポートされていません。」「string」を選択したため、エラーは紛らわしい-「myClass」をその場所に置くと、エラーは別の方法で読み取られます。


3

他の人がすでに述べたように、型ヒントは現在、オブジェクト型に対してのみ機能します。しかし、あなたが引き起こした特定のエラーは、次の文字列型SplStringの準備にあるかもしれないと思います。

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


2

これらのタイプが利用可能になりましたので、PHP 7.0のようなタイプの宣言は、スカラー型を許可:selfarraycallableboolfloatintstring。最初の3つはPHP 5で利用可能でしたが、最後の4つはPHP 7で新しく追加されました。それ以外のもの(integerまたはなどboolean)を使用すると、クラス名として解釈されます。

詳細については、PHPのマニュアルを参照してください


0

安全ではないかもしれませんが、必要な場合:

class string
{
    private $Text;
    public function __construct($value)
    {
        $this->Text = $value;
    }

    public function __toString()
    {
        return $this->Text;
    }
}

function Test123(string $s)
{
    echo $s;
}

Test123(new string("Testing"));

5
私はまだ作成できますnew string(array(1,2,3))
ジミーT.

0

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

数時間後、私は問題を発見しました:静的関数内から$ thisを使用していました。


Using $this when not in object context確かに不可解なメッセージです。
ベンフランセン2017年

0

(もともと彼の質問でleepowersによって投稿されました)

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

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

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

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

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

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-プリミティブ文字列?いいえ-文字列インスタンス?はい

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


-1

私は知っているようにブロック内のphpの型キャスト、PHPの文字列はオブジェクトではないと思います:

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

2
関数にis_string()検証を追加して、関数に他の値が渡されないようにすることができます。
subosito 2010年

1
(string) $s$s文字列にキャストできないオブジェクト(__toString()メソッドが実装されていない)の場合、エラーがスローされる可能性があるため、それほど簡単ではありません
Yanick Rochon

はい、Yanickのとおりです。しかし、すべての入力を文字列に強制することはできませんか?だから例外が出てきます。検証の種類を組み合わせて、残りの例外をキャッチできます;)
subosito 2010年

変数をキャストできるかどうかを最初にチェックせずに一部の変数を文字列にキャストすることは避けなければならないことを言っているだけです。主に例外のキャッチはコストがかかり、悪いデザインパターン/コーディングの習慣につながるからです。
Yanick Rochon、2010年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.