Two forms from one model both forms validate when

2019-09-18 23:48发布

问题:

I have to use a form once in footer and in individual page i.e. index.ctp. For that I have a database table named contactforms. I have created a model Contactform.php

<?php
App::uses('AppModel', 'Model');
/**
 * Contactform Model
 *
 */
class Contactform extends AppModel {
/**
 * Validation rules
 *
 * @var array
 */
      var $useTable = false;

    public $validate = array(
        'firstname' => array(
            'notempty' => array(
                'rule' => array('notempty')             
            )
        ),
        'contactno' => array(
            'notempty' => array(
                'rule' => array('notempty')             
            )
        ),
        'email' => array(
            'notempty' => array(
                'rule' => array('notempty')         
            )
        )
    );
}
?>

I have a controller from where I am trying to send an email

<?php
App::uses('AppController', 'Controller');
App::uses('CakeEmail', 'Network/Email');

class ContactformsController extends AppController {


    public function index() {
        $this->Contactform->recursive = 0;
        $this->set('contactforms', $this->paginate());
    }


        public function contact() {

        $email = new CakeEmail();
            if(isset($this->params['requested']) && $this->params['requested']==true)
    {
         if ($this->request->is('post')) 
            {
             $this->Contactform->set($this->request->data);
                if($this->Contactform->save($this->request->data)) 
                {
                 $name=$this->request->data['Contactform']['firstname'];
                 $lastname=$this->request->data['Contactform']['lastname'];
                 $contact=$this->request->data['Contactform']['contactno'];
                 $mail= $this->request->data['Contactform']['email'];
                 $email->from(array($mail => $name));
                     $email->to('abc@gmail.com');                      
                     $message= $this->request->data['Contactform']['message'];
                     $email->subject('Wombats contact form information');        
                 if($email->send($message))
                 {
                    $this->Session->setFlash('Quote Processed..Thank You For Visiting Our Website!!!');
                                     $this->redirect($this->referer());
                    }   
                    }
                 }

               }
        }
}
?>

And then I created an element which I used called in footer and then in index file. contact.ctp looks like

<?php echo $this->Html->css('contactfooter.css');?>

<?php $contactforms = $this->requestAction('Contactforms/contact') ?>
<div class="frm">
<?php echo $this->Form->create('Contactform'); ?> 
<div class="firstrow">
    <div class="first">
        <?php echo $this->Form->input('firstname',array('label'=>false,'placeholder'=>'firstname','div'=>'firstname','style'=>'width:130px; height:20px;' ));?>
        <?php // echo $this->Form->input('firstname',array('label'=>false,'placeholder'=>'firstname','style'=>'width:130px; height:20px; float:left; margin-right:5px;','error'=>array('attributes'=>array('wrap'=>'div','class'=>'errorfirst'))));?>
    </div>
    <div class="second">
        <?php echo $this->Form->input('lastname',array('label'=>false,'placeholder'=>'lastname','div'=>'lastname','style'=>'width:140px; height:20px; '));?>
    </div>   
</div>
<!--<div class="secondrow">-->
<?php echo $this->Form->input('contactno',array('label'=>false,'placeholder'=>'contactno','div'=>'contactno','style'=>'width:270px; height:20px; margin-bottom:10px;'));?>
<!--</div>-->

<?php echo $this->Form->input('email',array('label'=>false,'placeholder'=>'email','div'=>'email','style'=>'width:270px; height:20px; '));?>
<?php echo $this->Form->input('message',array('label'=>false,'placeholder'=>'message','div'=>'message','style'=>'width:270px; height:25px;margin-top:10px; '));?>
</div>
<!--<br>-->
<div class="sub">
<?php echo $this->Form->end('SUBMIT'); ?> 
    </div>

When I click submit of one form other form as well validates. I tried a lot but don't know how to fix Can anyone please help.

EDIT:- @Nunser I am very confused with these names sorry for that. I have changed my code according to what u told but still its validating one form only. I have a doubt, according to you I should change in view and elements too but I just have elements.Please can u help I am posting my edited code

I called element from index page as

<?php echo $this->element('Contactform/contact',array('source'=>'index')); ?>\

and from default page as

<?php echo $this->element('Contactform/contact'); ?>

my controller action is

public function contact() {

        $email = new CakeEmail();

        if(isset($this->params['requested']) && $this->params['requested']==true){

        if ($this->request->is('post')) 

        {
            $index = 'Contactform';
            if (isset($this->request->data['Contactformindex']))
                $index = 'Contactformindex';

        $this->Contactform->set($this->request->data[$index]);

        if($this->Contactform->save($this->request->data[$index])) 

        {

        $name=$this->request->data[$index]['firstname'];

        $lastname=$this->request->data[$index]['lastname'];

        $contact=$this->request->data[$index]['contactno'];

        $mail= $this->request->data[$index]['email'];

        $email->from(array($mail => $name));



        $email->to('skyhi13@gmail.com');               

                $message= $this->request->data[$index]['message'];

                $email->subject('Wombats contact form information');

        //$email->send($message);

        if($email->send($message))

        {
        $this->Session->setFlash('Quote Processed..Thank You For Visiting Our Website!!!');

        //$this->render('/view/elements/quotes/quoteform.ctp');

//        $this->autoRender=FALSE;

        $this->redirect($this->referer());

        }    


        }
        else {
            $this->set('formName',$index);
        }

      }

          }

        }

In the elements ctp file I changed as

<?php if (!empty($this->validationErrors['Contactform'])) {
     $this->validationErrors[$formName] = $this->validationErrors['Contactform'];
}?>
<div class="frm">
<?php
    if(isset($source)&& $source == 'index')
        echo $this->Form->create('Contactformindex'); 
    else
        echo $this->Form->create('Contactform'); 
 ?>   
