PHP:当数组是方法参数时,如何记录它们


PHP: How to document array when they are method parameters

当数组是方法的参数时,记录数组元素的最佳方式是什么?例如,使用PHPDoc头,我可能会有类似的东西:

@param array $data

这并没有告诉我数组中哪些元素是强制性的,哪些是可选元素。我想这应该包括在对方法的解释中。类似于:

array: $data
============ 
int     $id      Required 
name    $string  Required 
town    $string  Optional
/**
 * @param array $data
 * 
 * @var $data[id] int, required
 * @var $data[name] string, required
 * @var $data[town] string, required
 */

这个使用条令的例子和zf2的例子:

/**
* @ORM'Id
* @ORM'Column(type="integer")
* @ORM'GeneratedValue
* @Form'Attributes({"type":"hidden"})
*/
protected $id;
/**
* @ORM'Column(type="string")
* @Form'Type("Zend'Form'Element'Text")
* @Form'Required({"required":"true"})
* @Form'Filter({"name":"StripTags"})
* @Form'Filter({"name":"StringTrim"})
* @Form'Validator({"name":"StringLength", "options":{"min":"5"}})
* @Form'Options({"label":"First name"})
*/
protected $firstName;

如果您有这样一个对每个成员都有约束的复杂数组,我不会使用匿名数组,而是使用一个定义良好的对象。对于数组,你永远无法确定它包含什么,这有点像在Java中传递"Object",你很少会认为这是一个好的选择。

然而,当您的数组包含这里所解释的特定类型的对象时,可能会有一些暗示,但这并不是一个很好的答案。

如果您确实需要将参数作为数组,则可以按照方法描述中建议的方式对其进行文档记录;但是,如果使用对象作为参数,那么在现代IDE(IntelliSense等)中会有额外的支持。

EDIT:我的意思是,对我来说,问题是"我为什么要使用匿名数组而不是自定义类型"——除了简单性(如果你维护和扩展你的代码,这将适得其反,成为技术债务)之外,我想不出什么原因,尤其是与使用用户定义的类型(自文档化的代码、通过标准方法可见和显式的约束等等)相比。

如果你只需要一个数据转储,你可能想使用一个简单的数组,但由于你已经在考虑可选和必需的键,这对于用户定义的类型来说非常重要。

EDIT2:关于您是否已经有一个数组作为源的评论:我不确定您是否需要将其作为数组传递,或者在收到数组后立即执行"映射"操作(例如,作为$_POST或作为某些第三方库或PHP内部函数的返回值等)。

我想有人可能会争辩说,解释视图生成的数据(例如,POST数据的HTML表单)不是模型的职责,而是控制器对输入做出相应反应并以适当的状态传输模型的责任。我的意思是,如果你收到一个数组$_POST:,你可以做这样的事情

$customer = new Customer();
$customer->setId($_POST['id']);
$customer->setName($_POST['name']);
$customer->setTown($_POST['town']);

并在访问$customer时立即处理错误,例如,如果未设置名称(即$_POST['name']为空等),则抛出异常。通过这种方式,您可以使用源数组来调用对象上的setter,而不是将数组传递给像Customer::buildByHttpPostData(array $data)这样的工厂,从而委托视图的详细信息(HTML输入标记的名称等)。

最重要的是,没有"标准"的方法来声明必需或可选的数组键,当然您可以在方法描述中描述这些约束,但也许您可以通过使用受支持的方法来避免这种情况,比如对setter或getter的PHPDoc注释。

当然,可能有更好的方法来处理这个问题,也许有人会想出更好的答案来处理它

要回答这个没有正式方法的问题,请尝试使用您认为最直观的方法。我做了类似的事情:

/**
 * @param array $data [ int $id, string $name, string $town ]
 */

然而,我不会将这种表示法用于参数,而是用作返回值。在您的情况下,我会将方法参数提取到对象中,并将其传递到方法中:

/**
 * @param User $user
 */
public function myMethod( User $user )
{ 
    //... 
}

这是因为用户对象将其属性作为API公开给其他开发人员,即自文档代码!

另一种方法是将数组元素分离为如下参数:

/**
 * @param int $id
 * @param string $name
 * @param string $town
 */
public function myMethod( $id, $name, $town )
{
    //...
}

3个参数是可以通过的,但你应该开始寻找重构它的方法,就像我的第一个建议一样。4个参数通常被认为是混乱的,你可以重构它。