检查通过数组传递给函数的参数

时间:2014-08-19 12:04:10

标签: php

我在具有签名的Yii 1.8中包装模型函数:

public save($runValidation=true, array $attributes=NULL)

有一个功能:

public xSave(array $params)

允许添加一个标志和可选消息,导致包装函数在委托的save()函数返回false的情况下抛出异常。

我玩弄了save()覆盖:

的想法
public save(
  $runValidation=true,
  array $attributes=NULL,
  $exception_on_error=false,
  $exception_message=false
)

但是希望允许最后两个参数的指定独立于第一个,并且允许使用字符串键传递数组的额外可读性。

我到目前为止:

/**
  * Enhanced save function.
  *   Delegates to standard model save to allow exceptions to be thrown
  *   in the case where the model was not saved.
 **/
public function xSave(array $params=array()){

  $_params=array(
    'run_validation'=>true,
    'attributes'=> null,
    'exception_on_failure'=>false,
    'exception_message'=>false,
  );

  array_merge($_params, $params);

  // Call the save method.
  $is_saved=$this->save($_params['run_validation'],$_params['attributes']);

  // Throw exception to if flag set and model not saved.
  if($_params['exception_on_failure'] && !$is_saved){

    // If no exception message was passed in, use the default.
    if($_params['exception_message'] === false){
      throw new CException('
        Could not '.($this->isNewRecord()?'create':'update').' '.get_class($this).';
        Errors: '.CJSON::encode($this->errors)
      );
    }

    // Else throw using the one provided.
    throw new CException($exception_message);
  }

  // Return result of standard save method.
  return $is_saved;
}

首先,我想知道这是否是明智的选择,因为我可能会将它用于系统的其他部分。我目前并不太担心参数的输入,但我同意这可能会成为未来的问题。

其次,我还希望能够在$params具有未在$_params中定义的密钥以及指定该密钥的消息的情况下抛出异常,并且希望这样做如果可能,array_merge的一部分。

2 个答案:

答案 0 :(得分:1)

使用单个参数或参数数组的决定是基于意见的。这取决于实际情况。至少我会在整个项目中保持设计的一致性。


要确定是否传递了未知参数,您可以使用array_diff()

$a = array(
  'test' => 'foo',
  'name' => 'bar'
);

$b = array(
  'test' => 'foo',
  'name' => 'bar',
  'abcd' => '123'
);

$d = array_diff(
    array_keys($b), array_keys($a)
);

echo "The following keys can't be understood: " . implode(', ', $d) . PHP_EOL;

然而,我会跳过那张支票,因为它不会伤害"如果有未知参数。

答案 1 :(得分:1)

对于1),是的,传递数组是不支持命名参数的语言中常见的蹩脚解决方法(请参阅jQuery等)。使用新的数组语法,这甚至几乎可读:

$some->save([
  $runValidation => true,
  $attributes => ['foo', 'bar']
]);

在函数内部,您可以使用extract来避免丑陋的$params[foobar]引用。

为了获得更好的品味,请说服@NikiCthis patch做好准备))

至2),如果您计划系统地使用参数数组,请考虑这样的辅助函数:

function parseArgs($args, $defaults) {
    foreach($args as $k => $v) {
        if(!array_key_exists($k, $defaults))
            throw new Exception("invalid argument: $k");

        // might want to add some type checking, like
        // if(gettype($v) != gettype($defaults[$k])) bang!
    }
    return $args + $defaults;
}

用法:

public function xSave(array $params=array()){

     extract(parseArgs($params, [
       'run_validation'=>true,
       'attributes'=> null,
       'exception_on_failure'=>false,
       'exception_message'=>false,
    ]));

    if ($run_validation)
        etc....