I'm hoping someone can point me in the right direction here. This is my first Symfony project, and I'm stumped on why the form won't validate.
To test the application, I fill out all of the form inputs and click the submit button and it fails to validate every time. No idea why.
Any help will be appreciated!
The view -- modules/content/templates/commentSuccess.php :
<?php echo $form->renderFormTag('/index.php/content/comment') ?>
<table>
<?php echo $form['name']->renderRow(array('size' => 25, 'class' => 'content'), 'Your Name') ?>
<?php echo $form['email']->renderRow(array('onclick' => 'this.value = "";'), 'Your Email') ?>
<?php echo $form['subject']->renderRow() ?>
<?php echo $form['message']->renderRow() ?>
<tr>
<td colspan="2">
<input type="submit" />
</td>
</tr>
</table>
</form>
The controller -- modules/content/actions/actions.class.php :
public function executeComment($request)
{
$this->form = new ContentForm();
// Deal with the request
if ($request->isMethod('post'))
{
$this->form->bind($request->getParameter("content"));
if ($this->form->isValid())
{
// Do stuff
//$this->redirect('foo/bar');
echo "valid";
}
else
{
echo "invalid";
}
}
}
The form -- /lib/form/ContentForm.class.php :
class ContentForm extends sfForm {
protected static $subjects = array('Subject A', 'Subject B', 'Subject C');
public function configure()
{
$this->widgetSchema->setNameFormat('content[%s]');
$this->widgetSchema->setIdFormat('my_form_%s');
$this->setWidgets(array(
'name' => new sfWidgetFormInputText(),
'email' => new sfWidgetFormInput(array('default' => 'me#example.com')),
'subject' => new sfWidgetFormChoice(array('choices' => array('Subject A', 'Subject B', 'Subject C'))),
'message' => new sfWidgetFormTextarea(),
));
$this->setValidators(array(
'name' => new sfValidatorString(),
'email' => new sfValidatorEmail(),
'subject' => new sfValidatorString(),
'message' => new sfValidatorString(array('min_length' => 4))
));
$this->setDefaults(array(
'email' => 'me#example.com'
));
}
}
Thanks in advance! I'll edit this post as needed during progress.
EDIT
I've changed my view code to this:
<?php echo $form->renderFormTag('/frontend_dev.php/content/comment') ?>
<table>
<?php if ($form->isCSRFProtected()) : ?>
<?php echo $form['_csrf_token']->render(); ?>
<?php endif; ?>
<?php echo $form['name']->renderRow(array('size' => 25, 'class' => 'content'), 'Your Name') ?>
<?php echo $form['email']->renderRow(array('onclick' => 'this.value = "";'), 'Your Email') ?>
<?php echo $form['subject']->renderRow() ?>
<?php echo $form['message']->renderRow() ?>
<?php if ($form['name']->hasError()): ?>
<?php echo $form['name']->renderError() ?>
<?php endif ?>
<?php echo $form->renderGlobalErrors() ?>
<tr>
<td colspan="2">
<input type="submit" />
</td>
</tr>
</table>
</form>
This gives a required error on all fields, and gives " csrf token: Required.
" too.
My controller has been updated to include $this->form->getCSRFToken(); :
public function executeComment($request)
{
$this->form = new ContentForm();
//$form->addCSRFProtection('flkd445rvvrGV34G');
$this->form->getWidgetSchema()->setNameFormat('contact[%s]');
$this->form->getCSRFToken();
// Deal with the request
if ($request->isMethod('post'))
{
$this->form->bind($request->getParameter("content[%s]"));
if ($this->form->isValid())
{
// Do stuff
//$this->redirect('foo/bar');
echo "valid";
}
else
{
$this->_preWrap($_POST);
}
}
}
Still don't know why it's giving me an error on all fields and why I'm getting the csrf token: Required.
When you take full control of a Symfony form, as you are doing according to the code snippets in your OP, you will have to manually add the error and csrf elements to your form:
// Manually render an error
<?php if ($form['name']->hasError()): ?>
<?php echo $form['name']->renderError() ?>
<?php endif ?>
<?php echo $form['name']->renderRow(array('size' => 25, 'class' => 'content'), 'Your Name') ?>
// This will echo out the CSRF token (hidden)
<?php echo $form['_csrf_token']->render() ?>
Check out Symfony Docs on custom forms for more info. Also, be sure to add CSRF back to your form, there is no reason to leave it out, and will protect from outside sites posting to your forms.
It might be wise to render any global form errors:
$form->renderGlobalErrors()
Don't you have a typo in your executeComment function ?
$this->form->getWidgetSchema()->setNameFormat('contact[%s]');
and later:
$this->form->bind($request->getParameter("content[%s]"));
You should write:
$this->form->getWidgetSchema()->setNameFormat('content[%s]');
But this line is not necessary you can delete it (the NameFormat is already done in your form class).
And the $request->getParameter("content[%s]") will not word ("content[%s]" is the format of the data sent by the form), you should use:
$this->form->bind($request->getParameter("content"));
Or best, to avoid this kind of typo:
public function executeComment($request)
{
$this->form = new ContentForm();
// Deal with the request
if ($request->isMethod('post'))
{
$this->form->bind($request->getParameter($this->form->getName()));
if ($this->form->isValid())
{
// Do stuff
//$this->redirect('foo/bar');
echo "valid";
}
else
{
$this->_preWrap($_POST);
}
}
}
I ran into the same problem with an admin generated backend form. When I tried to apply css schema changes with this code, it broke the token. It didn't break right away. That signals to me this is a bug in Symfony 1.4
$this->setWidgetSchema(new sfWidgetFormSchema(array(
'id' => new sfWidgetFormInputHidden(),
'category' => new sfWidgetFormDoctrineChoice(array('model' => $this->getRelatedModelName('RidCategories'), 'add_empty' => false)),
'location_id' => new sfWidgetFormInputText(),
'title' => new sfWidgetFormInputText(array(), array('class' => 'content')),
'content' => new sfWidgetFormTextarea(array(), array('class' => 'content')),
'content_type' => new sfWidgetFormInputText(),
'schedule_date' => new sfWidgetFormInputText(),
'post_date' => new sfWidgetFormInputText(),
'display_status' => new sfWidgetFormInputText(),
'parent_id' => new sfWidgetFormInputText(),
'keyword' => new sfWidgetFormInputText(),
'meta_description' => new sfWidgetFormInputText(),
'update_frequency' => new sfWidgetFormInputText(),
'keywords' => new sfWidgetFormInputText(),
'allow_content_vote' => new sfWidgetFormInputText(),
'rating_score' => new sfWidgetFormInputText()
)));
Related
I'm reviewing a basic contact form which is not associated with any model. I would like some advice on the best way to leverage Cake's automatic view rendering of field errors for this situation.
Controller
Performs validation through a custom Validator.
public function index()
{
if ($this->request->is('post')) {
// Validate the form
$validator = new EnquiryValidator();
$data = $this->request->data();
$errors = $validator->errors($data);
if (empty($errors)) {
// Send email, etc.
// ...
// Refresh page on success
}
// Show error
$this->Flash->error('Unable to send email');
}
}
View
<?= $this->Form->create(); ?>
<?= $this->Form->input('name', [
'autofocus' => 'autofocus',
'placeholder' => 'Your name',
'required'
]);
?>
<?= $this->Form->input('email', [
'placeholder' => 'Your email address',
'required'
]);
?>
<?= $this->Form->input('subject', [
'placeholder' => 'What would you like to discuss?',
'required'
]);
?>
<?= $this->Form->input('message', [
'label' => 'Query',
'placeholder' => 'How can we help?',
'cols' => '30',
'rows' => '10',
'required'
]);
?>
<div class="text-right">
<?= $this->Form->button('Send'); ?>
</div>
<?= $this->Form->end(); ?>
Currently the form will not show any errors next to the input fields. I assume it's because there is no entity associated with the form or something like that, but I'm not sure.
What is the best solution? Can the validation be performed in a better way to automatically provide field errors in the view?
Modelless forms
Use a modelless form. It can be used to validate data and perform actions, similar to tables and entities, and the form helper supports it just like entities, ie, you simply pass the modelless form instance to the FormHelper::create() call.
Here's the example from the docs, modified a little to match your case:
src/Form/EnquiryForm.php
namespace App\Form;
use App\...\EnquiryValidator;
use Cake\Form\Form;
use Cake\Form\Schema;
use Cake\Validation\Validator;
class EnquiryForm extends Form
{
protected function _buildSchema(Schema $schema)
{
return $schema
->addField('name', 'string')
->addField('email', ['type' => 'string'])
->addField('subject', ['type' => 'string'])
->addField('message', ['type' => 'text']);
}
protected function _buildValidator(Validator $validator)
{
return new EnquiryValidator();
}
protected function _execute(array $data)
{
// Send email, etc.
return true;
}
}
in your controller
use App\Form\EnquiryForm;
// ...
public function index()
{
$enquiry = new EnquiryForm();
if ($this->request->is('post')) {
if ($enquiry->execute($this->request->data)) {
$this->Flash->success('Everything is fine.');
// ...
} else {
$this->Flash->error('Unable to send email.');
}
}
$this->set('enquiry', $enquiry);
}
in your view template
<?= $this->Form->create($enquiry); ?>
See also
Cookbook > Modelless Forms
I have a view (_form.php) with fields (name,summary) submit button. If I click on submit button, it should update Name field of One model and Summary field of another model.Both this models are of different databases.
Can anyone help on this. I tried the following for this
In _form.php(Test)
<?php echo $form->labelEx($model, ‘name’); ?>
<?php echo $form->textField($model, ‘name’, array(‘size’ => 60, ‘maxlength’ => 250)); ?>
<?php echo $form->error($model, ‘name’); ?>
<?php echo $form->labelEx(Test1::model(), ‘summary’); ?>
<?php echo $form->textField(Test1::model(), ‘summary’, array(‘size’ => 60, ‘maxlength’ => 250)); ?>
<?php echo $form->error(Test1::model(), ‘summary’); ?>
<?php echo CHtml::submitButton($model->isNewRecord ? ‘Create’ : ‘Save’); ?>
In TestController.php
public function actionCreate() {
$model = new Test;
if (isset($_POST['Test'])) {
$model->attributes = $_POST['Test'];
if ($model->save()) {
$modeltest1 = new Test1;
$modeltest1->attributes = $_POST['Test1'];
$modeltest1->Id = $model->Id;
if ($modeltest1->save())
$this->redirect(array('view', 'Id' => $model->Id));
}
}
$this->render('create', array(
'model' => $model,
));
}
This code is not working. How can I make it work for different databases. I followed the below link for this.
http://www.yiiframework.com/wiki/291/update-two-models-with-one-view/
This code actually should work, but its bad.
I assume that you dont understand at all what is model and what its doing in Yii, also how to render and create forms.
I'll try to explain how it should be.
1st of all dont use Test::model() in views, unless you want to call some function from it(but try to avoid it). It can be done by passing it from controller:
public function actionCreate() {
$model_name = new Name;
$model_summary=new Summary;
//something here
$this->render('create', array(
'name' => $model_name,
'summary'=>$model_summary,
));
}
When you make render you passing variables to your view (name_in_view=>$variable)
2nd. In your view you can use your variables.
<?php echo $form->labelEx($name, ‘name’);
echo $form->textField($name, ‘name’, array(‘size’ => 60, ‘maxlength’ => 250));
echo $form->error($name, ‘name’);
echo $form->labelEx($summary, ‘summary’);
echo $form->textField($summary, ‘summary’, array(‘size’ => 60, ‘maxlength’ => 250)); ?>
echo $form->error($summary, ‘summary’); ?>
echo CHtml::submitButton($model->isNewRecord ? ‘Create’ : ‘Save’); ?>
3rd. You need to understand what is model. It's class that extends CActiveRecord in this case. Your code in controller should loo like:
public function actionCreate() {
$model_name = new Name;
$model_summary=new Summary;
if (isset($_POST['Name']))
$model_name->attributes=$_POST['Name'];
if (isset($_POST['Summary']))
$model_name->attributes=$_POST['Summary'];
if ($model_name->save()&&$model_summary->save())
$this->redirect(array('view', 'Id' => $model->Id));
$this->render('create', array(
'name' => $model_name,
'summary'=>$model_summary,
));
}
$model->attributes=$_POST[] here is mass assignment of attributes, so they must be safe in rules. You always can assign attributes with your hands (1 by 1), or form an array and push it from array.
i want to create a form from 2 different models,
1st is for countries, and the 2nd is for documents.
The problem is that i can't make a dropdown list, i get the errors all the time.
Here's the code, first my controller.php part
$model = new Country;
$model2 = new Product;
$this->performAjaxValidation(array($model, $model2));
if(isset($_POST['Country'],$_POST['Product']))
{
// populate input data to $model and $model2
$model->attributes=$_POST['Country'];
$model2->attributes=$_POST['Product'];
// validate BOTH $model and $model2
$valid=$model->validate();
$valid=$model2->validate() && $valid;
if($valid)
{
// use false parameter to disable validation
$model->save(false);
$model2->save(false);
$this->redirect('index');
}
}
...
$countriesIssued = Country::model()->findAll(array('select'=>'code, name', 'order'=>'name'));
...
$this->render('legalisation', array('model'=>$model, 'model2'=>$model2, 'documents'=>$documents, 'countriesIssued'=>$countriesIssued, 'countries'=>$countries, 'flag'=>$flag));
}
In my view script I use this code
<?php $form = $this->beginWidget('CActiveForm', array(
'id'=>'user-form',
'enableAjaxValidation'=>true,
)); ?>
<?php echo $form->errorSummary(array($model,$model2)); ?>
<?php echo $form->dropDownList($model, 'countriesIssued',
CHtml::listData($countriesIssued, 'code', 'name'));?>
<?php $this->endWidget(); ?>
but i get this error :
Property "Country.countriesIssued" is not defined.
Ok it's not defined, i try to change it to 'countriesIssued', then i got another error saying Invalid argument supplied for foreach() .
If anybody can help me please.
I know there is more solutions on net, i try it but not understand, Thanks.
By definition, the first param of listData is an array; Your is a object;
<?php
echo $form->dropDownList($model, 'classification_levels_id', CHtml::listData(ClassificationLevels::model()->findAll(), 'id', 'name'),$classification_levels_options);
?>
Make a list variable like this:
In your Model:
$countriesIssued = Country::model()->findAll(array('select'=>'code, name', 'order'=>'name'));
And in your view:
$list = CHtml::listData($countriesIssued, 'code', 'name'));
echo CHtml::dropDownList('Your variable', Your $model,
$list,
array('empty' => '(Select a category'));
dropDownList($model,'state',array('1' => 'Do 1', '2' => 'Do 2'),array('selected' => 'Choose')); ?>
Or Yii 2
field($model,'state')->dropDownList(
array('1' => 'Do 1','0' => 'Do 2'),array('options' => array('0' => array('selected' => true))))
->label('State')
?>
i have a simple question i have a form where user enters his details and when the submit button is clicked whit his details submitted to database it will take the user to a different page i am using codeigniter and i am new to this is there an easy way to do this ? tnx for you help. here is my cmv:
controller
<?php
class Info extends CI_Controller{
function index(){
$this->load->view('info_view');
}
// insert data
function credentials()
{
$data = array(
'name' => $this->input->post('name'),
'second_name' => $this->input->post('second_name'),
'phone' => $this->input->post('phone'),
'email' => $this->input->post('email'),
);
$this->info_model->add_record($data);
}
}
?>
model
<?php
class Info_model extends CI_Model {
function get_records()
{
$query = $this->db->get('credentials');
return $query->result();
}
function add_record($data)
{
$this->db->insert('credentials', $data);
return;
}
}
?>
view
<html>
<head>
</head>
<body>
<?php echo form_open('info/credentials'); ?>
<ul id="info">
<li>Name:<?php echo form_input('name')?></li>
<li>Second Name: <?php echo form_input('second_name');?></li>
<li>Phone: <?php echo form_input('phone');?></li>
<li>Email: <?php echo form_input('email');?></li>
<li><?php echo form_submit('submit', 'Start survay!!' );?></li>
</ul>
<?php echo form_close();?>
</body>
</html>
If all you need is a simple redirect upon submission of the form:
$this->info_model->add_record($data);
redirect('controller/method');
You could use the redirect() function from the URL Helper to actually redirect the user
(http://ellislab.com/codeigniter/user-guide/helpers/url_helper.html)
Like this:
$this->load->helper('url');
redirect('/some/other/page');
Note that this has to be called before any data is outputted to the browser.
Another way of doing it is to simply have two different views that you load depending on the context. Normally you want some form validation as well so you can use that to direct the user. I usually end up with something like this in my function, which is used both for posting the data, inserting it to the database and "redirecting":
$this->load->library('form_validation');
$this->form_validation->set_rules('name', 'Name', 'required|trim|xss_clean');
/* More validation */
if ($this->form_validation->run() !== FALSE) {
$data = array(
'name' => $this->input->post('name'),
'second_name' => $this->input->post('second_name'),
'phone' => $this->input->post('phone'),
'email' => $this->input->post('email'),
);
$this->info_model->add_record($data);
$this->load->view('some_other_view');
} else {
$this->load->view('info_view');
}
You can also use refresh as a second parameter:
$this->info_model->add_record($data);
redirect('controllerName/methodName','refresh');
The form is duplicating in a page. I cant upload the picture though:(
I dont remember having any loop for that. I badly need help. This is my
view_register.php
<body>
<h1>IMAGE HERE</h1>
<div id="body">
<br/>
<p class="body">
<!--trial-->
<?php
echo form_open('start');
$firstname = array(
'name' => 'firstname',
'value' => set_value('firstname')
);
$lastname = array(
'name' => 'lastname',
'value' => set_value('lastname')
);
$email = array(
'name' => 'email',
'value' => set_value('email')
);
$dateofbirth = array(
'name' => 'dateofbirth',
'value' => set_value('dateofbirth')
);
$gender = array(
'name' => 'gender',
'value' => set_value('gender'),
'style' => 'margin:10px'
);
$username = array(
'name' => 'username',
'value' => set_value('username')
);
$password = array(
'name' => 'password',
'value' => ''
);
$confpass = array(
'name' => 'confpass',
'value' => ''
);
?>
<!--trial ends here-->
<strong>User Information: </strong>
<div align="right"><font color="red">*</font>Denotes Required Field</div>
<div align="left">
First Name<font color="red">*</font>:
<?php echo form_input($firstname)?>
<br/>
Last Name<font color="red">*</font>:
<?php echo form_input($lastname)?>
<br/>
Email Address<font color="red">*</font>:
<?php echo form_input($email)?>
<br/>
Date Of Birth:
<?php echo form_input($dateofbirth)?>
<br/>
Gender:
<?php
echo form_radio($gender, 'Male');
echo "Male";
echo form_radio($gender, 'Female');
echo "Female";
?>
<br/>
<strong>Account Information:</strong><br/>
Username<font color="red">*</font>:
<?php echo form_input($username)?><br/>
Password<font color="red">*</font>:
<?php echo form_password($password)?><br/>
Password Confirmation<font color="red">*</font>:
<?php echo form_password($confpass)?><br/>
<?php
echo validation_errors();?>
<?php echo form_submit(array('name'=>'register'), 'Register');?>
<?php echo form_reset(array('name'=>'reset'), 'Reset')?>
</div>
</body>
This is my user.php. I'm not really sure with the codes. these are mostly form tutorials i've seen..
class User extends CI_Controller {
private $view_data = array();
function _construct()
{
parent::_construct();
$this->view_data['base_url']=base_url();
}
function index()
{
$this->register();
}
function register()
{
$this->load->library('form_validation');
$this->form_validation->set_rules('firstname', 'First Name', 'trim|required|max_length[100]|min_length[1]|xss_clean');
$this->form_validation->set_rules('lastname', 'Last Name', 'trim|required|max_length[100]|min_length[1]|xss_clean');
$this->form_validation->set_rules('email', 'Email Address', 'trim|required|max_length[100]|xss_clean|valid_email');
$this->form_validation->set_rules('dateofbirth', 'Date of Birth', 'trim|max_length[100]|min_length[1]|xss_clean');
$this->form_validation->set_rules('gender', 'Gender', 'trim|max_length[6]|min_length[6]|xss_clean');
$this->form_validation->set_rules('username', 'User Name', 'trim|required|alpha_numeric|callback_username_not_exists|max_length[100]|min_length[6]|xss_clean');
if ($this->form_validation->run() == FALSE)
{
//not run
$this->load->view('view_register', $this->view_data);
}
else
{
//good
$firstname=$this->input->post('firstname');
$lastname=$this->input->post('lastname');
$email=$this->input->post('email');
$dateofbirth=$this->input->post('dateofbirth');
$gender=$this->input->post('gender');
$username=$this->input->post('username');
$password=$this->input->post('password');
$this->User_model->register_user($firstname, $lastname, $email, $dateofbirth, $gender, $username, $password);
}
$this->load->view('view_register', $this->view_data);
}
Then after that I am stuck. After clicking Register, It says Page404 Not Found, there's not even a validation.
First. Find new tutorials, there is a lot of code in there that makes zero sense. I strongly suggest this series: http://net.tutsplus.com/sessions/codeigniter-from-scratch/
Next. You're getting a page not found because your form action leads no where. In the line:
echo form_open('start');
You're trying to call a function in your controller called 'start' yet there is no function in your controller called start. The function is called register.
Next. You're running the form validation before even seeing if there is any post data and you're actually running it before there CAN be any post data.
You're getting the form twice probably because you're loading the same view into the page twice, once when the form validation fails, which it obviously will the first time you load then again when you're calling your user model.
Quite honestly the only answer here is to nuke what you've done, reinstall CI and follow the tutorial series I gave you above. The tutorials you're following are giving you very bad practices and you need to just forget what they've taught you. Follow the Nettuts tutorial one step at a time and make sure you're understanding what it's telling you before moving on. Don't just copy and paste and cross your fingers.