Cómo documentar métodos mágicos (_call y _callStatic) para IDE

81

Después de muchos años felices codificando en notepad ++ y sublime, me recomendaron probar un IDE de PHP. Estoy probando phpStorm y parece agradable. La finalización del código y la documentación es una gran característica, pero no me funciona cuando se utilizan métodos mágicos. ¿Existe una solución alternativa para que phpStorm comprenda lo que está sucediendo con los métodos mágicos?

Nuestra situación es algo como esto:

abstract class a {
    public static function __callStatic($method,$args)
    {
        if(strpos($method,"get_by_") === 0)
        {
            //do stuff
        } elseif(strpos($method,"get_first_by_") === 0) {
            //do stuff
        } elseif($method == "get_all") {
            //do stuff
        }
    }
}

class b extends a {
    // some more stuff
}

b::get_by_user_id(27);
b::get_first_by_id(156);
b::get_all();

El método mágico callStatic nos permite obtener una colección de objetos a través de 1 o más argumentos que componen la llamada a la función.

Veo que hay una declaración @method para usar en estos casos, pero phpStorm solo está recogiendo la primera de estas declaraciones. Además, solo puedo configurar el tipo de retorno en mixto, ya que preferiría poder configurarlo como cualquier clase a la que se haya llamado (b en mi ejemplo).

Cualquier idea o sugerencia será bien recibida, gracias.

Rob Forrest
fuente
1
¿POR QUÉ PENSARÍA ALGUIEN QUE ANULAR _callES UNA BUENA IDEA? !!
Brian Gordon
Tengo que decir que hizo +1 en el comentario de Brian en caso de que alguna persona en su sano juicio encontrara esta pregunta. Los métodos mágicos son para todos los efectos: indocumentables (intente documentar un [parámetro | condición previa | postcondición | excepción] a un método mágico), no compatibles con IDE (intente depurar un método mágico), resistentes a la refactorización (por favor, ni siquiera considere intentar refactorizar un método mágico en una pieza de software titular) y LAZY (vale, el último podría interpretarse como una opinión).
Luke A. Leber
17
-1 a la opinión en el comentario de @ LukeA.Leber ya que evidencia falta de visión. Si bien los métodos mágicos no son una forma de escribir menos código (si los usa para ser perezoso), los métodos mágicos hacen posibles arquitecturas que de otra manera simples no serían posibles o que serían tan escandalosamente complejas que no valdría la pena escribirlas. Y son completamente compatibles con IDE cuando se usa PHPDoc. Tenga en cuenta que la mayoría de las veces no necesita métodos mágicos, pero cuando los necesita no hay sustituto (en PHP). Cuando se usan de una manera muy estructurada, usarlos es una solución válida completa.
MikeSchinkel
5
No crea que anular __calles una mala idea. Se trata de implementación. La implementación que se muestra en la pregunta anterior definitivamente no sería la mejor manera, pero para las API con capacidad de cadena, permite mucha flexibilidad.
Steve Bauman

Respuestas:

144

Use el comentario PHPDoc de nivel de clase, específicamente la etiqueta @method , funciona bien en PhpStorm:

/**
 * @method static someClass get_by_user_id(int $id) Bla-bla
 * @method static someClass get_first_by_id(int $id) 
 */
abstract class a {
...

En lo anterior:

  • @method - Etiqueta PHPDoc
  • static - dice que este es un método estático
  • someClasso $this- tipo de retorno
  • get_by_user_id - nombre del método
  • (int $id) - firma del método: ([[type] [parameter]<, ...>])
  • Bla-bla - alguna descripción opcional

Más sobre @method:

PD Si @method staticbien funciona bien en PhpStorm (le dice al IDE que el método es estático) puede que no sea (¿todavía?) Compatible con la herramienta phpDocumentor real (lo siento, no lo he usado por un tiempo).


Alternativamente : (en PhpStorm, por supuesto) Settings | Inspections | PHP | Undefined | Undefined method --> Downgrade severity if __magic methods are present in class- no ayudará a completar el código para dichos métodos de ninguna manera, pero no marcará esos métodos mágicos como errores de "método indefinido".


Ticket de phpDocumentor con respecto al uso de RegEx / nombres parciales para @property/ @methodetiquetas (cómo puede ser útil para la documentación y qué poca ayuda puede aportar al IDE real cuando se trata de completar el código):

LazyOne
fuente
2
Gracias, esto parece una sugerencia razonable y ciertamente funciona en phpStorm, pero me detesta un poco escribir los potencialmente cientos de líneas de @method en la parte superior de cada clase. Verá que el método get_by_ * puede ser precedido por cualquiera de los parámetros de los objetos para obtener objetos de ese tipo por el parámetro especificado. Incluso excluyendo la posibilidad de get_by_ _AND_ que terminaría siendo, con alrededor de 1500 @methodsa través de 140 clases diferentes. ¿No existe una forma más genérica de proporcionar documentación?
Rob Forrest
No. Todos los métodos mágicos deben declararse específicamente (ese es el punto principal de documentar de esta manera) - PHPDoc no comprende nombres parciales (por ejemplo get_by_*(int $id)). Para IDE (inspección de código, no finalización), tiene una solución alternativa (deshabilite las advertencias). Para phpDocumentor (o herramienta alternativa): no conozco ninguna solución (tal vez esté ahí, pero no la conozco). Tiene el enlace a github - archivar un nuevo ticket y pedir que se agreguen estas funciones de coincidencia de "nombres parciales" - vea lo que dirán (lo más probable es que sea rechazado). Si se implementará, entonces IDE también puede tenerlo más adelante.
LazyOne
github.com/phpDocumentor/phpDocumentor2/issues - pero compruebe si no existe un ticket similar antes de publicar el suyo.
LazyOne
Gracias por todo eso. Actualmente hay un boleto abierto con respecto a esto, pero todo parece haberse quedado en silencio. He metido un comentario allí y veremos qué sale de él.
Rob Forrest
2
Solo como referencia, el ticket de phpDocumentor (para que otros usuarios sepan de qué ticket estás hablando; también lo agregaron a la respuesta): github.com/phpDocumentor/phpDocumentor2/issues/689
LazyOne
4

Algo relacionado con la pregunta original:

También puede definir esto en el archivo meta phpstorm. Aquí hay un ejemplo para el método de fábrica (v2016.3):

// Define in .phpstorm.meta.php
namespace PHPSTORM_META {
    $STATIC_METHOD_TYPES = [
        \Factory::create('') => [],
    ];
}

// Then use in code
$factory = new \Factory();
$user = $factory->create(\User::class);
// Here you get autocomplete.
$user->subscribe();

De esta manera, no tienes que bloquear todas las posibilidades cuando ocurre la magia.

Tenga algunos documentos para obtener más detalles.

Yauheni Prakopchyk
fuente
Esto no funciona con __call. Tampoco es PHP documentado y no válido. PHPStorm solo brinda soporte para aquellos casos en los que haya métodos definidos estáticamente que devuelvan una mezcla de tipos según la entrada.
jgmjgm