メソッドの宣言は、PHPの親メソッドと互換性がある必要があります


107
厳密な標準:childClass :: customMethod()の宣言は、parentClass :: customMethod()の宣言と互換性がある必要があります

PHPでこのエラーの考えられる原因は何ですか?互換性あるとはどういう意味ですか?


notJimはまさにその通りです。@ waiwai933、function customMethod( ... )各関数のヘッダー(最初の行のみ)を投稿できれば、具体的な問題を知ることができます
nickf

エラーメッセージとPHPコンパイル時の影響に関する詳細:bugs.php.net/bug.php
id=


1
私の問題は、引数が型ヒントされたもののuse Closure;、クラス型の先頭に追加されなかったことでした(型ヒントがだったためClosure)。だから...そのような依存関係がないかどうかを確認してください。
ライアン

回答:


126

childClass::customMethod()とは異なる引数、またはとは異なるアクセスレベル(public / private / protected)がありparentClass::customMethod()ます。


1
おそらくそれは、可視性、メソッド署名がPHPの問題ではないためです
Gabriel Sosa

43
同じ正確な引数のデフォルト値を持つことも重要です。例えば、parentClass::customMethod($thing = false)そしてchildClass::customMethod($thing)子供の方法は、最初の引数のデフォルト値が定義されていないため、エラーが表示されます。
チャールズ

1
可視性は実際には別のエラーだと思います。ちなみに、私のショップではストリクトモードを使用していません。これは、E_ALL、IIRCを使用しているためです。
davidtbernal 2010年

12
これはPHP 5.4で変更されました。btw:* E_ALLは、error_reporting設定ディレクティブにE_STRICTレベルのエラーを含みます。こちらをご覧ください:php.net/manual/en/migration54.other.php
Duncan Lock

1
&引数にアンパサンド()がないと、このエラーも発生する可能性があります。
IvanRF 2014

36

このメッセージは、実行時に失敗する可能性がある特定の可能なメソッド呼び出しがあることを意味します。あなたが持っていると仮定します

class A { public function foo($a = 1) {;}}
class B extends A { public function foo($a) {;}}
function bar(A $a) {$a->foo();}

コンパイラーは、パラメーターを必要としないA :: foo()の要件に対して、呼び出し$ a-> foo()のみをチェックします。ただし、$ aはクラスBのオブジェクトであり、パラメーターを必要とするため、実行時に呼び出しが失敗します。

ただし、これが失敗することはなく、エラーは発生しません

class A { public function foo($a) {;}}
class B extends A { public function foo($a = 1) {;}}
function bar(A $a) {$a->foo();}

したがって、どのメソッドにも、その親メソッドよりも多くの必須パラメーターがある可能性があります。

型ヒントが一致しない場合も同じメッセージが生成されますが、この場合、PHPの方が制限が厳しくなります。これはエラーになります:

class A { public function foo(StdClass $a) {;}}
class B extends A { public function foo($a) {;}}

これもそうです:

class A { public function foo($a) {;}}
class B extends A { public function foo(StdClass $a) {;}}

それは必要以上に制限的だと思われ、私は内部のせいだと思います。

可視性の違いは別のエラーを引き起こしますが、基本的な理由は同じです。親メソッドよりも目立たないメソッドはありません。


2
最後の例では、正当であるため、ここでエラーは発生しません。stdClass$ aは、混合$ aよりも制限的です。これを回避する方法はありますか?この場合、PHPはこれを許可するはずですが、それでもエラーが発生します...
galchen

2
最後の例はタイプセーフなので、確かに「必要以上に制限的」です。それはC ++およびJavaで多型と競合するので、これは、貨物カルトプログラミングの場合であってもよいen.wikipedia.org/wiki/...
Warbo

説明してくれてありがとう、私の場合、あなたが最初に与えた例はまさに私のエラーを引き起こしたものでした。
ビリーノア2018年

どうもありがとうございました。
Eldoïr

22

エラーをオフにすることなくOOPフォームを保持したい場合は、次のこともできます。

class A
{
    public function foo() {
        ;
    }
}
class B extends A
{
    /*instead of : 
    public function foo($a, $b, $c) {*/
    public function foo() {
        list($a, $b, $c) = func_get_args();
        // ...

    }
}

これらのエラーを回避するためにこのハックを使用したいと思います。このアプローチではパフォーマンスが低下するのではないかと心配しています。私はこれを調査しますが、その質問に答えるのに役立つリソースがあれば、それは素晴らしいことです。
Adam Friedman

状況にもよりますが。まだはい、それは少しハックかもしれませんが、それはphpですか?すでに、時にはそれは良い回避策になることがあります、ありがとう!<@
マスタージェームズ

あなたは私の日を救った!これは、php7を搭載したサーバーでレガシーphp5プロジェクトを問題なく起動する唯一のオプションでした
vladkras

このケースでは、デフォルト値の代わりに使用することができますfunc_get_args()で、すなわち、Bpublic function foo($a = null, $b = null, $c = null)これは約束したことで契約を壊さないよう、A
ジェイク、

1

インターフェイスのコンテキストでこのエラーを拡張するために、次のように関数のパラメーターのヒントを入力している場合:

インターフェースA

use Bar;

interface A
{
    public function foo(Bar $b);
}

クラスB

class B implements A
{
    public function foo(Bar $b);
}

useステートメントを実装クラス(クラスB)に含めるのを忘れた場合、メソッドのパラメーターが同じであっても、このエラーが発生します。


0

GitHubから既存のクラスを拡張しようとしたときに、この問題に直面しました。私は自分自身を説明しようと思います。最初はあるべき姿でクラスを書いて、それから今のクラスを書いていきます。

私が何を

namespace mycompany\CutreApi;

use mycompany\CutreApi\ClassOfVendor;

class CutreApi extends \vendor\AwesomeApi\AwesomeApi
{
   public function whatever(): ClassOfVendor
   {
        return new ClassOfVendor();
   }
}

やっとやったこと

namespace mycompany\CutreApi;

use \vendor\AwesomeApi\ClassOfVendor;

class CutreApi extends \vendor\AwesomeApi\AwesomeApi
{
   public function whatever(): ClassOfVendor
   {
        return new \mycompany\CutreApi\ClassOfVendor();
   }
}

このエラーは、名前空間クラスを返すメソッドを使用していて、同じクラスを他の名前空間で返そうとした場合にも発生するようです。幸い私はこの解決策を見つけましたが、php 7.2でこの機能の利点を完全に理解していません。私にとって、入力パラメーターの再定義や、あるいは方法。

以前のアプローチの1つの欠点は、IDEが\ mycompany \ CutreApi \ ClassOfVendor()に実装された新しいメソッドを認識できなかったことです。それで、今のところ、私はこの実装で行きます。

現在行われています

namespace mycompany\CutreApi;

use mycompany\CutreApi\ClassOfVendor;

class CutreApi extends \vendor\AwesomeApi\AwesomeApi
{
   public function getWhatever(): ClassOfVendor
   {
        return new ClassOfVendor();
   }
}

そこで、「whatever」メソッドを使用する代わりに、「getWhatever」という新しいメソッドを作成しました。実際、どちらも同じように動作し、クラスを返すだけですが、前に説明したように、名前空間は異なります。

これが誰かを助けることを願っています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.