Just starting out playing with CakePHP so please bear with me if this is an easy question.
I'm using CakePHP 2.4.0 and I want to reuse a specific form in multiple views. Therefore, I add this form to an view-element and include this element in each view.
This is the element.ctp file:
<?php
echo $this->Form->create('Lead', array('type' => 'post',
'url' => array('controller' => 'Lead', 'action' => 'index'),
'novalidate' => true));
echo $this->Form->input('name', array('label' => 'Achternaam'));
echo $this->Form->input('email', array('label' => 'Email'));
echo $this->Form->input('phone', array('label' => 'Telefoon'));
echo $this->Form->submit('submit', array('name' => 'submit'));
?>
This element is included in multiple views in the following way:
This is the home.ctp (a view) file:
<?php echo $this->element('element'); ?>
This is the LeadController.php file that receives the post operation from the form:
<?php
class LeadController extends AppController{
public function index(){
$this->autoRender = false;
if(!empty($_POST))
$this->Lead->save($this->request->data);
$this->redirect('/Pages/home');
}
}
?>
This is the Lead.php file that hodls all the validation checks.
class Lead extends AppModel{
public $useTable = 'Leads';
public $validate = array(
'email' => array(
'required' => array(
'rule' => array('notEmpty'),
'required' => true,
'message' => 'need email'
),
'validEmailRule' => array(
'rule' => array('email'),
'required' => true,
'message' => 'invalid emial'
)
),
'name' => array(
'required' => array(
'rule' => array('notEmpty'),
'required' => true,
'message' => 'need name'
)
),....
When the form in the view-element is completely valid, than the data from the form is successfully added to the database. But when the form is invalid, than the errors aren't returned to the view. If I write the following in the LeadController to the logfile than they are shown their.
$this->Lead->invalidFields();
If I add the code from LeadController/index to PagesController/home and change the form submit url, than the errors are shown in the view at each form-element.
What do you have to do to show the errors from a form in the view at each form-element, when the form is placed in a separate view-element and reused in multiple pages?
This has probably something to do with the fact that I use a redirect but I think their is a better way than saving the errors temporarily in a session.
This has probably something to do with the fact that I use a
redirect...
It's actually COMPLETELY to do with the fact that you use a redirect. By redirecting, you lose the validation errors.
There are as many ways to deal with this as your imagination can think of (and each has it's own merits depending on YOUR situation), but it is already widely asked/answered on the web:
CakePHP preserving validation errors after redirecting
http://bakery.cakephp.org/articles/binarycrafts/2010/01/20/persistentvalidation-keeping-your-validation-data-after-redirects-2
CakePHP: Keep validation data upon redirect
https://groups.google.com/forum/#!topic/cake-php/NsfckwSfY5c
Related
I've declared my validation fields of my view in this way:
public $validate = array(
'myField' => array(
'alphaNumeric' => array(
'rule' => 'alphaNumeric',
'required' => true,
'message' => 'username required'
),
'unique' => array(
'rule' => 'isUnique',
'required' => 'create',
'message' => 'Username already used'
)
)
);
Is there a way to know (inside the relative controller class) when this message is fired?
Because if one of these rules is violated, I would like to perform some tasks, and not simply show message to the user.
Yes, first set the data to the model in your controller:
$this->ModelName->set($this->request->data);
Then, to check if the data validates, use the validates method of the model, which will return true if it validates and false if it doesn’t:
if ($this->ModelName->validates()) {
// it validated logic
} else {
// didn't validate logic
$errors = $this->ModelName->validationErrors;
}
To know more about validationErrors, go to cakephp Validating Data from the Controller article.
I have a form in my ZF2 app with a CAPTCHA element as follows :
$this->add(array(
'type' => 'Zend\Form\Element\Captcha',
'name' => 'captcha',
'attributes' => array(
'class'=>'form-control',
),
'options' => array(
'label' => 'Please verify you are human.',
'captcha' => array('class' => 'Dumb')
),
));
I have an input filter attached to the form that validates the other elements in the form (name, email, message). When this is attached to the form the validation for the CAPTCHA field is ignored when checking if valid.
if ($request->isPost()) {
// set the filter
$form->setInputFilter($form->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) { ...
If i remove the input filter then the CAPTCHA field is validated correctly but obviously the other fields have no validators. What silly mistake am I making? Is there a "CAPTCHA" validator I have to set in the input filter?
The issue is because, I assume that on your form you have created a method called:
getInputFilter();
which overrides the original getInputFilter(),
there are two solutions:
rename your function on your form to be getInputFilterCustom()
and then modify also:
if ($request->isPost()) {
// set the filter
$form->setInputFilter($form->getInputFilterCustom());
or inside your current getInputFilter() add the logic to validate the captcha.
This is my code to add a captcha image control in a ZF2 form :
$this->add(array(
'name' => 'captcha',
'type' => 'Captcha',
'attributes' => array(
'id' => 'captcha',
'autocomplete' => 'off',
'required' => 'required'
),
'options' => array(
'label' => 'Captcha :',
'captcha' => new \Zend\Captcha\Image(array(
'font' => 'public/fonts/arial.ttf',
'imgDir' => 'public/img/captcha',
'imgUrl' => 'img/captcha'
))
),
));
The others form elements are using validators from the input filter, but i didn't use any validators to make it work.
I hope this can help you.
It is because you don't call the parent getInputFilter() within yours. Simply do
public function getInputFilter()
{
parent::getInputFilter();
//... your filters here
}
In my form model I have this:
class UpdateForm extends Form {
public function __construct($name = null) {
parent::__construct('updateForm');
$this->setAttribute('method','post');
$this->add(array(
'name' => 'response',
'attributes' => array(
'type' => 'textarea',
),
'options' => array(
'label' => 'Response',
),
));...
In my view I was doing this:
$form->get('response')->setAttributes(array(
'class' => 'form-control',
'placeholder' => '--- Enter your response here ---'
));
I found I can set the class of a specific form input in my Form model by just doing:
$this->add(array(
'name' => 'response',
'attributes' => array(
'type' => 'textarea',
'class' => 'fart',
),...
But now I wonder if this is wise. Should I do this in the view or does it matter (assuming I am trying to adhere to MVC best practices)
Both of the options are valid.
I am not sure which one best fits the MVC approach but here's what I do. If I am working in a team and if someone else is handling the design of the application, I will add these CSS classes in the view. So the designer can change them if he/she wants to.
If I am most likely to work with a developer I assign the CSS classes in the model. And leave a comment in the view pointing out the location of the file where the classes are assigned.
Hope this help.
I have created a Controller, a model and a view for this. I want to make a form in CakePHP. But this is not working and till now I cannot understand the reason why is this happening...
My code for the controller is:
class MlistsController extends AppController {
public $helpers = array('Html','Form');
public function create() {
if ($this->request->is('post')) {
if ($this->Mlist->save($this->request->data)) {
$this->Session->setFlash(__('okay..'));
$this->redirect('action' => 'index');
}
}
}
}
My Model is:
App::uses('AuthComponent', 'Controller/Component');
class MList extends AppModel {
public function beforeSave($options = array()) {
if (isset($this->data[$this->alias]['password'])) {
$this->data[$this->alias]['password'] = AuthComponent::password($this->data[$this->alias]['password']);
}
return true;
}
public $validate = array(
'listname' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'A listname '
)
),
'replyto' => array(
'required' => array(
'rule' => array('notEmpty'),
'email' => 'email'
)
),
'fromName' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'Your name'
)
),
'subject' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'A subject '
)
),
'reminder' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'A reminder '
)
),
'contactsfile' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'custom message'
)
));
}
And my view file create.ctp is:
<h2>Create new list</h2>
<?php
$this->Form->create('Mlist');
echo $this->Form->input('listname',array('label' => 'Your ListName:'));;
echo $this->Form->input('replyto',array('label' => 'Reply To email:'));
echo $this->Form->input('fromName',array('label' => 'From Name:'));
echo $this->Form->input('subject',array('label' => 'mail subject:'));
echo $this->Form->input('reminder',array('label' => 'Reminder'));
echo $this->Form->input('contactsfile',array('label' => 'Upload your file','type' => 'file'));
echo '<br />';
echo $this->Form->end('submit');
Finally, the Submit button of the form is not even green, but grey and does not function when I click it. Also the star symbol (*) is not showing apart the form labels where the fields are required...
Can you help me with this issue?
You're kind of bypassing Cake's 'Convention over configuration' paradigm.
In order for these conventions to work Cake uses the Inflector Class which handles the plural forms of English words.
So when you use an appropriate (to this convention) naming policy it will work for you "out of the box". Otherwise you will have to configure the Model, Controller and any Helpers/Components/Behaviours you're using. They all have configuration parameters for this, but there is not a big point in doing this static configuration with Cake since you will also have to go through it again if you rename a DB table for example.
I's just against the idea of Cake. If you need to do this just use some other configuration based framework.
I believe the problem is in your view. You also have to echo the starting of the form:
echo $this->Form->create('Mlist');
The naming convention is ok. Cake doesn't have any database of real english words, only few irregularities (see arrays in http://api.cakephp.org/2.3/source-class-Inflector.html) so anything like Mlist is just pluralized with adding "s" at the end.
I have a cakephp form that has validation. The validation itself works BUT when an error shows up after clicking submit, it just produces some text.
Why am I getting no colour. eg Its meant to display errors in red.
Controller
<div class="users form">
<?php echo $this->Form->create('Ticket'); ?>
<fieldset>
<legend><?php echo __('Purchase'); ?></legend>
<?php
echo $this->Form->input('first_name');
echo $this->Form->input('last_name');
echo $this->Form->input('email');
echo $this->Form->input('phone');
echo $this->Form->input('date', array('options'=> $dates));
echo $this->Form->input('quantity', array('options' => $maxAmount, 'default' => '1'));
?>
</fieldset>
<?php
echo $this->Form->end(__('Purchase'));
?>
</div>
Model
public $validate = array(
'first_name' => array(
'rule' => '/^[a-zA-Z]{1,}$/i',
'message' => 'Alphabets only',
'required' => true
),
'last_name' => array(
'rule' => '/^[a-zA-Z]{1,}$/i',
'message' => 'Alphabet only',
'required' => true
),
'phone' => array(
'rule' => 'numeric',
'message' => 'numbers only please',
'required' => true
),
'email' => array(
'rule' => 'email',
'message' => 'Your email is not valid',
'required' => true
),
'quantity' => array(
'rule' => 'numeric',
'message' => 'numbers only please',
'required' => true
)
);
Did you include a stylesheet in your default.ctp? If you removed the default CakePHP stylesheet from your default.ctp layout, the default colours will no longer be there.
You need to either include the CakePHP stylesheet again in your layout (here you can see how it was in the original default.ctp: https://github.com/cakephp/cakephp/blob/master/app/View/Layouts/default.ctp#L33)
Or create your own CSS styles in your stylesheet. You can use the styles from the default CakePHP stylesheet as an example;
https://github.com/cakephp/cakephp/blob/master/app/webroot/css/cake.generic.css#L371
There is nothing wrong with your code. That is just how CakePHP is handling the error reporting. The red stuff is reserved for major errors like missing view, or a missing function, or cant connect to the database. Basically stuff that would generate a status code that is in the range of 400.
I did some searching to answer your question better, but i stumbled on this page.
CakePHP 2.0 - How to make custom error pages?
Its all about what status code CakePHP will generate when u do something wrong.
Validation errors will I think throw even an OK (200) but wont write anything to the database. Happened a couple a times to me.