I need to display an error message for a custom validation rule, but I can't get to do it.
This is the validation rule:
$config = array(
....,
array(
'field' => 'general_sales_subaccount',
'label' => 'General Sales Subaccount',
'rules' => array(
'required',
'numeric',
array(
$this->subaccounts_model,
'is_valid'
)
),
)
);
$this->form_validation->set_rules($config);
And now this is the referenced model method:
public function is_valid($subaccount)
{
$subaccount_num_digits = $this->preferences->get('subaccount_num_digits');
if (strlen($subaccount) != $subaccount_num_digits ) {
$this->form_validation->set_message('is_valid', "The number of digits in %s doesn't match the length set to " . $subaccount_num_digits);
return false;
}
return true;
}
The rule seems to work, but it displays this error message:
Unable to access an error message corresponding to your field name (Anonymous function).
Any ideas?
You can't get an error message because you don't setup functions name. You may change your rule function like below:
$config = array(
....,
array(
'field' => 'general_sales_subaccount',
'label' => 'General Sales Subaccount',
'rules' => array(
'required',
'numeric',
array( //you may get all in another array
'is_valid', // and tell codeigniter your functions name
array(
$this->subaccounts_model,
'is_valid'
)
)
),
)
);
$this->form_validation->set_rules($config);
I am using Doctrine 2 in my Zend Framework 2 Project. I have now created a Form and create one of my Dropdowns with Values from the Database. My Problem now is that I want to change which values are used and not the one which I get back from my repository. Okay, here some Code for a better understanding:
$this->add(
array(
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'name' => 'county',
'options' => array(
'object_manager' => $this->getObjectManager(),
'label' => 'County',
'target_class' => 'Advert\Entity\Geolocation',
'property' => 'county',
'is_method' => true,
'empty_option' => '--- select county ---',
'value_options'=> function($targetEntity) {
$values = array($targetEntity->getCounty() => $targetEntity->getCounty());
return $values;
},
'find_method' => array(
'name' => 'getCounties',
),
),
'allow_empty' => true,
'required' => false,
'attributes' => array(
'id' => 'county',
'multiple' => false,
)
)
);
I want to set the value for my Select to be the County Name and not the ID. I thought that I would need the 'value_options' which needs an array. I tried it like above, but get the
Error Message: Argument 1 passed to Zend\Form\Element\Select::setValueOptions() must be of the type array, object given
Is this possible at all?
I was going to suggest modifying your code, although after checking the ObjectSelect code i'm surprised that (as far as I can tell) this isn't actually possible without extending the class. This is because the value is always generated from the id.
I create all form elements using factories (without the ObjectSelect), especially complex ones that require varied lists.
Alternative solution
First create a new method in the Repository that returns the correct array. This will allow you to reuse that same method should you need it anywhere else (not just for forms!).
class FooRepository extends Repository
{
public function getCounties()
{
// normal method unchanged, returns a collection
// of counties
}
public function getCountiesAsArrayKeyedByCountyName()
{
$counties = array();
foreach($this->getCounties() as $county) {
$counties[$county->getName()] = $county->getName();
}
return $counties;
}
}
Next create a custom select factory that will set the value options for you.
namespace MyModule\Form\Element;
use Zend\Form\Element\Select;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\FactoryInterface;
class CountiesByNameSelectFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $formElementManager)
{
$element = new Select;
$element->setValueOptions($this->loadValueOptions($formElementManager));
// set other select options etc
$element->setName('foo')
->setOptions(array('foo' => 'bar'));
return $element;
}
protected function loadValueOptions(ServiceLocatorInterface $formElementManager)
{
$serviceManager = $formElementManager->getServiceLocator();
$repository = $serviceManager->get('DoctrineObjectManager')->getRepository('Foo/Entity/Bar');
return $repository->getCountiesAsArrayKeyedByCountyName();
}
}
Register the new element with the service manager by adding a new entry in Module.php or module.config.php.
// Module.php
public function getFormElementConfig()
{
return array(
'factories' => array(
'MyModule\Form\Element\CountiesByNameSelect'
=> 'MyModule\Form\Element\CountiesByNameSelectFactory',
),
);
}
Lastly change the form and remove your current select element and add the new one (use the name that you registered with the service manager as the type key)
$this->add(array(
'name' => 'counties',
'type' => 'MyModule\Form\Element\CountiesByNameSelect',
));
It might seem like a lot more code (because it is) however you will benefit from it being a much clearer separation of concerns and you can now reuse the element on multiple forms and only need to configure it in one place.
I have tried almost everything in my knowledge and found on net but nothing works. What I am trying to do is while adding new record I want to check whether the field value is already in database table or not. If not than add else throw error message.
I have tried also with is_usnique but than it is not allowing to modify data since it is considering that form value is exists.
Table name is positions
Coloumn name is position
Input field name is position
I have tried below code in my Controller
public function _unique_poscode()
{
$id = $this->uri->segment(4);
$this->db->where('position', $this->input->post('position'));
!$id || $this->db->where('id !=', $id);
$poses = $this->positions_model->get();
if (count($poses)) {
$this->form_validation->set_message('_unique_poscode', '%s should be uinique');
return FALSE;
}
return TRUE;
}
And set rules in my Model as below
public $rules = array(
'position' => array(
'field' => 'position',
'label' => 'Position Code',
'rules' => 'trim|required|max_length[10]|callback__unique_poscode|xss_clean'
),
'label' => array(
'field' => 'label',
'label' => 'Position Label',
'rules' => 'trim|required|max_length[50]|xss_clean'
),
);
but no matter whatever I do it is not working and adding record even if it is exists in table.
Can anyone help me to fix this issue? Thanks a lot.
you are missing parameter
public function _unique_poscode( $p )
{
$this->form_validation->set_message('_unique_poscode', '%s should be uinique');
$q = $this->db->get_where('positions', array('position' => $p));
return ($q->num_rows() > 0) ? TRUE : FALSE;
}
and in rules
...|callback__unique_poscode|trim
and how it is done by codeigniter is as one of rules, please see this for more
is_unique[table.column]
Simply add this to rules and check.
is_unique[TABLENAME.COLUMNNAME]
According to your one it should be,
is_unique[positions.position]
I'm going crazy trying out different solutions on the net of a fairly simple problem
I have literally hundreds of dates being stored by my application, and my client's source data has a bad habit of dates being in different formats.
For example, one of my models has rules as followed (for completion all are listed for this specific model)
public function rules() {
return array(
array('function, junior, ces,agreement_expected,start_date', 'required'),
array('start_budget', 'numerical'),
array('visa_received,training_days', 'numerical', 'integerOnly' => true),
array('function, junior, ces,currency', 'length', 'max' => 10),
array('agreement_received, status, stop_date_original, stop_date_extended', 'safe'),
array('agreement_received, visa_received, stop_date_original, stop_date_extended', 'default', 'setOnEmpty' => true, 'value' => null),
array('agreement_received,agreement_expected,start_date,stop_date_original,stop_date_extended', 'date', 'format' => 'Y-m-d', 'allowEmpty' => true),
array('id, Sname,PFces, PFdomain,PDkeyword, PFstatus, PRname,PRcountry,PRscore,PRcomment,PRngo,TRname,TRpic, TFfunction, TFx, TRdateofbirth,TRedufields,TRcoach,TRlocation,TRtask,TRcontract,TRproject,TRcontact,TFdateofbirth,TFedufields,TFcoach,TFlocation,TFtask,TFcontract,TFproject,TFcontact,
date1,date2,idate, ddomains,dkeywords,country,agreement, function,ngo, status,group, junior, junior_lastname, junior_firstname,search_all,search_interrupt, ces, agreement_expected, agreement_received, visa_received, start_date, stop_date_original, stop_date_extended,currency, start_budget, training_days', 'safe', 'on' => 'search'),
);
}
what I want to achieve is depicted by following rules
array('agreement_received, visa_received, stop_date_original, stop_date_extended', 'default', 'setOnEmpty' => true, 'value' => null),
array('agreement_received,agreement_expected,start_date,stop_date_original,stop_date_extended', 'date', 'format' => 'Y-m-d', 'allowEmpty' => true),
When I have a form, and I submit an empty value on say stop_date_extended, it is not set to NULL rather an empty string..
What am I doing wrong?
Surely there must be an easy work-around as not using the date validator works peachy.
Yii Default Validator class handles the empty values like this :
/framework/validators/CDefaultValueValidator.php
protected function validateAttribute($object,$attribute)
{
if(!$this->setOnEmpty)
$object->$attribute=$this->value;
else
{
$value=$object->$attribute;
if($value===null || $value==='')
$object->$attribute=$this->value;
}
}
Given the function above your only issue could be that the value[i.e $value] posting by form could be not empty string probably it might have spaces. Probably you could try trim() the values before assigning them to model attributes. Or extend the default value validator e.g
class CMyDefaultValueValidator extends CDefaultValueValidator
{
protected function validateAttribute($object,$attribute)
{
if(!$this->setOnEmpty)
$object->$attribute=$this->value;
else
{
$value=trim($object->$attribute);
if($value===null || $value==='')
$object->$attribute=$this->value;
}
}
}
just note the line : $value=trim($object->$attribute);
Although,I haven't tested above code, I do not know if this is could be done some better way,
if you want to insert null for empty strings, you can do it in your model, after validation:
public function afterValidate()
{
if(empty(trim($this->yourField))) // put whatever logic that you need
$this->yourField = null;
return parent::afterValidation();
}
i just write my first article so please tell me if i've done something wrong!
My Problem: I want to validate data given by url.
../Logs/requests?from=2011-10-18T16:15:00&to=2011-10-18T16:30:00&fmt=csv
I have just find out that there is an option to validate with the rules added to the Model.
public $validate = array(
'request_id' => array(
'alphaNumeric' => array(
'rule' => 'alphaNumeric',
'required' => true,
'message' => 'Alphabets and numbers only'
),
)
);
Using "ModelName->set($params)" in the Controller and after that the "ModelName->validates()"-function should deliver the answer if its valid or not. The only differenz between my solution and the solution at http://book.cakephp.org/2.0/en/models/data-validation/validating-data-from-the-controller.html
is that my controller using a couple of Models to collect the data for the response.
The problem is that the "validates()"-function just return "valid" even if i put in special-characters or other stuff what should be "not valid"-signed by the model-rules.
Help!
This is not an answer, but added to assist the OP;
I've created a test controller/model to test your situation. I deliberately did not extend the 'AppController' / 'AppModel' to remove any code in those from causing problems.
My test model (app/Model/Some.php)
class Some extends Model
{
public $name = 'Some';
public $useTable = 'false';
public $validate = array(
'request_id' => array(
'alphaNumeric' => array(
'rule' => 'alphaNumeric',
'required' => true,
'message' => 'Alphabets and numbers only'
),
)
);
}
My test controller (app/Controller/SomeController.php)
class SomeController extends Controller
{
public $uses = array('Some');
public function index()
{
$this->autoRender = false;
$params = array('Some' => array('request_id'=>'4*G/&2'));
$this->Some->set($params);
$result = $this->Some->validates();
debug($result);
$params = array('Some' => array('request_id'=>'AAAA'));
$this->Some->set($params);
$result = $this->Some->validates();
debug($result);
}
}
Outputs:
\app\Controller\SomeController.php (line 32)
false
\app\Controller\SomeController.php (line 37)
true
This test setup seems to work as planned, so you may try to test these in your application as well to narrow down the cause of your problem. Maybe some behavior is attached to your AppModel that contains a 'beforeValidate()' callback and disables the validation of the request_id field?