【问题标题】:How to filter / validate for a boolean value?如何过滤/验证布尔值?
【发布时间】:2012-06-21 10:15:26
【问题描述】:

我刚刚阅读了 Michelangelo van Dam aka DragonBe 关于Quality Assurance for PHP Projects 的精彩演讲。在他的演讲中,他以 Zend-Framework 为例,我在基本层面上很熟悉。

因为我想提高自己,我从单元测试开始,虽然我觉得问题出在 ZF 方面。

问题:

每当我分配布尔值false 时,使用给定的代码工件,Zend_Filter 或 Zend_Validator 将其更改为null。我不知道为什么会这样。

请参阅底部的更新以获取更新的代码和测试

首先进行测试

public function goodData() {
  return array(
    array('DU-IT', 'Sample Description', true, false),
    array('Mercüß', 'bla"ß"trager', false, true),
    array('Mia123', '728 Tage im Jahr', false, false)
  );
}

/**
 * @dataProvider goodData()
 */
public function testModelAcceptsValidData($name, $description, $flag_active, $flag_deleted)
{
  $data = array(
    'id'            => 0,
    'name'          => $name,
    'description'   => $description,
    'flag_active'   => $flag_active,
    'flag_deleted'  => $flag_deleted
  );

  try {
    $this->_model->populate($data);
  } catch (Zend_Exception $e) {
    $this->fail('Unexpected Exception: '.$e->getMessage());
  }

  $this->assertSame($data, $this->_model->toArray());
}

模型

public function __construct($props = null)
{
  // Set Filters
  $this->_filters = array(
    'id'            => array('Int'),
    'name'          => array('StringTrim', 'StripTags'),
    'description'   => array('StringTrim', 'StripTags'),
    'flag_active'   => array(new Zend_Filter_Boolean()),
    'flag_deleted'  => array(new Zend_Filter_Boolean())
  );

  // Set Validators
  $this->_validators = array(
    'id'            => array('Int'),
    'name'          => array(new Zend_Validate_StringLength(array('min'=>4, 'max'=>50))),
    'description'   => array(new Zend_Validate_StringLength(array('max'=>5000))),
    'flag_active'   => array(new Zend_Validate_InArray(array(true, false))),
    'flag_deleted'  => array(new Zend_Validate_InArray(array(true, false)))
  );

  // Set Properties
  if (!is_null($props)) {
    $this->populate($props);
  }
}

public function setFlagActive($arg)
{
  $input = new Zend_Filter_Input($this->_filters, $this->_validators);
  $input->setData(array('flag_active'=>$arg));
  if (!$input->isValid('flag_active')) {
    throw new Zend_Exception('Invalid FLAG_ACTIVE provided'. gettype($input->flag_active));
  }
  $this->_flag_active = (bool) $input->flag_active;
  return $this;
}

就模型而言,我尝试将flag_active 和flag_deleted 的验证器留空,但这并没有改变我的结果。 phpunit的报错信息不变:

Unexpected Exception: Invalid FLAG_ACTIVE providedNULL

而 NULL 是变量的类型,而当我通过数据提供者 goodData() 将 false 作为标志的参数传递时(badData 也是如此)。

我的猜测是这与 Zend_Filter 有关,但我就是想不通。非常感谢您的提示!

更新 由于德鲁给出了一点提示,我已经进一步测试了一点,但问题仍然存在。我已将更新的类和单元测试粘贴到 pastebin 以提高可读性。

PHPUnit 给出以下错误:You must give a non-empty value for field 'flag_active' flag_deleted 相同。一半测试的第二个错误是<null> does not match expected type "boolean"。我被困住了。无论我使用过滤器还是 inArrayValidator(array(0=>true,1=>false)) 它都不会改变任何事情:\

