20

tl;dr

を介して実装された関数に (PHPDoc で) 注釈を付ける正しい方法は何__callStaticですか? さらに重要: NetBeansPHPStorm にこれらが静的メソッドであることを理解させる方法はありますか?

動機

全体像が必要な場合は、この質問にたどり着いた方法を次に示します。

問題: 現在のプロジェクトでは、実際にはシングルトン (DB プロキシなど) である必要があるクラスが大量にあります。言うまでもなく、少なくとも数百行はrequire_onceあり$foo = new FooProxy();ます。

解決策:魔法のメソッドLoaderを使用して、これを解決するクラスを作成した__callStaticので、単に$foo = Loader::FooProxy();. 私たちの目的には完璧ですが、

問題: この方法では、チームで使用されるいずれの IDE にも明らかに型ヒントがありません。

解決策: すべてのモジュールは のサブクラスを定義し、Loader単に にルーティングするメソッドを追加し__callStaticます。

問題: オートコンプリートのためだけに、実際に解釈されたコードを追加することは受け入れられません (これは議論の余地がありますが、とりあえず受け入れましょう)。

解決策: 実際のメソッドを追加せず、次のように PHPDoc でメソッドを宣言するだけにしましょう。

<?php
/**
 * @method FooProxy FooProxy()
 */
 class BarLoader extends Loader {}
?>

問題:FooProxy静的メソッドではありません。次のいずれも静的にしません。

<?php
/**
 * @static
 * @method FooProxy FooProxy()
 */

///////////////

/**
 * @static @method A A()
 * @method static A A()
 * @method A static A()
 * @method A A() static
 */

クラスを抽象化しても違いはありません。約 1 時間の Google'ing では解決策が見つかりませんでした。主な目標は、IDE にこれらの機能を認識させることです。正しい PHPDoc を用意する必要はありません。

4

2 に答える 2

37

まあ、PhpStorm 3.0は受け入れます

@method static type name() description

関連する機能リクエストを参照してくださいhttp://youtrack.jetbrains.net/issue/WI-4051

于 2011-09-14T11:51:11.603 に答える
1

一般的に言えば、魔法のようなものを使用するという選択には、オートコンプリートなどの効果を失うというトレードオフを受け入れる必要があるという警告が伴うと思います。

ただし、Eclipse PDT (WinXP で PHP 5.3.2 を使用する Helios) を使用したテストでは、例に基づいてモデル化した Loader クラスから 1 つの明示的な静的メソッドと 2 つの魔法の静的メソッドから適切なオートコンプリートを取得できました。

つまり、クラス docblock で @method タグを使用するだけで、Eclipse が問題を解決するのに十分だったようです。NetBeans と PHPStorm に問題がある場合、それが「静的」な側面に関連しているかどうかはわかりません...そのような動的コードの解析は、自動補完ロジックが処理するように構築されている以上のものである可能性があります。

<?php
/**
 * @method BarProxy BarProxy() returns an instance of BarProxy
 * @method BazProxy BazProxy() returns an instance of BazProxy
 */
class Loader
{
    public static function __callStatic($name, $arguments)
    {
        return new $name($arguments);
    }

    /**
     * @return FooProxy
     */
    public static function FooProxy(){
        return new FooProxy();
    }
}

class FooProxy
{
    public function sayCheese() {}
}

class BarProxy
{
    public function eatFries() {}
}

class BazProxy
{
    public function sleep() {}
}

$foo = Loader::FooProxy();
$foo->sayCheese(); // did this simply to verify explicit autocompletion succeeded

$bar = Loader::BarProxy();
$bar->eatFries();  // autocompletion of just "$bar->" brought up "eatFries()"

$baz = Loader::BazProxy();
$baz->sleep();     // autocompletion of just "$baz->" brought up "sleep()"
于 2011-05-12T21:52:21.760 に答える