PHPDoc и __callStatic

tl;dr

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

Мотивация

Если вам нужна более широкая картина, вот как я добрался до этого вопроса.

Проблема: в моем текущем проекте у нас есть масса классов, которые на самом деле должны быть синглтонами (прокси-серверы БД и тому подобное). Излишне говорить, что у нас есть как минимум несколько сотен строк 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
 */

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


person abesto    schedule 12.05.2011    source источник


Ответы (2)


Что ж, PhpStorm 3.0 примет

@method static type name() description

См. соответствующий запрос функции http://youtrack.jetbrains.net/issue/WI-4051.

person Alexey Gopachenko    schedule 14.09.2011
comment
Работает и в VS Code. - person pixelarbeit; 26.06.2020

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

Однако в моем тестировании с 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()"
person ashnazg    schedule 12.05.2011
comment
К сожалению, @method прекрасно анализируется и используется обеими IDE, но они предполагают, что эти методы являются динамическими. PHPStorm даже выдает предупреждение о том, что я вызываю нестатический метод статически. - person abesto; 13.05.2011
comment
Похоже, мне придется принять это как ответ «нет, это невозможно». - person abesto; 24.05.2011