I have several contact forms through my site. The main one (from the "Contact" section) works through an action in my "Clients" controller, and I have several other forms in other pages (in views from other controllers, where I send the form to the main controller's action and then redirect to the original form), and everything works just fine. The email notifications are being sent and the records are being saved into my database.
The problem came after I implemented a Recaptcha plugin. The plugin works correctly (as in "if you check the recaptcha, it works as intended; if you don't, it displays an error message"), but when I'm using the "secondary" forms, instead of redirecting back to the original starting page, it always redirects me to the page for the main controller's action (and I loose the info at the hidden fields where I'm registering the specific form the client is currently using).
I tried deactivating the redirect, but that doesn't work. The user is still "brought" to the main controller's page.
Then I searched (in google and stack overflow) for some solution, and in a similar question there was the answer "save your current url into a session and load it for the redirection", and it made sense. However, when I tried saving it I found out the session is being saved after the process starts, so my session is saving the url after it jumps to the main action, instead of before submitting the form.
I tried saving the session in beforeFilter and beforeRender, and it still didn't work.
What can I do to save the url in the session before the form is submitted to the main action?
My main controller's action:
class ClientsController extends AppController
{
public function beforeFilter(\Cake\Event\Event $event)
{
parent::beforeFilter($event);
$route = $this->request->getParam('_matchedRoute');
$session = $this->request->getSession()->write('Origin',$route);
}
public function contact()
{
$cliente = $this->Clients->newEntity();
if ($this->request->is('post')) {
if ($this->Recaptcha->verify()) {
// Verify recaptcha
$client = $this->Clients->patchEntity($client, $this->request->getData());
if ($this->Clients->save($client)) {
$email = new Email();
$email->setProfile('default');
$email->setFrom($client->email)
->to('[email protected]')
->setSubject('Contact form sent from: ' . $client->source)
->setEmailFormat('both')
->setViewVars([
'source' => $client->source,
'name' => $client->first_name . ' ' . $cliente->last_name,
'company' => $client->company,
'localphone' => $client->local_phone,
'email' => $client->email,
'comments' => $client->comments
])
->viewBuilder()->setTemplate('default','default');
$email->send([$client->comments]);
$this->Flash->success('Youyr message has been sent. We'll contact you soon!');
$this->redirect($this->referer());
} else {
$this->Flash->error('There was a problem with your Contact form. Please, try again!');
}
} else {
// user failed to solve the captcha
$this->Flash->error('Please, check the Google Recaptcha before proceeding.');
$this->redirect($this->request->getSession()->read('Origin'));
}
}
}
}
(The recaptcha plugin is loaded at my AppController's Initialize.)
And as an example, one of the forms in another controller's view where I'm calling the main controller's action:
<?= $this->Form->create('client',['url' => ['controller' => 'clients','action' => 'contact']]); ?>
<?= $this->Form->hidden('source',['value' => 'Product page']) ?>
<?= $this->Form->control('first_name', ['label' => 'First name:','required' => true]) ?>
<?= $this->Form->control('last_name', ['label' => 'Last name:','required' => true]) ?>
<?= $this->Form->control('email', ['label' => 'Email:','required' => true]) ?>
<?= $this->Form->control('local_phone', ['label' => 'Local phone:','maxlength' => 10,'required' => true]) ?>
<?= $this->Form->control('comments', ['label' => 'Comentarios:', 'rows' => 3]) ?>
<?= $this->Recaptcha->display(); ?>
<?= $this->Form->button('Send') ?>
<?= $this->Form->end(); ?>
You could use JavaScript on the frontend to add an event listener to hook the form submit button click.
In your event listener, save the current URL of the window to sessionStorage in the browser.
Then let the submit click event pass to the default action.
This solution will store the URL before it is changed to have the form field contents added to it.
For future visitors, this solution involves use of the following JavasCript concepts which the OP is already across but can be researched seperately:
You could set the object your are listening to (the form submit button) in a number of ways. I usually give it an ID and specify the element using document.getElementById
More info: