2

我有一个工作申请表,管理员需要从某些用户 ID 列表中进行选择。该列表仅包含“雇主”类型的用户 ID,但是我想验证管理员输入,因此如果他手动插入一个不存在的 ID 或用于与“雇主”不同类型的用户,验证应该失败。我认为执行此操作的代码是:

new Zend_Validate_Db_RecordExists(
    array(
        'table' => 'users',
        'field' => 'id',
        'exclude' => "mode != 'employer'"
    )
)

所以,我正在搜索表用户中的所有记录,不包括那些 mode != 'employer' - 如果存在这样的记录,其中 id 等于从输入中选择的记录,它通过验证。但是,上面的代码不起作用 - 我必须这样做'exclude' => "mode = 'employer'",所以 exclude 实际上等于 where 语句。我对这里逻辑的理解是错误的——有人能告诉我为什么吗?

PHP:5.2.17,Zend:1.10.4

编辑:(对@ro ko 询问的评论,因为它可能会清除问题)

请在此处找到表格和示例代码:http: //pastebin.com/C7AXMNTZ。据我了解,这应该对 Joker(是雇主)返回有效,但对 Kingpin(不是雇主)和 Poison Ivy(不在数据库中)返回错误 - 正如您所看到的结果不是我所期望的。

4

4 回答 4

2

一种)'exclude' => "mode != 'employer'"

    $id = new Zend_Form_Element_Select("id");
    $id->setRegisterInArrayValidator(false);
    $id->addValidator(new Zend_Validate_Db_RecordExists(array(
        'table' => 'villains',
        'field' => 'id',
        'exclude' => "mode != 'employer'"
    )));

产生以下查询:

SELECT `villains`.`id` 
    FROM `villains` 
    WHERE (`id` = :value) AND (mode != 'employer') 
    LIMIT 1

二)'exclude' => "mode = 'employer'"

    $id = new Zend_Form_Element_Select("id");
    $id->setRegisterInArrayValidator(false);
    $id->addValidator(new Zend_Validate_Db_RecordExists(array(
        'table' => 'villains',
        'field' => 'id',
        'exclude' => "mode = 'employer'"
    )));

产生以下查询:

SELECT `villains`.`id` 
    FROM `villains` 
    WHERE (`id` = :value) AND (mode = 'employer') 
    LIMIT 1

C)'exclude' => array("field" => "mode", "value" => "employer")

    $id = new Zend_Form_Element_Select("id");
    $id->setRegisterInArrayValidator(false);
    $id->addValidator(new Zend_Validate_Db_RecordExists(array(
        'table' => 'villains',
        'field' => 'id',
        'exclude' => array(
            "field" => "mode",
            "value" => "employer"
        )
    )));

产生以下查询:

SELECT `villains`.`id` 
    FROM `villains` 
    WHERE (`id` = :value) AND (`mode` != 'employer') 
    LIMIT 1

结果

你想要B。这令人困惑,并且可以说组件的逻辑和行为是倒退的。尽管如此,您想要的行为来自示例 B。

附录

我们可以破解一个测试(我真的是指一起破解)来检查上述是否按预期工作。

test1 和 test2 都通过了,但是正如您从提供者那里看到的那样,它们都产生了不同的结果。

class SO14706653Test extends PHPUnit_Framework_TestCase
{
    /**
     * @var Zend_Test_PHPUnit_Db_Connection
     */
    public $dbConnection;

    public function getRowCount($tableName) {
        $query = "SELECT COUNT(*) FROM ".$this->dbConnection->quoteSchemaObject($tableName);
        return (int) $this->dbConnection->getConnection()->query($query)->fetchColumn();
    }

