I currently have the following models:
class Category extends AppModel {
var $name = 'Category';
/*var $validate = array(
'name' => 'multiple'
);
no idea how to use this
*/
var $hasAndBelongsToMany = array(
'Post' => array(
'className' => 'Post'
)
);
class Post extends AppModel {
var $name = 'Post';
var $hasAndBelongsToMany = array(
'Category' => array(
'className' => 'Category'
)
);
var $belongsTo = array(
'Page' => array(
'className' => 'Page'
)
);
class Page extends AppModel {
var $name = 'Page';
var $order = array('Page.modified' => 'desc');
var $hasOne = array(
'Post' => array(
'className' => 'Post'
));
I also have this Form in the view:
<div id="content-wrap">
<div id="main">
<h2>Add Post</h2>
<?php echo $this->Session->flash();?>
<div>
<?php
echo $this->Form->create('Post');
echo $this->Form->input('Post.title');
echo $this->Form->input('Category.Category', array('multiple' => 'checkbox'));
echo $this->Form->input('Post.body', array('rows' => '3'));
echo $this->Form->input('Page.meta_keywords');
echo $this->Form->input('Page.meta_description');
echo $this->Form->end('Save Post');
?>
</div>
<!-- main ends -->
</div>
My Controller:
function admin_add() {
// pr(Debugger::trace());
$this->set('categories', $this->Post->Category->find('list'));
if ( ! empty($this->data)) {
$this->data['Page']['title'] = $this->data['Post']['title'];
$this->data['Page']['layout'] = 'index';
if ($this->Post->saveAll($this->data)) {
$this->Session->setFlash('Your post has been saved', 'flash_good');
$this->redirect($this->here);
}
}
}
The problem I am having is that I could save a Post without choosing a category for it.
I've tried adding the following as a rule to the Category Model:
var $validate = array(
'rule' => array('multiple', array('in' => array(1, 2, 3, 4))),
'required' => TRUE,
'message' => 'Please select one, two or three options'
);
The Post and Page Model validates.
How do I activate validation for the Category?
First off, you haven't set up the $validate variable properly. The keys in the $validate array must be field names. Secondly, the multiple rule is used to check if the value(s) of a field lies within a set of values.
var $validate = array(
'color' => array(
'multiple' => array(
'rule' => array('multiple', array('in' => array('Red', 'Blue', 'Green'))),
'required' => false,
'message' => 'Please select one, two or three options'
),
),
);
I checked the example in the book for multiple and it's a typo there. The above code is correct.
Next, if you want to validate related models, I suggest you do that in your beforeSave() function:
function beforeSave(){
if (isset($this->data['Category']['Category']) && empty($this->data['Category']['Category'])) {
return false;
}
return true;
}
Here, returning false from the beforeSave() would prevent the save from going through. So, you will have successfully validated your requirement.
Related
I am working on Magento 1.7 version.
My code is below:-
$categoryArray = Mage::getSingleton('lookbook/category')->getOptionArray();
$catId = Mage::getSingleton('core/session')->getCatId(); //it has value 4
$fieldset->addField('category_id', 'select', array(
'label' => Mage::helper('lookbook')->__('Lookbook'),
'name' => 'category_id[]',
'values' => $categoryArray,
'value' => $catId,
'disabled' => true
));
How to set this value selected in drop-down of admin grid form in Magento?
Take a look # https://magento.stackexchange.com/questions/544/how-to-set-default-value-for-form-fields
protected function _prepareForm()
{
$form_data = new Varien_Object();
$form = new Varien_Data_Form();
$this->setForm($form);
....
if ( Mage::getSingleton('adminhtml/session')->getXyzData() )
{
$form_data = Mage::getSingleton('adminhtml/session')->getXyzData();
Mage::getSingleton('adminhtml/session')->setXyzData(null);
}
else if ( Mage::registry('xyz_data') ) {
$form_data = Mage::registry('xyz_data');
}
$catId = Mage::getSingleton('core/session')->getCatId(); // it has value 4
if( empty($form_data->getData('category_id')) ){
$form_data->setData('category_id', $catId);
}
$fieldset->addField('category_id', 'select', array(
'label' => Mage::helper('lookbook')->__('Lookbook'),
'name' => 'category_id[]',
'values' => $categoryArray,
'disabled' => true
));
....
$form->setValues($form_data);
$this->setForm($form);
}
Add this in the __construct method of your grid.
$this->_defaultFilter = array('category_id'=>Mage::getSingleton('core/session')->getCatId());
I have one view wich has 2 forms one for login and one for registration as following :
signup.ctp //my view
<div>
<?php
echo $this->Form->create("Tbluser");
echo $this->Form->hidden('formsent', array('value' => 'signup'));
echo $this->Form->input('username' ,array('label'=>'Username'));
echo $this->Form->input('password' ,array('label'=>'Password','type' => 'password'));
echo $this->Form->input('email' ,array('label'=>'Email'));
echo $this->Form->end('Register');
?>
</div>
<div>
<?php
echo $this->Form->create("Tbluser"); ?>
echo $this->Form->hidden('formsent', array('value' => 'login'));
echo $this->Form->input('username' ,array('label'=>"Username :"));
echo $this->Form->input('password' ,array('label'=>"Password :",'type' => 'password'));
echo $this->Form->end('Login');
?>
<div>
The model I'm using for both forms is as following :
<?php
class Tbluser extends AppModel{
public $validate = array(
'username'=>array(
array(
'rule'=>'alphaNumeric',
'allowEmpty'=>false,
'message'=>'Invalide Username!'
),
array(
'rule' => array('minLength', '4'),
'message' => 'Username has to be more than 3 chars'
),
array(
'rule'=>'isUnique',
'message'=>'Username already taken!'
)
),
'password' => array(
array(
'rule' => 'alphaNumeric',
'allowEmpty'=>false,
'message' => 'Password must be AlphaNumeric!'
),
array(
'rule' => array('minLength', '4'),
'message' => 'Username has to be more that 3 chars'
)
),
'email'=>array(
array(
'rule'=>array('email',true),
'required'=>true,
'allowEmpty'=>false,
'message'=>'Invalide email adress!'
),
array(
'rule'=>'isUnique',
'message'=>'Mail adress already taken!'
)
)
);
}
?>
The controller I'm using is as following :
<?php
class TblusersController extends AppController
{
public $uses = array(
'Tbluser'
);
public function signup()
{
if ($this->request->is('post')) {
if ('signup' === $this->request->data['Tbluser']['formsent']) {
// Registration part.
}else if('login' === $this->request->data['Tbluser']['formsent']){
//Login part
}
}
}
?>
My AppController looks like :
<?php
class AppController extends Controller {
public $helpers = array('Form', 'Html');
public $components = array('Session','Cookie','Auth'=>array(
'authenticate'=>array(
'Form' => array(
'userModel' => 'Tblforumuser',
'fields' => array(
'username' => 'username',
'password' => 'password'
)
)
)
));
}
?>
Right now if I fill wrong data into the signup form and submit it the validation occurs but also in the login form fields so How can I set the validation only to apply to that signup form and not to both forms? Thanks.
It looks like all validation is being invoked on every read and write because you are telling your model to run all validation without restriction. A better way to handle this would be a separate model for each form.
By creating two new models userLogin and userRegister that extend Tbluser, you can set specific validation rules for each form. You could do something like :
View/Tbluser/signup.ctp
<div>
<?php
echo $this->Form->create("userRegister");
echo $this->Form->hidden('formsent', array('value' => 'signup'));
echo $this->Form->input('username' ,array('label'=>'Username'));
echo $this->Form->input('password' ,array('label'=>'Password','type' => 'password'));
echo $this->Form->input('email' ,array('label'=>'Email'));
echo $this->Form->end('Register');
?>
</div>
<div>
<?php
echo $this->Form->create("userLogin"); ?>
echo $this->Form->hidden('formsent', array('value' => 'login'));
echo $this->Form->input('username' ,array('label'=>"Username :"));
echo $this->Form->input('password' ,array('label'=>"Password :",'type' => 'password'));
echo $this->Form->end('Login');
?>
<div>
Here, since we're using two separate models with each $this->Form-create(); helper, only the validation in the specified model will be run. Your models will contain only the validation that applies to the form assigned to it:
Model/userRegister.php
class userRegister extends Tbluser{
public $validate = array(
'username'=>array(
array(
'rule'=>'alphaNumeric',
'allowEmpty'=>false,
'message'=>'Invalide Username!'
),
array(
'rule' => array('minLength', '4'),
'message' => 'Username has to be more than 3 chars'
),
array(
'rule'=>'isUnique',
'message'=>'Username already taken!'
)
),
'password' => array(
array(
'rule' => 'alphaNumeric',
'allowEmpty'=>false,
'message' => 'Password must be AlphaNumeric!'
),
array(
'rule' => array('minLength', '4'),
'message' => 'Username has to be more that 3 chars'
)
),
'email'=>array(
array(
'rule'=>array('email',true),
'required'=>true,
'allowEmpty'=>false,
'message'=>'Invalide email adress!'
),
array(
'rule'=>'isUnique',
'message'=>'Mail adress already taken!'
)
)
);
}
Model/userLogin.php
class userLogin extends Tbluser{
public $validate = array(
'username'=>array(
array(
'rule'=>'alphaNumeric',
'allowEmpty'=>false,
'message'=>'Invalide Username!'
),
array(
'rule' => array('minLength', '4'),
'message' => 'Username has to be more than 3 chars'
),
array(
'rule'=>'isUnique',
'message'=>'Username already taken!'
)
),
'password' => array(
array(
'rule' => 'alphaNumeric',
'allowEmpty'=>false,
'message' => 'Password must be AlphaNumeric!'
),
array(
'rule' => array('minLength', '4'),
'message' => 'Username has to be more that 3 chars'
)
)
);
}
Then in your signup(); method, you will want to load the two new models you just created accordingly:
Controller/TblusersController.php
class TblusersController extends AppController {
public $uses = array(
'Tblforumuser'
);
public function signup() {
$this->loadModel('userLogin');
$this->loadModel('userRegistration');
if ($this->request->is('post')) {
if ('signup' === $this->request->data['Tblforumuser']['formsent']) {
// Registration part.
}else if('login' === $this->request->data['Tblforumuser']['formsent']){
//Login part
}
}
}
Hope this helps
I'm having some issues with validating form fields inside my controller, for testing purposes.
I have my model Experience with hasMany ExperienceDetail. ExperienceDetail belongsTo Experience.
I created a form using the FormHelper which contains the following:
index.ctp
<?php
echo $this->Form->create('Experience', array('action' => 'index'));
echo $this->Form->input('Experience.date', array(
'label' => array(
'text' => 'Datum'),
'type' => 'date',
'dateFormat' => 'DMY',
'monthNames' => false,
'minYear' => date('Y') - 10,
'maxYear' => date('Y')
)
);
echo $this->Form->input('Experience.test');
echo $this->Form->input('ExperienceDetail.vertrekstation');
echo $this->Form->end('Verstuur!');
?>
There are some more fields provided with ExperienceDetail, but these are irrelevant for this matter.
Experience.php
<?php
class Experience extends AppModel {
public $name = 'Experience';
public $hasMany = 'ExperienceDetail';
public $validate = array(
'vertrekstation' => array(
'rule' => 'notEmpty',
'message' => 'Voer een vertrekstation in',
'required' => true
),
'test' => array(
'rule' => 'notEmpty',
'message' => 'Test mag niet leeg zijn!'
)
);
}
?>
ExperienceDetail.php
<?php
class ExperienceDetail extends AppModel {
public $name = 'ExperienceDetail';
public $belongsTo = 'Experience';
public $validate = array(
'vertrekstation' => array(
'rule' => 'notEmpty',
'message' => 'Voer een vertrekstation in'
)
);
}
?>
ExperiencesController.php
<?php
class ExperiencesController extends AppController {
public $helpers = array('Html', 'Form', 'Session');
public function index() {
// $this->layout = 'default_orig';
$this->set('title_for_layout', 'De OV-Ervaringenmeter!');
// LOAD Model Carrier
$this->loadModel('Carrier');
$this->set('carrier', $this->Carrier->find('list', array('order' => array('Carrier.name' => 'asc'))));
// Check if form is allready filled
if($this->request->is('post')) {
$this->Experience->set($this->request->data);
$this->Session->setFlash('No if or else statement is called');
if ($this->Experience->validates()) {
$this->Session->setFlash('Validates!');
}
}
}
}
?>
The problem is: when I send the form and leave test empty, it provides me the validation error which I've set up in the Model. But when I leave vertrekstation empty, it doesn't provide me any errors that belongs to the input field.
What am I doing wrong and how am I able to get these errors printed?
I'm trying to working with the Uploader Plugin to create a structure where a User Model can upload it's avatar with the Avatar Model, I've read the instructions several times but when I try to $this->Uploader->upload('Avatar.filename') I get no validation errors but the upload method fails.
Here is how I've written the User Model
<?php
class User extends AppModel {
public $name = 'User';
public $hasOne = array(
'Profile' => array(
'className' => 'Profile',
'conditions' => '',
'dependent' => true,
'foreignKey' => 'user_id',
'associatedKey' => 'user_id'
),
'Avatar' => array (
'className' => 'Avatar',
'foreignKey' => 'user_id',
'dependent' => true
)
);
public $validate = array(...);
// other stuff not relevant here...
?>
Here is the Avatar Model
<?php
class Avatar extends AppModel {
public $name = 'Avatar';
public $actsAs = array (
'Uploader.Attachment' => array (
'Avatar.filename' => array(
'name' => 'setNameAsImgId', // Name of the function to use to format filenames
'baseDir' => '', // See UploaderComponent::$baseDir
'uploadDir' => 'files/avatars/', // See UploaderComponent::$uploadDir
'dbColumn' => 'filename', // The database column name to save the path to
'importFrom' => '', // Path or URL to import file
'defaultPath' => '', // Default file path if no upload present
'maxNameLength' => 500, // Max file name length
'overwrite' => true, // Overwrite file with same name if it exists
'stopSave' => true, // Stop the model save() if upload fails
'allowEmpty' => true, // Allow an empty file upload to continue
'transforms' => array (
array('method' => 'resize', 'width' => 128, 'height' => 128, 'dbColumn' => 'name')
) // What transformations to do on images: scale, resize, ete
)
),
'Uploader.FileValidation' => array (
'Avatar.filename' => array (
'maxWidth' => array (
'value' => 512,
'error' => 'maxWidth error'
),
'maxHeight' => array (
'value' => 512,
'error' => 'maxWidth error'
),
'extension' => array (
'value' => array('gif', 'jpg', 'png', 'jpeg'),
'error' => 'extension error'
),
'filesize' => array (
'value' => 5242880,
'error' => 'filesize error'
)
)
)
);
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id',
'conditions' => '',
'order' => ''
)
);
public function setNameAsImgId ($name, $field, $file) {
/**
* Format the filename a specific way before uploading and attaching.
*
* #access public
* #param string $name - The current filename without extension
* #param string $field - The form field name
* #param array $file - The $_FILES data
* #return string
*/
// devo ricavare l'id dell'immagine appena creata per rinominare il file
return $name;
}
}
?>
This is the UsersController for edit method
<?php
App::uses('CakeEmail','Network/Email');
CakePlugin::load('Uploader');
App::import('Vendor', 'Uploader.Uploader');
class UsersController extends AppController {
public $name = 'Users';
public function edit ($id) {
$this->User->id = $id;
if (!$this->User->exists()) {
throw new NotFoundException ('Nessuna corrispondenza trovata per questo utente');
}
if (!$id) {
$this->set('flash_element','error');
$this->Session->setFlash ('Utente non valido');
}
$this->User->recursive = 1;
$this->set('user', $this->User->read());
if ($this->request->is('post')) {
$this->User->id = $this->request->data['User']['id'];
if (!$this->User->exists()) {
$this->set('flash_element','warning');
$this->Session->setFlash('Nessun utente trovato con questa corrispondenza');
}
if ($this->User->save($this->request->data)) {
$this->request->data['Profile']['user_id'] = $this->User->id;
$conditions = array(
'conditions' => array(
'Profile.id' => $this->request->data['Profile']['id']
)
);
if ($this->User->Profile->save($this->request->data, $conditions)) {
if (!empty($this->request->data['Avatar']['filename'])) {
$this->request->data['Avatar']['user_id'] = $this->User->id;
if ($this->User->Avatar->save($this->request->data)) {
$avatar = $this->User->Avatar->find('first', array(
'conditions' => array('Avatar.user_id' => $this->User->id)
));
$ext = Uploader::ext($this->request->data['Avatar']['filename']);
$filename = $avatar['Avatar']['id'].'.'.$ext;
if ($this->User->Avatar->save('Avatar.filename')) {
$this->set('flash_element','done');
$this->Session->setFlash('Avatar changed successfully');
debug('saved successfully');
} else {
debug('not saved');
$this->set('flash_element','warning');
$this->Session->setFlash('Avatar not saved on the server');
}
} else {
$this->Session->write('flash_element','error');
$this->Session->setFlash('Avatar data not saved on the server');
$this->redirect(array('action'=>'index'));
}
} else {
$this->Session->write('flash_element','done');
$this->Session->setFlash('Data successfully saved, avatar not changed');
$this->redirect(array('action'=>'index'));
}
} else {
$this->set('flash_element','error');
$this->Session->setFlash('Error on saving Profile data to the server');
}
} else {
$this->Session->write('flash_element','error');
$this->Session->setFlash('Error on saving User data to the server');
$this->redirect(array('action'=>'index'));
}
}
}
}
?>
And in the view file I have this
<?php
echo $this->Form->create('User', array ('class' => 'form'));
echo $this->Form->input('User.id', array ('type'=>'hidden', 'value'=> $user['User']['id'],'label'=> false, 'id' => 'id'));
echo $this->Form->input('User.username', array ('label'=> false, 'value' => $user['User']['username'], 'id' => 'username', 'after' => '<div class="message">Message for username field'));
echo $this->Form->input('User.email', array ('label'=> false, 'value' => $user['User']['email'], 'id' => 'email', 'after' => '<div class="message">Message for email field</div>'));
echo $this->Form->input('UserOptions.id', array ('type'=>'hidden', 'value'=> $user['UserOptions']['id'],'label'=> false, 'id' => 'UserOptions.id'));
$attributes = array ('value' => $user['UserOptions']['avatar_type'], 'empty' => false);
$options = array('0' => 'This site', '1' => 'Gravatar');
echo $this->Form->select('UserOptions.avatar_type', $options, $attributes);
/* avatar code */
echo $this->Form->input('Avatar.id', array ('type'=>'hidden', 'value'=> $user['Avatar']['id'],'label'=> false, 'id' => 'Avatar.id'));
echo $this->Form->input('Avatar.filename', array('type' => 'file'));
/* end avatar code */
echo $this->Form->input('Profile.city', array ('label'=> false, 'value' => defaultValue ('City', $user['Profile']['city']), 'id' => 'city', 'after' => '<div class="message">Message for city field</div>'));
echo $this->Form->input('Profile.country', array ('label'=> false, 'value' => defaultValue('',$user['Profile']['country']), 'id' => 'country', 'after' => '<div class="message">Message for country field</div>'));
echo $this->Form->input('Profile.url', array ('label'=> false, 'value' => defaultValue('http://', $user['Profile']['url']), 'id' => 'url', 'after' => '<div class="message">Message for url field</div>'));
echo $this->Form->input('Profile.description', array ('label'=> false, 'value' => defaultValue('Description',$user['Profile']['description']), 'id' => 'description', 'after' => '<div class="message">Message for description field</div>'));
echo $this->Form->submit('Modifica', array('id'=>'edit'));
echo $this->Form->end();
?>
In the Controller, every part of the data is saved until I reach $this->Uploader->upload('Avatar.filename', array('overwrite' => true, 'name' => $filename)) where I get a generic error.
This Plugin seems to be the best way to do it without write tons of code, but I'm not sure how to use it.
I'm not sure what's wrong with the code, can You help me to solve the problem?
I've found the problems, I forgot two things:
In the view page I've forgot 'type' => 'file'
<?php
echo $this->Form->create('User', array ('class' => 'form', 'type' => 'file'));
?>
I was used to work with 1.3 version so the app/Config/bootstrap.php configuration was missing:
<?php
CakePlugin::load('Uploader');
?>
Now it works!
I've been struggling with this for the last hour or so, wondering if some fresh eyes can help.
Model
class User extends AppModel {
public $name = 'User';
public $validate = array(
'email' => array(
'valid' => array(
'rule' => 'email',
'message' => 'The email is not valid'
),
'required' => array(
'rule' => 'notEmpty',
'message' => 'Please enter an email'
)
)
);
}
Controller
class UserController extends AppController {
var $uses = array('User');
function index(){
$users = $this->User->find('all');
$this->set(compact('users'));
}
public function add() {
$this->set('title_for_layout', 'Add new user');
if(isset($this->data) && !empty($this->data)) {
$this->User->set($this->data);
$this->log($this->User->invalidFields(), "debug");
if($this->User->validates()){
if ($this->User->save($this->data)) {
$this->Session->setFlash("Added " . $this->data['User']['name']);
$this->redirect('index');
}
} else {
$this->Session->setFlash('There are errors with your form submit, please see below.');
}
}
}
}
View
<?php
echo $this->Form->create('User');
echo $this->Form->input('name', array('label' => 'Name'));
echo "<div class='clear'></div>";
echo $this->Form->input('email', array('label' => 'Email'));
echo "<div class='clear'></div>";
echo $this->Form->button('Reset', array('type' => 'reset'));
echo $this->Form->button('Add Useer', array('type' => 'submit'));
echo $this->Form->end();
?>
But I never get invalid fields for email? Have I missed something glaring?
If it makes any difference, this is a plugin Im developing so it doesnt sit directly in app/ but in app/Plugins
Thanks
EDIT: So I've been struggling with this for a while now, and still no joy. One thing I have noticed though, when I print out the model details (using var_dump($this->User) ), the [validate] array is empty. For example:
[validate] => Array
(
)
[validationErrors] => Array
(
)
Im presuming this is what the issue is, even though I have declared my $validate array, its somehow being overwritten? Anyone come across this before? Any solutions?
public $validate = array(
'email' => array(
'valid' => array(
'rule' => array('email'),
'message' => 'The email is not valid'
),
'required' => array(
'rule' => array('notEmpty'),
'message' => 'Please enter an email',
'allowEmpty' => false
)
)
);
Try adding rules as array and adding 'allowEmpty' key set to false on the required validation.
Damn! So simple. If I read the cookbook properly at http://book.cakephp.org/1.3/en/view/1114/Plugin-Models it would have told me that
If you need to reference a model within your plugin, you need to include the plugin name with the model name, separated with a dot.
Thus..
var $uses = array('Plugin.User');
works.. Hope this helps someone else!