10

私は、自分で使用するためのユーティリティ Web サイトをいくつか構築することで、Zend のスキルをゆっくりと築き上げています。私は Zend Forms と Form validation を使用してきましたが、Zend のやり方を理解できたことに満足しています。しかし、Zend_Validate_Db_NoRecordExists() を編集フォームのコンテキストで使用する方法と、一意である必要があるデータベース列にマップするフィールドについて少し混乱しています。

たとえば、この単純なテーブルを使用して

TABLE Test
(
  ID INT AUTO_INCREMENT,
  Data INT UNIQUE
);

テーブル テストに新しい行を追加するだけの場合は、データ フィールドの Zend フォーム要素にバリデーターを次のように追加できます。

$data = new Zend_Form_Element_Text('Data');
$data->addValidator( new Zend_Validate_Db_NoRecordExists('Test', 'Data') )

フォームの検証時に、このバリデーターは Data 要素の内容がテーブルにまだ存在しないことを確認します。したがって、Test への挿入は、データ フィールドの UNIQUE 修飾子に違反することなく続行できます。

ただし、Test テーブルの既存の行を編集する場合は状況が異なります。その場合、バリデーターは、要素の値が相互に排他的な 2 つの条件のいずれかを満たすことを確認する必要があります。

  1. ユーザーが要素の値を変更しましたが、新しい値は現在テーブルに存在しません。

  2. ユーザーは要素の値を変更していません。したがって、値現在テーブルに存在します (これは問題ありません)。

Zend Validation Docsでは、検証プロセスからレコードを除外する目的で NoRecordExists() バリデーターにパラメーターを追加することについて説明しています。「一致する行を探してテーブルを検証しますが、フィールドにこの特定の値があるヒットは無視する」という考えです。このような使用例は、テーブルの編集時に要素を検証するために必要なものです。1.9 でこれを行うための疑似コードは次のようになります (実際、これは 1.9 のソース コードから取得したものです。現在のドキュメントは間違っている可能性があります)。

$data = new Zend_Form_Element_Text('Data');
$data->addValidator( new Zend_Validate_Db_NoRecordExists('Test', 'Data',
                     array ('field'=>'Data', 'Value'=> $Value) );

問題は、除外される値 ($Value) がインスタンス化された時点で (フォームがインスタンス化された時点でも) バリデーターにバインドされることです。ただし、フォームがレコードを編集している場合、その値は、フォームに最初にデータが入力されたときの $data フィールドの内容にバインドする必要があります。つまり、Test テーブルの行から最初に読み取られたデータ値です。しかし、典型的な Zend パターンでは、フォームは 2 つの別々のステップでインスタンス化され、入力されます。これにより、除外値を目的の要素値にバインドすることができなくなります。

次の Zend 疑似コードは、$Value を NoRecordExists() バリデーターにバインドする場所を示しています (これは Zend コントローラーの一般的なパターンであることに注意してください)。

$form = new Form() 
if (is Post) {
    $formData = GetPostData()
    if ($form->isValid($formData)) {
        Update Table with $formData
        Redirect out of here
    } else {
        $form->populate($formData)
    }
} else {
    $RowData = Get Data from Table
    $form->populate($RowData)     <=== This is where I want ('value' => $Value) bound
}

Zend_Form をサブクラス化し、populate() メソッドをオーバーライドして、最初のフォーム作成時に NoRecordExists() バリデーターをワンショット挿入することもできますが、それは私には大きなハックのように思えます。だから私は他の人がどう思うか知りたかったのですが、この問題を解決するパターンがすでに書き留められていますか?

2009-02-04 を編集

この問題に対する適切な解決策は、カスタム バリデータを作成し、Zend バージョンを忘れることだけだと私は考えています。私のフォームには非表示フィールドとしてレコード ID があるため、テーブル名と列名を指定して、一意性をテストし、そのような ID を持つ行を除外する SQL を作成できます。もちろん、これにより、モデルが非表示にするはずの dB レイヤーにフォームを結び付ける方法について考えるようになりました。

4

7 に答える 7

6

これはそれがどのように行われるかです:

  1. フォームに、このバリデーターを追加します (たとえば、電子メール フィールド)。

 

$email->addValidator('Db_NoRecordExists', true, array('table' => 'user', 'field' => 'email'));
  1. その後はうまくいかなかったので、これにカスタムエラーメッセージを追加しないでください。

 

$email->getValidator('Db_NoRecordExists')->setMessage('This email is already registered.');

 

  1. コントローラーにこれを追加します:

 

/* Don't check for Db_NoRecordExists if editing the same field */

    $form->getElement('email')
             ->addValidator('Db_NoRecordExists',
                                 false,
                                 array('table' => 'user',
                                       'field' => 'email',
                                       'exclude' => array ('field' => 'id', 'value' => $this->request->get('id'))));

And after this you do verifications, e.g.:

    if ($this->getRequest()->isPost())
            {
                if($form->isValid($this->getRequest()->getPost()))
                {

    ....

それでおしまい!

于 2011-03-03T10:54:06.883 に答える
1

圧倒的な反応を検討した結果、カスタムバリデーターを使用することにしました。

于 2010-02-09T13:52:26.500 に答える
1
private $_id;

public function setId($id=null)
{
    $this->_id=$id;    
}

public function init()
{
    .....
    if(isset($this->_id)){
        $email->addValidator('Db_NoRecordExists', false, array('table' => 'user', 'field' => 'email','exclude' => array ('field' => 'id', 'value' => $this->_id) )); 
        $email->getValidator('Db_NoRecordExists')->setMessage('This email is already registered.');      
    }

今あなたは使用することができます:

$form = new Form_Test(array('id'=>$id));
于 2011-05-06T22:32:48.883 に答える
1

これを見てください: 私が提起し、ディッキーがよく解決した回答

于 2011-03-21T15:25:20.303 に答える
0

私はこの例を独自性のために試しましたがemail address、以下のもので完全に機能します:

1]私の形で:

// Add an email element
    $this->addElement('text', 'email', array(
        'label'      => 'Email :',
        'required'   => true,
        'filters'    => array('StringTrim'),
        'validators' => array(
            'EmailAddress',
        )
    ));

これが私がunique email address仕事のために追加する必要があった特別なものです:

    $email = new Zend_Form_Element_Text('email');
    $email->addValidator('Db_NoRecordExists', true, array('table' => 'guestbook', 'field' => 'email'));

2]私のコントローラー:

$form->getElement('email')
     ->addValidator('Db_NoRecordExists',
                         false,
                         array('table' => 'guestbook',
                               'field' => 'email',
                               'exclude' => array ('field' => 'id', 'value' => $request->get('id'))));

if ($this->getRequest()->isPost()) {
        if ($form->isValid($request->getPost())) {

それがあなたの人々に役立つことを願っています!

ありがとう

于 2012-08-16T08:23:19.860 に答える
0

$form->getElement('input')->removeValidator('Zend_Validator_Db_NoRecordExists');除外を提供する代わりに呼び出すことができます。

于 2010-02-02T14:42:21.290 に答える