<div class="firstrow">
    <div class="first">
        <?php echo $this->Form->input('firstname',array('label'=>false,'placeholder'=>'firstname','div'=>'firstname','style'=>'width:130px; height:20px;' ));?>
        <?php // echo $this->Form->input('firstname',array('label'=>false,'placeholder'=>'firstname','style'=>'width:130px; height:20px; float:left; margin-right:5px;','error'=>array('attributes'=>array('wrap'=>'div','class'=>'errorfirst'))));?>
    </div>
    <div class="second">
        <?php echo $this->Form->input('lastname',array('label'=>false,'placeholder'=>'lastname','div'=>'lastname','style'=>'width:140px; height:20px; '));?>
    </div>   
</div>
<!--<div class="secondrow">-->
<?php echo $this->Form->input('contactno',array('label'=>false,'placeholder'=>'contactno','div'=>'contactno','style'=>'width:270px; height:20px; margin-bottom:10px;'));?>
<!--</div>-->

<?php echo $this->Form->input('email',array('label'=>false,'placeholder'=>'email','div'=>'email','style'=>'width:270px; height:20px; '));?>
<?php echo $this->Form->input('message',array('label'=>false,'placeholder'=>'message','div'=>'message','style'=>'width:270px; height:25px;margin-top:10px; '));?>
</div>
<!--<br>-->
<div class="sub">
<?php echo $this->Form->end('SUBMIT'); ?> 
    </div>

Using this code still it validated one form only and form is that which I have called without source as index and when clicked on index submit button it validates the other form. I am not sure as do I have to use the same Fromindex name as specified by you, does that matter. I am not able to find as where I am going wrong.Please help and Thanks in advance.

回答1:

First, why are you doing this

<?php $contactforms = $this->requestAction('Contactforms/contact') ?>

in your element? I don't see the use of that requestAction except slowing down the processing...

Ok, but your problem...
Since you're calling an element, there's no easy way to avoid the validation of both forms. Usually, when there are two forms corresponding to the same model, the way to not validate both is to change the "name" of the form like this

<!--in the first form-->
<?php echo $this->Form->create('Contactform1'); ?> 
<!--in the second form-->
<?php echo $this->Form->create('Contactform2'); ?> 

But, since you are creating that form with an element, there's no easy way of changing the name of the form in one place and not in the other...

So this is what you should do (there may be other ways of doing what you want, but this is the one I can think of). When you call the contact.ctp element, pass a variable to it

echo $this->element('contact', array(
   "source" => "index"
));

With that, you know you're calling the element from the index.ctp, for example. Then, in the element, change the form declaration depending on the variable

//the beginning of your element
<?php
    if (isset($source) && $source == 'index')
      echo $this->Form->create('FromIndex');
    else
      echo $this->Form->create('FromContact');
?>

You'll also need to modify your action, to read the data in FromIndex or in FromContact, depending on where it came from

public function contact() {

   $email = new CakeEmail();
   if(isset($this->params['requested']) && $this->params['requested']==true)  {
     if ($this->request->is('post'))  {

        //change the index of the array depending on where it came form
        $index = 'FromContact';
        if (isset($this->request->data['FromIndex']))
           $index = 'FromIndex';

         $this->Contactform->set($this->request->data[$index]);
            if($this->Contactform->save($this->request->data[$index])) 
            {
             $name=$this->request->data[$index]['firstname'];
             $lastname=$this->request->data[$index]['lastname'];
             $contact=$this->request->data[$index]['contactno'];
             $mail= $this->request->data[$index]['email'];
             $email->from(array($mail => $name));
                 $email->to('abc@gmail.com');                      
                 $message= $this->request->data[$index]['message'];
                 $email->subject('Wombats contact form information');        
             if($email->send($message))
             {
                $this->Session->setFlash('Quote Processed..Thank You For Visiting Our Website!!!');
                                 $this->redirect($this->referer());
                }   
                }
             }

           }
    }
}

When you save or set something (unless is with saveAssociated, saveAll or those kind of functions, when you're saving more than one model), there's no need to specify the model in the array to be saved.

$saveMe = array('User'=>array('name'=>'John'));
$saveMeToo = array('name'=>'John');
$this->User->save($saveMe); //will work
$this->User->save($saveMeToo); //will work too

That's why the change of $this->request->data indexes will work either way. But the validation will be for the specific index (FromContact or FromIndex).

Note: I haven't tested the code, so be sure to check for missing parenthesis, unclosed ' and those kind of things.

EDiT
@winnie pointed out that the validation only happened for one form, and that's because I overlooked something. The validation errors get displayed in the view if there's something set in this variable $this->validationErrors['ModelName'] in the view. And that's what I missed. So, re-change the action to pass the $index of the model to the view, so the view knows which form called the action, like this

public function contact() {

   $email = new CakeEmail();
   if(isset($this->params['requested']) && $this->params['requested']==true)  {
     if ($this->request->is('post'))  {

        //change the index of the array depending on where it came form
        $index = 'FromContact';
        if (isset($this->request->data['FromIndex']))
           $index = 'FromIndex';

         $this->Contactform->set($this->request->data[$index]);
            if($this->Contactform->save($this->request->data[$index])) 
            {
                //this if is exactly the same as the other one
            } else {
                //now, if there's no save, there's some validation errors
                //tell the view which form called this save
                $this->set('formName', $index);

            }
    }
}

Now in the view you need to copy the errors you get in the model, to the "fake model name" we gave the form. In the first line of your view do this (and in the element too)

if (!empty($this->validationErrors['Contactform'])) {
     $this->validationErrors[$formName] = $this->validationErrors['Contactform'];
}