【问题讨论】:

    标签: zend-framework zend-validate zend-filter


    【解决方案1】:

    如果您检查 $input->getMessages() 的内容,它应该提供一些解释,说明为什么该特定值无效。

    当您使用Zend_Filter_Input 时,任何未通过验证的值都将无法通过其名称神奇地访问(例如$input->flag_active)。如果未通过验证步骤,该值将始终为 NULL。

    某些过滤器在某些情况下几乎可以保证验证(即带有 Int 验证器的 Int 过滤器),因为过滤器将过滤数据并为验证器返回有效值。通过Int 过滤器传递hello 将返回0,即使原始输入数据无效,也可以使用简单的Int 验证器进行验证。

    您最有可能在异常中获得空值的原因是该值不可用,因为它没有经过验证;因此,请检查输入消息以获取有关原因的任何提示。

    编辑:

    我认为您遇到的问题是Zend_Filter_Input 默认情况下不允许空值。因此,如果进入过滤器的值为false 或NULL,则会导致过滤器出错。

    查看此代码:

        <?php
    
        // set up a boolean validator and inarray validator like you have
        $filters    = array('test' => array(new Zend_Filter_Boolean()));
        $validators = array('test' => array(new Zend_Validate_InArray(array(true, false))));
    
        // set up the input filter with default options
        $input      = new Zend_Filter_Input($filters, $validators);
    
        // our "input" value which is (bool)false
        $test       = false;
    
        $input->setData(array('test' => $test));
    
        // run through input filter using default values
        // should throw error about a non-empty value
        if (!$input->isValid('test')) {
            echo "Test is not valid.  <br />Original Value: ";
            var_dump($test);
            echo "<br />";
            print_r($input->getMessages());
        } else {
            echo "Test is valid.<br />Original Value: ";
            var_dump($test);
            echo "<br />Value now: ";
            var_dump($input->test);
        }
    
        // now allowing empty values...
        echo "<hr />\n";
    
        // tell Zend_Filter_Input to allow empty values on input
        $options = array(Zend_Filter_Input::ALLOW_EMPTY => true);
    
        // set up new input filter with option
        $input   = new Zend_Filter_Input($filters, $validators, null, $options);
    
        $input->setData(array('test' => $test));
    
        // run through input filter allowing empty values
        // this should NOT throw an error
        if (!$input->isValid('test')) {
            echo "Test is not valid.  <br />Original Value: ";
            var_dump($test);
            echo "<br />";
            print_r($input->getMessages());
        } else {
            echo "Test is valid.<br />Original Value: ";
            var_dump($test);
            echo "<br />Value now: ";
            var_dump($input->test);
        }
    

    所以问题似乎是 Zend_Filter_Input 不喜欢空值,除非你指定一个选项。因此,将有效的 (false) 值发送到过滤器会导致错误,除非您将 Zend_Filter_Input::ALLOW_EMPTY 设置为 true。

    【讨论】:

    • 首先感谢您的回答。遗憾的是,已知的错误消息并没有太大帮助,因为它只是写得更好的“嘿,你在这里得到了一个空值”——有关新类和测试代码的详细信息,请参阅更新的问题。问题仍然存在:布尔值能否由 Zend_Filter_Input 验证?即使使用空过滤器/验证器,只要我输入“false”,inputFilter 就会严重失败,返回 null。
    • 你确认$arg进入集合函数是你所期望的吗?我用Zend_Filter_Input 和布尔过滤器测试了一些东西,几乎所有值都被转换为布尔值,所以很奇怪这失败了。
    • 实际上在类中存在一个错误,没有正确设置属性,但我设法在最后 5 分钟的工作中找到它。我稍后会进一步检查 - 在此之前我没有让它工作。您能否提供使用 true 和 false 布尔值的示例?
    • 这是我使用的paste。稍后我将使用我认为的一些有用信息来更新答案。
    • 好的,很高兴知道有一个选项,我会在两天内检查一下(遗憾的是,只有到那时)。据我所知,空值也允许分配NULL,对吗?我想这不能改变。然后必须将NULL视为FALSE,我想我可以忍受。虽然感觉很奇怪 :) 预先感谢,我会在星期四告诉你我的案子是如何处理的,并正确分配(小)奖;)
    猜你喜欢
    • 2020-05-15
    • 2014-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-25
    • 1970-01-01
    • 2019-12-09
    • 2014-05-11
    相关资源
    最近更新 更多