2

管理者が特定のユーザー ID のリストから選択する必要がある求人応募用のフォームがあります。リストには「employer」タイプのユーザーIDのみが含まれていますが、管理者の入力を検証したいので、存在しないIDまたは「employer」とは異なるタイプのユーザー用のIDを手動で挿入すると、検証は失敗するはずです。これを行うコードは次のようになると思いました。

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

そのため、mode != 'employer' のレコードを除く、テーブル users のすべてのレコードを検索しています。そのようなレコードが存在する場合、id は入力から選択されたものと同じで、検証に合格します。ただし、上記のコードは機能しません。実行する必要'exclude' => "mode = 'employer'"があるため、exclude は実際には where ステートメントと等しくなります。ここでのロジックの私の理解は間違っています - 誰かが理由を教えてもらえますか?

PHP: 5.2.17、ゼンド: 1.10.4

編集:(@ro koのお問い合わせへのコメント。おそらく問題が解決するため)

表とサンプル コードはhttp://pastebin.com/C7AXMNTZにあります。私の理解では、これは Joker (雇用主である) には有効ですが、Kingpin (雇用主ではない) と Poison Ivy (データベースにない) には false を返すはずです。

4

4 に答える 4

2

A)'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

B)'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' => 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

exclude オプションで配列を渡します。例えば。

$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ます。

編集:マニュアルに次のような説明が表示されます。このステートメントは、私が推測するあなたのために物事をクリアするはずです。

于 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.)に従って、除外オプションは実際にWHEREステートメントとして機能します。

この機能にそのようなキーワードを使用するのは良い考えですが、誰でも邪悪なユーモアのセンスを持っていたとしか言えません。

于 2013-02-07T14:09:02.993 に答える