Подтвердить что ты не робот

PHPDoc и __callStatic

TL;DR

Каков правильный способ аннотировать (в PHPDoc) функции, реализованные через __callStatic? Более важно: есть ли способ, который сделает NetBeans и PHPStorm понятными, что это статические методы?

Мотивация

Если вы хотите увеличить картинку, вот как я добрался до этого вопроса.

Проблема. В моем текущем проекте у нас есть тонна классов, которые должны быть действительно одиночными (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
 */

Создание абстрактного класса не имеет значения. Примерно через час Google'ы не нашли решения. Основная цель - информировать IDE об этих функциях; наличие правильного PHPDoc на самом деле не является необходимостью.

4b9b3361

Ответ 2

Вообще говоря, я считаю, что выбор использования магического материала связан с необходимостью принять компромисс с потерей эффективности таких вещей, как автозаполнение.

Однако в моем тестировании с Eclipse PDT (Helios с PHP 5.3.2 на WinXP) мне удалось получить хорошие автозаполнения из одного явного статического метода и двух волшебных статических методов из моего класса Loader, которые я смоделировал после вашего примера.

Короче говоря, кажется, что использование тега @method в классе docblock было достаточно для того, чтобы 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()"