主に PhpStorm7 で開発してらっしゃる方が対象です。
ほかの IDE では試していませんが、可能性はあるかもしれません。
ここでの「アノテーション」は、ドキュメントコメントで IDE にメタ情報を提供するための注釈を指しています。Web Application Framework への情報提供ではありません。
また、PSR に準拠しているか否かについては確認しておりませんのでご了承ください。
遅延静的束縛の static はアノテーションでも使える
たとえば、DB からとある Model(Entity) を取得する共通メソッドが親クラスで定義されていたとします。
class Model {
/*
* モデル取得メソッド
*
* @param array|string|integer $parameters
* @return Model
*/
public static function findFirst($parameters=null) { }
}
これを継承して具象クラスを定義すると...
基底クラスで定義されている findFirst
の戻り値は Model
なので、最後の一文 $entry->date
で Model
にプロパティ $date
が定義されていない旨の警告が表示されます。
(実際には magic method としてアクセスされるよというメッセージです)
つまり、 $entry
は Entry
クラスのインスタンスとして扱いたい場面なのに、 Model
クラスのインスタンスとして認識されてしまう、ということです。
そこで、 Model::findFirst
のアノテーションを次のように修正します。
class Model {
/*
* モデル取得メソッド
*
* @param array|string|integer $parameters
* @return static
*/
public static function findFirst($parameters=null) { }
}
@return
に続く型注釈を Model
ではなく static
に変更しました。
これで警告は解除され、呼び出し元である Entry
クラスのインスタンスとして認識されました。
例ではクラスのフィールドを参照しましたが、例えばせっかくメソッドチェーンを繋げられるように setter メソッドで $this
を返却していても、具象クラスのインスタンスとして認識されなければ警告だらけになるわ入力補完が効かないわで残念な気持ちになりますよね。
返却されるインスタンスが具象クラスのものとなることがわかっている場合、アノテーションに static を指定するとそんなこともなくなります。
遅延静的束縛(static) について詳しいことは 公式マニュアル:遅延静的束縛 をご参照ください。
Phalcon でのお話
PhpStorm + Phalcon で開発されている方はもうお気づきかとは思いますが、上記の例をそのまま Phalcon の ドキュメントライブラリ に当てはめることで開発を加速できます。
ide/1.2.5/Phalcon/Mvc/Model.php#L388
<?php
namespace Phalcon\Mvc {
abstract class Model implements \Phalcon\Mvc\ModelInterface, \Phalcon\Mvc\Model\ResultInterface, \Phalcon\DI\InjectionAwareInterface, \Serializable {
/* 省略 */
/**
* Allows to query a set of records that match the specified conditions
*
* <code>
*
* //How many robots are there?
* $robots = Robots::find();
* echo "There are ", count($robots), "\n";
*
* //How many mechanical robots are there?
* $robots = Robots::find("type='mechanical'");
* echo "There are ", count($robots), "\n";
*
* //Get and print virtual robots ordered by name
* $robots = Robots::find(array("type='virtual'", "order" => "name"));
* foreach ($robots as $robot) {
* echo $robot->name, "\n";
* }
*
* //Get first 100 virtual robots ordered by name
* $robots = Robots::find(array("type='virtual'", "order" => "name", "limit" => 100));
* foreach ($robots as $robot) {
* echo $robot->name, "\n";
* }
* </code>
*
* @param array|string $parameters
* ...配列だけじゃなく文字列も渡せるので修正
* @return \Phalcon\Mvc\Model\ResultsetInterface|static[]
* ...static[] を追加して具象クラスの配列として認識させる
*/
public static function find($parameters=null){ }
/**
* Allows to query the first record that match the specified conditions
*
* <code>
*
* //What's the first robot in robots table?
* $robot = Robots::findFirst();
* echo "The robot name is ", $robot->name;
*
* //What's the first mechanical robot in robots table?
* $robot = Robots::findFirst("type='mechanical'");
* echo "The first mechanical robot name is ", $robot->name;
*
* //Get first virtual robot ordered by name
* $robot = Robots::findFirst(array("type='virtual'", "order" => "name"));
* echo "The first virtual robot name is ", $robot->name;
*
* </code>
*
* @param array|string|integer $parameters
* ...文字列も、実は数値(主キー値)も渡せる
* @return static
* ...こちらも同様に具象クラスのインスタンスとして認識させる
*/
public static function findFirst($parameters=null){ }
/* 省略 */
}
}
上記のように、アノテーションを4行書き換えます。
これに気づくまでは具象クラス側で find
findFirst
をオーバライドしてアノテーションを振り当てていましたが、これでその必要もなくなりました!
ふと Pull Request を送ろうかとも思ったのですが、Phalcon 全体としてのコーディングスタイルや PSR との衝突も考えられるので、あくまで個人的に調整する範囲であると考えこちらに投稿いたしました。