algún usuario
Estoy tratando de averiguar si es posible usar PHPdoc para definir las propiedades del objeto que devuelve una función o un método de objeto.
Digamos que tengo la siguiente clase:
class SomeClass {
public function staffDetails($id){
$object = new stdClass();
$object->type = "person";
$object->name = "dave";
$object->age = "46";
return $object;
}
}
Ahora, es bastante fácil definir parámetros de entrada.
/**
* Get Staff Member Details
*
* @param string $id staff id number
*
* @return object
*/
class SomeClass {
public function staffDetails($id){
$object = new stdClass();
$object->type = "person";
$object->name = "dave";
$object->age = "46";
return $object;
}
}
La pregunta es si existe algo similar para definir las propiedades del objeto de salida (de un stdClass) devuelto por el método en cuestión. ¿Para que otro programador no tenga que abrir esta clase y buscar manualmente en el método para ver qué está devolviendo el objeto de retorno?
jeremy harris
Aquí está 4 años después, y todavía no parece haber una forma de anotar las propiedades de un objeto stdClass como se describe originalmente en su pregunta.
Se habían propuesto colecciones en PSR-5, pero eso parece haber sido derribado: https://github.com/php-fig/fig-standards/blob/211063eed7f4d9b4514b728d7b1810d9b3379dd1/proposed/phpdoc.md#colecciones
Parece que solo hay dos opciones disponibles:
Opción 1:
Cree una clase normal que represente su objeto de datos y anote las propiedades.
class MyData
{
/**
* This is the name attribute.
* @var string
*/
public $name;
/**
* This is the age attribute.
* @var integer
*/
public $age;
}
Opcion 2:
Crear un genérico Struct
escriba la clase como sugiere Gordon y extiéndala como su objeto de datos, usando el @propiedad anotación para definir qué valores genéricos son posibles de acceder con __get
y __set
.
class Struct
{
/**
* Private internal struct attributes
* @var array
*/
private $attributes = [];
/**
* Set a value
* @param string $key
* @param mixed $value
*/
public function __set($key, $value)
{
$this->attributes[$key] = $value;
}
/**
* Get a value
* @param string $key
* @return mixed
*/
public function __get($key)
{
return isset($this->attributes[$key]) ? $this->attributes[$key] : null;
}
/**
* Check if a key is set
* @param string $key
* @return boolean
*/
public function __isset($key)
{
return isset($this->attributes[$key]) ? true : false;
}
}
/**
* @property string $name
* @property integer $age
*/
class MyData extends Struct
{
// Can optionally add data mutators or utility methods here
}
-
Si elige la opción 1, puede declarar la clase en un archivo escaneado por su IDE pero ignorado por su proyecto. Indique que el método devuelve un
StaffMember
pero sigue usandostdClass
en la implementación.–David Harkness
06/04/2017 a las 18:59
-
¿Cómo puede tener un archivo escaneado por su IDE pero ignorado por su proyecto con NetBeans?
– Yevgeniy Afanasyev
28 de enero de 2021 a las 23:59
-
Esta es una vieja pregunta, recomendaría hacer una nueva.
–Jeremy Harris
1 de febrero de 2021 a las 15:30
-
También podría ser una buena idea implementar el Serializable y JsonSerializable interfaz
– Tofandel
18 ago a las 9:52
Maksim Fiódorov
Solo tiene dos formas de documentar la estructura de la clase de resultado.
1.Se puede describir la estructura en un texto de comentario. Por ejemplo:
class SomeClass
{
/**
* Getting staff detail.
* Result object has following structure:
* <code>
* $type - person type
* $name - person name
* $age - person age
* </code>
* @param string $id staff id number
*
* @return stdClass
*
*/
public function staffDetails($id){
$object = new stdClass();
$object->type = "person";
$object->name = "dave";
$object->age = "46";
return $object;
}
}
2. Uno puede crear un tipo de datos que heredará stdClass y tendrá una anotación de un objeto de resultado. Por ejemplo:
/**
* @property string $type Person type
* @property string $name Person name
* @property integer $age Person age
*/
class DTO extends stdClass
{}
Y utilízalo en tus otras clases.
class SomeClass {
/**
* Getting staff detail.
*
* @param string $id staff id number
*
* @return DTO
*
*/
public function staffDetails($id){
$object = new DTO();
$object->type = "person";
$object->name = "dave";
$object->age = "46";
return $object;
}
}
En mi opinión, esta forma es mejor que una descripción en el comentario de texto porque hace que el código sea más obvio.
-
opción 1: no ayudaría a su IDE a trabajar con él, opción 2: rompería la convención PSR
– Yevgeniy Afanasyev
28 de enero de 2021 a las 23:18
-
@YevgeniyAfanasyev sí, la opción 1 no pudo ayudar al IDE, solo puede ayudar a un desarrollador que trabajará con su código; al menos verá la estructura. opción 2: ¿a qué PSR te refieres?
– Maksim Fiódorov
29 de enero de 2021 a las 8:07
-
los Especificaciones de PSR4 dice: >El nombre de la clase final corresponde a un nombre de archivo que termina en .php. El nombre del archivo DEBE coincidir con el caso del nombre de la clase de terminación.
– Yevgeniy Afanasyev
2 de febrero de 2021 a las 7:06
-
@YevgeniyAfanasyev No se relaciona con PSR-4 porque no hay ningún archivo en mi respuesta. Es solo un ejemplo de código simple.
– Maksim Fiódorov
2 de febrero de 2021 a las 9:16
-
@YevgeniyAfanasyev Sí, separé el código en el ejemplo, gracias 🙂
– Maksim Fiódorov
3 de febrero de 2021 a las 6:24
Yevgeni Afanasyev
Si está utilizando PHP 7, puede definir una clase anónima.
class SomeClass {
public function staffDetails($id){
$object = (new class() extends stdClass {
public /** @var string */ $type;
public /** @var string */ $name;
public /** @var int */ $age;
});
$object->type = "person";
$object->name = "dave";
$object->age = 46;
return $object;
}
}
Está funcionando para mi IDE (probado en NetBeans)
Krzysiek
con por ejemplo json_decode
es más difícil usar clases propias en lugar de stdClass
pero en mi caso acabo de crear un archivo ficticio con definiciones de clase, que en realidad no está cargado y estoy agregando clases propias como @return
(funciona para intelephense en vscode).
PHPdocObjetos.php
/**
* class only for PHPdoc (do not include)
*/
class Member {
/** @var string */
public $type;
/** @var string */
public $name;
/** @var string */
public $age;
}
/**
* Other format
*
* @property string $type;
* @property string $name;
* @property string $age;
*/
class MemberAlt {}
AlgunaClase.php
/**
* Get Staff Member Details
*
* @param string $id staff id number
*
* @return Member I'm in fact stdClass
*/
class SomeClass {
public function staffDetails($id){
$object = json_decode('{"type":"person","name":"dave","age":"46"}');
return $object;
}
}
Alexei Yashin
El truco que uso para autocompletar en PhpStorm:
- Cree algún metaarchivo que contenga algunas clases para describir sus estructuras. El archivo nunca se incluye y las estructuras tienen sus propias reglas de nombres para no confundirlas con las clases reales existentes:
<?php
/*
meta.php
never included
*/
/**
* @property string $type
* @property string $name
* @property string $age
*/
class StaffDetails_meta {}
- Use la metaclase como valor de retorno en su código real PHPDoc:
<?php
/*
SomeClass.php
eventually included
*/
class SomeClass
{
/**
* Get Staff Member Details
*
* @param string $id staff id number
*
* @return StaffDetails_meta
*/
public function staffDetails($id)
{
$object = new stdClass();
$object->type = "person";
$object->name = "dave";
$object->age = "46";
return $object;
}
}
- Felicitaciones, esto hará que su IDE complete automáticamente su código cuando escriba algo como
(new SomeClass)->staffDetails('staff_id')->
PD: Lo se, pasaron casi 10 años pero sigue vigente
¿Por qué no tiene una clase StaffDetails con propiedades de tipo, nombre y edad? Entonces puedes usar @param StaffDetails
– ken
15 de septiembre de 2012 a las 8:00
si no desea crear un tipo concreto para stdClass, aún puede escribir
@return \stdClass holding type, name and age
o explícalo en la descripción larga del Doc Block. Al menos está documentado entonces. Sin embargo, eso no hará que su IDE conozca mágicamente las propiedades.– Gordon
15 de septiembre de 2012 a las 8:08
no, no quiero que el IDE conozca las propiedades. Solo me gustaría que estuvieran bien documentados. El objeto que estoy usando en realidad tiene alrededor de 40 variables dentro de él, así que realmente quería saber si era una forma de colocarlas bien en una tabla como aparecen los parámetros de entrada. De lo contrario, si solo usa una descripción larga, se vuelve desordenado y difícil de leer.
– algún usuario
15 de septiembre de 2012 a las 8:12
@l_t Bueno, siempre puede documentarlos en la descripción larga de DocBlock. Pero un objeto que tiene 40 variables es un buen indicador de que un objeto sabe demasiado. Es probable que pueda dividir ese objeto en 4 a 10 objetos individuales. Busque propiedades que se puedan agrupar. Extraerlos en su propia clase. Entonces, asocie la clase principal con esa clase, de modo que al final obtendrá un buen gráfico de objeto dedicado.
– Gordon
15 de septiembre de 2012 a las 8:21
@Gordon Gracias: el método en cuestión es una agrupación de muchas clases diferentes. Lo hice así para que el desarrollador front-end pueda simplemente llamar a un método de clase y recuperar un objeto con todos los datos limpios/preprocesados necesarios para esa página (en este caso, datos del producto). ¿Eso generalmente no es una buena idea?
– algún usuario
15 de septiembre de 2012 a las 8:37