    // hack a very quick setup for tests
    public function setup() {
        $app = new Zend_Application(APPLICATION_ENV, APPLICATION_PATH . '/configs/application.ini');
        $app->bootstrap();
        $dbAdapter = $app->getBootstrap()->getResource('db'); /* @var $db Zend_Db_Adapter_Pdo_Mysql */
        $this->dbConnection = new Zend_Test_PHPUnit_Db_Connection($dbAdapter, 'unittests');

        $dbAdapter->exec("CREATE TABLE IF NOT EXISTS `villains` (
              `id` int(11) NOT NULL AUTO_INCREMENT,
              `name` varchar(255) NOT NULL,
              `mode` varchar(255) NOT NULL,
              PRIMARY KEY (`id`)
            ) ENGINE=InnoDB  DEFAULT CHARSET=latin1");

        $dbAdapter->exec('DELETE FROM villains'); // clean out db data

        $dbAdapter->exec("
            INSERT INTO `villains` VALUES(1, 'Joker', 'employer');
            INSERT INTO `villains` VALUES(2, 'Kingpin', '');
            INSERT INTO `villains` VALUES(3, 'Penguin', '');
        ");
    }

    // ensure the above setup is working as expected
    public function assertPreConditions() {
        $this->assertEquals(3, $this->getRowCount('villains')); 
    }

    public function provideTest1()
    {
        return [
            // form data        is valid?       isRequired?
            [['id' => '1'],     false,          false],
            [['id' => '2'],     true,           false],
            [['id' => '3'],     true,           false],
            [['id' => ''],      true,           false],
            [[],                true,           false],
            [['id' => '856'],   false,          false],
            [['id' => '856'],   false,          true],
            [['id' => ''],      false,          true],
            [[],                false,          true],
        ];
    }

    public function provideTest2()
    {
        return [
            //  form data       is valid?       isRequired?
            [['id' => '1'],     true,           false],
            [['id' => '2'],     false,          false],
            [['id' => '3'],     false,          false],
            [['id' => ''],      true,           false],
            [[],                true,           false],
            [['id' => '856'],   false,          false],
            [['id' => '856'],   false,          true],
            [['id' => ''],      false,          true],
            [[],                false,          true],
        ];
    }

    /**
     * @dataProvider provideTest1
     */
    public function test1(array $data, $isValid, $isRequired)
    {
        $form = new Zend_Form();
        $id = new Zend_Form_Element_Select("id");
        $id->setRegisterInArrayValidator(false);
        $id->addValidator(new Zend_Validate_Db_RecordExists(array(
            'table' => 'villains',
            'field' => 'id',
            'exclude' => "mode != 'employer'"
        )));
        $id->setRequired($isRequired);
        $form->addElement($id);

        // produces the query
        // SELECT `villains`.`id`
        // FROM `villains`
        // WHERE (`id` = :value) AND (mode != 'employer')
        // LIMIT 1

        $this->assertSame($isValid, $form->isValid($data));
    }

    /**
     * @dataProvider provideTest2
     */
    public function test2(array $data, $isValid, $isRequired)
    {
        $form = new Zend_Form();
        $id = new Zend_Form_Element_Select("id");
        $id->setRegisterInArrayValidator(false);
        $id->addValidator(new Zend_Validate_Db_RecordExists(array(
            'table' => 'villains',
            'field' => 'id',
            'exclude' => "mode = 'employer'"
        )));
        $id->setRequired($isRequired);
        $form->addElement($id);

        // produces the query
        // SELECT `villains`.`id` 
        // FROM `villains` 
        // WHERE (`id` = :value) AND (mode = 'employer') 
        // LIMIT 1

        $this->assertSame($isValid, $form->isValid($data));
    }
}
于 2013-02-12T01:39:00.890 回答
0

您在排除选项中传递一个数组。例如。

$this->getElement('username')->addValidator(
    new Zend_Validate_Db_NoRecordExists(
        array(
        'table' => 'user', 
        'field' => 'username', 
        'exclude' => array(
                'field' => 'username', 
                'value' => $username
            )
        )
    )
);

在这里查看更多信息。

编辑:再次阅读问题后,我发现我实际上并没有回答。我要给出的唯一其他建议是使用文档中的 quoteInto 语句。

$email     = 'user@example.com';
$clause    = $db->quoteInto('email != ?', $email);
$validator = new Zend_Validate_Db_RecordExists(
    array(
        'table'   => 'users',
        'field'   => 'username',
        'exclude' => $clause
    )
);

这里还有一个关于 Zend_Validate_Db_RecordExists 的另一个问题的链接,它有一个很好的答案。

如何修改 zend Db_RecordExists 验证器 where 子句?

于 2013-02-05T13:08:39.997 回答
0

我想你在这里感到困惑。验证器的逻辑很好。

如何?
好吧,排除这里会否定您的条件。

'exclude' => "mode = 'employer'"

或者

'exclude' => array(
                'field' => 'mode', 
                'value' => 'employer'
            )

被解释为验证器应该对非mode = employer条件有效。

编辑:如果您在手册中看到说明:“上面的示例将检查表以确保除了 id = $user_id 包含值 $username 的记录之外没有其他记录。” 我认为这句话应该为你清楚。

于 2013-02-05T13:24:39.357 回答
0

根据文档(搜索The above example will check the table to ensure no records other than the one where id = $user_id contains the value $username.), exclude 选项确实可以用作 WHERE 语句。

我只能说,尽管为这个功能使用这样的关键字是个好主意,但无论谁都有一种邪恶的幽默感。

于 2013-02-07T14:09:02.993 回答