Sending form errors back to view via redirect - cakephp

I recently started picking up on CakePHP and now I'm trying to build a contact form for my site.
It seems to work in validating the forms, but there's something I want to do now.
I want it to show any errors that occur (like missing a required field).
However, I want it to show 2 different possible states:
- A user error (user forgot a field or the field doesn't meet the requirements), show this below the field (using Bootstrap 4)
- A server error (mail couldn't send from the server - for example, the SMTP server is down), shown using the Flash
I've been searching far and wide for this, but I couldn't get any further on this without posting a question myself.
Below is all the code that I'm using (running CakePHP 3.6)
src/Template/Pages/contact.ctp (controlled by the PagesController):
<div class="container">
<div class="row no-banner">
<div class="col-md-6">
<h4>Contact Form</h4>
<div style="padding-bottom:25px;">
Got a question? we'd love to hear it from you!<br />
Send us a message and we'll respond as soon as possible!
</div>
<?= $this->Flash->render(); ?>
<?= $this->Form->create("Contact",array("url"=>"/contact","class"=>"contact-form","id"=>"contact-form")); ?>
<?= $this->Form->control("name",array("placeholder"=>"Your Name","label"=>false,"class"=>"form-control")); ?>
<?= $this->Form->control("email",array("placeholder"=>"Your Email","label"=>false,"class"=>"form-control")); ?>
<?= $this->Form->control("subject",array("placeholder"=>"The Subject","label"=>false,"class"=>"form-control")); ?>
<?= $this->Form->textarea("message",array("placeholder"=>"Your Message","label"=>false,"class"=>"form-control")); ?>
<?= $this->Form->button('Submit',array("class"=>"btn")); ?>
<?= $this->Form->end(); ?>
</div>
<div class="col-md-6">
<h4>Social Media</h4>
<div style="padding-bottom:25px;">
We are active on a variety of of social media, feel free to like and follow us!
</div>
<i class="fab fa-facebook social-media-icon"></i>
<i class="fab fa-discord social-media-icon"></i>
<?= $this->Form->errors; ?>
</div>
</div>
</div>
src/Controller/ContactController.php:
<?php
namespace App\Controller;
use App\Controller\AppController;
use App\Form\ContactForm;
class ContactController extends AppController {
public function add() {
$contact = new ContactForm();
if ($this->request->is('post')) {
if ($contact->execute($this->request->getData())) {
$this->Flash->success('We will get back to you asap!');
$this->redirect($this->referer());
} else {
$this->Flash->error('There was an issue sending your mail. Please try again later!');
$this->redirect($this->referer());
}
}
$this->set('contact', $contact);
}
}
src/Form/ContactForm.php:
<?php
namespace App\Controller;
use App\Controller\AppController;
use App\Form\ContactForm;
class ContactController extends AppController {
public function add() {
$contact = new ContactForm();
if ($this->request->is('post')) {
if ($contact->execute($this->request->getData())) {
$this->Flash->success('We will get back to you asap!');
$this->redirect(array('controller' => 'Pages','action' => 'display','contact'));
} else {
$this->Flash->error('There was an issue sending your mail. Please try again later!');
$this->redirect($this->referer());
}
}
$this->set('contact', $contact);
}
}

Don't redirect, because you don't need to. Instead of using the Pages controller to display the form put the form in your controllers view: /Contacts/add.ctp. No need to call redirect() then.
The errors are already added to the form and the form helper will find them because you're passing the form object to Form->create().
If you want to make it more complicated than needed stick to your implementation and simply write the errors to the session and in the action that receives it read them from the session and set them to the form object via setErrors().

Related

Cakephp 4 can't change locales

I'm trying to set two buttons so depending of the language user can switch to the other.
In my default.php I have this, to change on click on the link AppController:
<li class="nav-item">
<?php
if (I18n::getLocale() !== 'en_US'){ ?>
<?= $this->Html->link('EN', ['action' => 'changeLang']); ?>
<?php
}else{ ?>
<?= $this->Html->link('ES', ['action' => 'changeLang']); ?>
<?php } ?>
</li>
My AppController
public function changeLang():void
{
if (I18n::getLocale() !== 'en_US'){
I18n::setLocale('en_US');
}else{
I18n::setLocale('es_ES');
}
$this->redirect($this->referer());
}
My default.po (in locales/es/default.po)
#: ./src/Controller/AddressController.php:72
#: ./src/Controller/UserController.php:81
msgid "Usuario registrado."
msgstr "Registered user."
It goes in the correct lines but the code doesn't change. What I'm doing wrong?
I used var_char to see if it pass the ifs correctly and it does.
A also change the app.php in config to from
'defaultLocale' => env('APP_DEFAULT_LOCALE', 'en_US'),
to
'defaultLocale' => env('APP_DEFAULT_LOCALE', 'es_ES'),
and it also works.
If I use I18n::setLocale('es_ES'); on AppController inicialize it works, so why does it not work in my function?
I18n::setLocale is a per-request setting. You're not doing anything in the code shown to save it to a session or cookie, so it will only ever be set to the default value when starting up, or to your specified value just before redirecting (which starts a new request, which resets to the default value).

Missing Controller not reading dropbox add function Cakephp Getting View Model not found

I have the follow code in my Controller, which is getting values from the dropbox chooser.
<?php class DropboxboxfilesController extends AppController {
public function add() {
if ($this->request->is('post')) {
$this->request->input('json_decode');
$this->Dropboxfile->create();
if ($this->Dropboxfile->save($this->request->data)) {
$this->Session->setFlash(__('Your file has been liberated :)'));
$this->redirect($this->referer());
} else {
$this->Session->setFlash(__('Something went wrong!'));
}
}
}}?>
However, when I am getting the error that the add function does not exist when I hit submit on the submit button for the chooser.
I have tried several things but nothing seems to be working so far.
EDIT:
View code
<?php echo $this->Form->create('Dropboxfile', array ('array' => 'file')); ?>
<input type="dropbox-chooser" name="selected-file" style="visibility: hidden;"/>
<?php echo $this->Form->end('Finish'); ?>
The dropbox code I am using https://www.dropbox.com/developers/dropins/chooser/js
EDIT
<form action="/cake/homes" array="file" id="DropboxfileIndexForm" method="post" accept- carset="utf-8"><div style="display:none;"><input type="hidden" name="_method" value="POST"/></div><input type="dropbox-chooser" name="selected-file" style="visibility: hidden;"/>
<div class="submit"><input type="submit" value="Finish"/></div></form
You're using the wrong format for your second argument in $this->Form->create(). Notice how, in your parsed form element, it has an invalid 'array="file"' element and the action does not lead to the add action. Try this instead:
<?php
echo $this->Form->create(
'Dropboxfile',
array(
'url' => array('action' => 'add'),
'type' => 'file'
)
);
?>

Passing data via POST from an element to controller/model Cakephp

I am pretty new to cakephp, I have an uploader form and would like to pass all of the data using POST to the controller and model so that it will save to the database. So far there are no cakephp errors occuring but no data is being passed.
Controller Code:
<?php class Controller extends AppController {
public function add() {
if ($this->request->is('post')) {
$this->File->create();
if ($this->File->save($this->request->data)) {
$this->Session->setFlash(__('Your file has been liberated :)'));
$this->redirect($this->referer());
} else {
$this->Session->setFlash(__('Something went wrong!'));
}
}
}
}?>
View Code:
<?php echo $this->Form->create('File'); ?>
<input type="uploader" name="selected-file" style="visibility: hidden;"/>
<?php echo $this->Form->end('Finish'); ?>
Model Code:
<?php class File extends AppModel {}
?>
Please, check input specification you can see there, that there are no "uploader" value for type attribute. Maybe you mean type="file".
Also, if you want to upload files, please, use
echo $this->Form->create('File', array('type' => 'file'));
this will produce correct enctype attribute enctype="multipart/form-data". such enctype needed if you send files by POST.
Also, you use style: style="visibility: hidden;" which should hide file input field, so, maybe you use some flash uploader or ajax, but this is not demonstrated in your code. If you provide more code, we can provide more concrete help to you.
and counter question: how you debug your code?

Yii file upload is not validating file type

I am validating the file type to be uploaded. The validation rule does not seem to work. I only want to accept jpg files but when I try putting pdf files, it still accepts it and does not give any error. Please help. I don't know what I'm doing wrong.
View:
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'document-form',
'enableAjaxValidation'=>true,
'enableClientValidation'=>true,
'clientOptions'=>array('validateOnSubmit'=>true), //This is very important
'htmlOptions'=>array('enctype'=>'multipart/form-data'),)); ?>
<p class="note">Fields with <span class="required">*</span> are required.</p>
<?php echo $form->errorSummary($model); ?>
<div class="row">
<?php echo $form->labelEx($model,'barangay_clearance'); ?>
<?php echo $form->fileField($model,'barangay_clearance'); ?>
<?php echo $form->error($model,'barangay_clearance'); ?>
</div>
<div class="row buttons">
<?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>
</div>
<?php $this->endWidget(); ?>
Model:
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('barangay_clearance', 'file', 'allowEmpty'=>true, 'types'=>'jpg', 'message'=>'Jpg files only', 'on'=>'insert'),
array('barangay_clearance, barangay_status, zoning_clearance, zoning_status, sanitary_clearance, sanitary_status, occupancy_permit, occupancy_status, fire_safety, fire_safety_status', 'safe'),
// The following rule is used by search().
// Please remove those attributes that should not be searched.
array('document_id, business_id, barangay_clearance, barangay_status, zoning_clearance, zoning_status, sanitary_clearance, sanitary_status, occupancy_permit, occupancy_status, fire_safety, fire_safety_status', 'safe', 'on'=>'search'),
);
}
Controller: (Note: I haven't really changed the controller yet except for activating the ajaxvalidation function and creating an instance of another model)
public function actionCreate($id)
{
$model=new Document;
$busModel = Business::model()->findByPk($id);
// Uncomment the following line if AJAX validation is needed
$this->performAjaxValidation($model);
if(isset($_POST['Document']))
{
$model->attributes=$_POST['Document'];
if($model->save())
$this->redirect(array('view','id'=>$model->document_id));
}
$this->render('create',array(
'model'=>$model,
'busModel'=>$busModel,
));
}
This should work perfectly.
array('barangay_clearance', 'file','types'=>'jpg', 'allowEmpty'=>true, 'on'=>'update', 'on'=>'insert'),
You didn't assign any scenario to model. If model you use in form widget is instance of Document then this:
$model=new Document;
has to be replaced with this:
$model=new Document('insert');
since rule declaration
array('barangay_clearance', 'file', 'allowEmpty'=>true, 'types'=>'jpg', 'message'=>'Jpg files only', 'on'=>'insert'),
says that it will be applied only on "insert" scenario.
I hope it helps.

How to use tinymce plugin?

I have tried many times to use this plugin and I failed.
I am following documentation, but it does not work for me.
I am posting the simple code here, to know what wrong I am doing.
1-I put this plugin in this folder app/plugins
2- I add TinyMce helper to articles_controller
<?php
class ArticlesController extends AppController {
// good practice to include the name variable
var $name = 'articles';
// load any helpers used in the views
var $helpers = array('Html', 'Form','TinyMce.TinyMce');
/**
* index()
* main index page of the formats page
* url: /formats/index
*/
function index(){
// get all formats from database where status = 1
$articles = $this->Article->find("all") ;
$this->set('articles', $articles);
}
function admin_add() {
// if the form data is not empty
if (!empty($this->data)) {
// initialise the format model
$this->Article->save($this->data);
// set a flash message
$this->Session->setFlash('The Format has been saved');
// redirect
$this->redirect(array('action'=>'index'));
} else {
// set a flash message
$this->Session->setFlash('The Format could not be saved. Please, try again.','default', array('class' => 'flash_bad'));
}
}
}
?>
3- in the view file articles/admin_add.ctp I added the editor
// i think the problem in this code
<?php $this->TinyMce->editor(array(
'theme' => 'advanced'
)); ?>
<div class="formats form">
<?php echo $form->create('Article');?>
<fieldset>
<legend>Add a article</legend>
<?php
// create the form inputs
echo $this->Form->input('title');
echo $this->Form->input('content'); ?>
</fieldset>
<?php echo $form->end('Add');?>
</div>
<ul class="actions">
<li><?php echo $html->link('List Articles', array('action'=>'index'));?></li>
</ul>
You need to put tinymce files into your js assets
Then you have to add into section of your layout.
Then you'll need to init tinymce according to example provided on tinymce website (ex: full tinymce layout) and configure it according to your requirements.
I'd personally would not rely on such cake plugins, when actions required to get things working are not many and they are simple enough.

Resources