On my bootstrap I don't have a class, it's a simple php file:
I have added there:
$loader = Zend_Loader_Autoloader::getInstance ();
$loader->setFallbackAutoloader ( true );
$loader->suppressNotFoundWarnings ( false );
//resource Loader
$resourceLoader = new Zend_Loader_Autoloader_Resource(array(
'basePath' => APPLICATION_PATH,
'namespace' => '',
));
$resourceLoader->addResourceType('validate', 'validators/', 'My_Validate_');
$loader->pushAutoloader($resourceLoader);
Then, in application/validators I have:
class My_Validate_Spam extends Zend_Validate_Abstract {
const SPAM = 'spam';
protected $_messageTemplates = array(
self::SPAM => "Spammer"
);
public function isValid($value, $context=null)
{
$value = (string)$value;
$this->_setValue($value);
if(is_string($value) and $value == ''){
return true;
}
$this->_error(self::SPAM);
return false;
}
}
In my form constructor I have:
$this->addElement(
'text',
'honeypot',
array(
'label' => 'Honeypot',
'required' => false,
'class' => 'honeypot',
'decorators' => array('ViewHelper'),
'validators' => array(
array(
'validator' => 'Spam'
)
)
)
);
And finally on my view I have:
<dt><label for="honeypot">Honeypot Test:</label></dt>
<dd><?php echo $this->form->honeypot;?></dd>
Despite all this, I receive my form data, either by filling or not filling that text field.
What am I missing here ?
Thanks a lot in advance.
Thats expected behaviour. $honeypot is a form-element. Now, let's say you have a form $hp_form where $honeypot is one of the elements assigned.
Now, in your controller simply use something like:
if ($hp_form->isValid($this->getRequest()->getPost())) {
// do something meaningful with your data here
}
Probably you also want to check, if you display the form for the first time or if the user submitted the form:
if ($this->getRequest()->isPost() &&
false !== $this->getRequest()->getPost('submit_button', false)) {
if ($hp_form->isValid($this->getRequest()->getPost())) {
// do something meaningful with your data here
}
}
...assuming that your submit button has the id 'submit_button'.
Hope this helps
Bye,
Christian
replace :
if (is_string($value) and $value == ''){
return true;
}
by :
if (strlen($value) > 0)
{
return true;
}
Related
So here's the deal. The ActiveForm below is supposed to receive two variables: $tt (radio) and $value (string numeric input) and send them to controller.
$value needs to be validated based on different rules and scenarios, which are defined in InputField model. $tt is radio value, so I'm not defining rules for it as of now.
The trick is, I'd like there to be some sort of input validation for $value, and the rules for it should change depending on what the user set as his $tt value. With this kind of configuration, controller never receives neither $tt, nor $value, I think the reason is conflicting rules for it.
Ideally, I would like my view to send checked radio $tt value (with jQuery or smthng) to controller, and for controller then to set scenario for the model so it has proper validation rules set up, which input field for $value in the view will operate on.
Yii2 experts: 1) can you explain me why my controller fails to receive any value. 2)suggest anything for what I was planning to do?
`
//View fragment
$valueForm = ActiveForm::begin([
'id' => 'input-field',
'action' => ['value-search/index'],
'method' => 'post',
'options' => ['class' => 'form-horizontal'] ]); ?>
<?= $valueForm->field($valueModel, 'tt')
->radioList(['P_sat'=>'Sat. Pressure', 'T_sat'=>'Sat. Temperature'])
->label('Select table type'); ?>
<?= $valueForm->field($valueModel, 'value')
->textInput(['options' => ['type'=>'number', 'name'=>'value','id'=>'value']]); ?>
<?php ActiveForm::end() ?>
//Model
class InputField extends \yii\base\Model
{
const SCENARIO_PSAT = 'P_sat';
const SCENARIO_TSAT = 'T_sat';
public $tt;
public $value;
public function scenarios() {
return [
self::SCENARIO_PSAT => ['tt','value'],
self::SCENARIO_TSAT => ['tt','value'],
];
}
public function rules() {
return [
['tt','safe'],
['value', 'double', 'numberPattern' => '/[0-9]+?(\.[0-9]{0,5})?/', 'min' => 0, 'max' => 22064,
'on' => self::SCENARIO_PSAT],
['value', 'double', 'numberPattern' => '/[0-9]+?(\.[0-9]{0,5})?/', 'min' => 0, 'max' => 373.95,
'on' => self::SCENARIO_TSAT],
];
}
//Operating action from the controller
public function actionIndex()
{
$inputModel = new InputField;
$inputModel->load(\Yii::$app->request->post());
$tt = $inputModel->tt;
switch($tt) {
case 'P_sat': $inputModel->scenario = $inputModel::SCENARIO_PSAT;
break;
case 'T_sat': $inputModel->scenario = $inputModel::SCENARIO_TSAT;
break;
default: throw new UserException('setTableType is not returning shit');
}
if ($inputModel->validate('value')) {
$searchValue = $inputModel->value;
$this->test = $inputModel->tt;
$this->test2 = $inputModel->value;
} else {
throw new UserException('Input is not validated');
}
return $this->render('index', [
//'provider' => $provider,
'array' => $this->test,
'array2' => $this->test2
]);
}
`
Both test and test2, which are supposed to receive $tt and $value from the model, are NULL :(
Scenario has to be set before loading a value
public function actionIndex()
{
$inputModel = new InputField;
$inputModel->load(\Yii::$app->request->post());
$tt = $inputModel->tt;
switch($tt) {
case 'P_sat': $inputModel->scenario = $inputModel::SCENARIO_PSAT;
break;
case 'T_sat': $inputModel->scenario = $inputModel::SCENARIO_TSAT;
break;
default: throw new UserException('setTableType is not returning shit');
}
if ($inputModel->load(\Yii::$app->request->post()) && $inputModel->validate('value')) {
$searchValue = $inputModel->value;
$this->test = $inputModel->tt;
$this->test2 = $inputModel->value;
} else {
throw new UserException('Input is not validated');
}
return $this->render('index', [
//'provider' => $provider,
'array' => $this->test,
'array2' => $this->test2
]);
}
So i have two radio button named Result that have value Fit and Unfit. And one form input that named Detail. If the Unfit is checked then the Detail must be filled. How do i set the validation. currently i have callback function in the controller like this:
public function _is_detail_required()
{
$result = $this->input->post('Result', true);
if ($result != 'Unfit') {
$detail = $this->input->post('Detail', true);
if ($result == 'Unfit') {
$this->form_validation->set_message('_is_detail_required', '%s harus diisi.');
return false;
}
}
return true;
}
and this is the validation rules (on models directory) that i set for the Detail:
$form_rules = array(
array(
'field' => 'Result',
'label' => 'Result',
'rules' => 'trim|xss_clean|required|max_length[50]'
),
array(
'field' => 'Detail',
'label' => 'Detail',
'rules' => 'trim|xss_clean|callback__is_detail_required|max_length[50]'
)
);
my problem is, this callback function is not working. how do i fix this? Any help will be very much appreciated.
You can try to add this in your form validation:
$CI =& get_instance();
if ($CI->input->post('Result') == 'Unfit') {
$form_rules[] = array(
'field' => 'Detail',
'label' => 'Detail',
'rules' => 'trim|xss_clean|required|max_length[50]'
);
}
Note: If your validation is located in your controller, use $this. If not, use $CI =& get_instance(); instead.
The callback function that I wrote is wrong, it didnt check if the input form (Detail) is empty, so this is the correct one
public function _is_detail_required()
{
$result = $this->input->post('Result', true);
if (! empty($result) && $result == 'Unfit') {
$detail = $this->input->post('Detail', true);
if (empty($detail)) {
$this->form_validation->set_message('_is_detail_required', '%s harus diisi.');
return false;
}
}
return true;
}
I am trying to develop a form validation system. But the problem is even though there is no data given by users as required the validation passes. Can't figure out where the problem is.
This is my form validation class
class Validation
{
private $_passed = false,
$_errors = array(),
$_db = null;
public function __construct() {
$this->_db = DB::getInstance();
}
public function check($source, $items= array()) {
foreach ($items as $item => $rules) {
foreach ($rules as $rule => $rule_value) {
$value = $source[$item];
if ($rule === 'required' && empty($value)) {
$this->addError("{$item} is required");
} else {
}
}
}
if (empty($this->_errors)) {
$this->_passed = true;
}
return $this;
}
private function addError($error) {
$this->errors[] = $error;
}
public function errors() {
return $this->_errors;
}
public function passed() {
return $this->_passed;
}
}
And this is the form page containing Html form.
require_once 'core/init.php';
if (Input::exists()) {
$validate = new Validation();
$validation = $validate->check($_POST, array(
'username' => array(
'required' => true,
'min' => 2,
'max' => 20,
'unique' => 'users'
),
'password' => array(
'required' => true,
'matches' => 'password'
),
'password_again' => array(
'required' => true,
'min' => 6
),
'name' => array(
'required' => true,
'min' => 2,
'max' => 60
),
));
if ($validation->passed()) {
//register new user
echo "passed"; //this passes even though users provides no data
} else {
print_r($validation->errors());
}
}
So, all i get is echo passed on the screen even though user provide no data at all. It should throw the errors instead. Please help. Thanks
addError writes in $this->errors, while the other methods use $this->_errors. (with underscore). The _errors array will remain empty, so _passed will be set to true in this statement:
if (empty($this->_errors)) {
$this->_passed = true;
}
How can i set the identical validator on a field without making it a required field in Zendframework 1 + allow the check of empty value.
here is the code
$this->addElement('password', 'password', array(
'label' => 'password',
'required' => false
),
));
$this->addElement('password', 'confirm', array(
'label' => 'confirm',
'required' => false,
'validators' => array(
array(
'validator' => 'Identical',
'options' => array(
'token' => 'password'
)
)
)
));
If the confirm element is set to 'required'=>false, the identical validator doesn't work if the value is empty.
You can't use Identical validator without required because in the isValid() method of Zend_Form_Element there is :
if ((('' === $value) || (null === $value))
&& !$this->isRequired()
&& $this->getAllowEmpty()
) {
return true;
}
and Zend_Form_Element_Password is an instance of Zend_Form_Element.
I think you have 3 possibilities:
Add required option in your confirm element, but you have a specific message required
Add allowEmpty option to false in your confirm element like this : 'allowEmpty' => false, instead of 'required' => false,
Create your own validator like the Cully Larson's answer. An other example it's the example #3 of the documentation about Writing validators. Otherwise, you can find more on the web. :)
I ended up writing my own validator for password confirmation:
class MyLib_Validate_PasswordConfirmation extends Zend_Validate_Abstract
{
const PASSWORD_MISMATACH = 'passwordMismatch';
protected $_messageTemplates = array(
self::PASSWORD_MISMATCH => 'This value does not match the confirmation value.'
);
/**
* Requires that 'password_confirm' be set in $context.
*/
public function isValid($value, $context = null)
{
$value = (string) $value;
$this->_setValue($value);
if (is_array($context)) {
if (isset($context['password_confirm'])
&& ($value == $context['password_confirm']))
{
return true;
}
} elseif (is_string($context) && ($value == $context)) {
return true;
}
$this->_error(self::PASSWORD_MISMATCH);
return false;
}
}
I'm fighting with a Zend_dojo_form.
Here is (part of) the code:
class Application_Form_RegistrationForm extends Zend_Dojo_Form {
private $_user;
private $_admin;
private $_teamadmin;
private $_newuser;
private $_redirect;
public function __construct($admin = false, $user = null, $redirect = '') {
//blablabla
parent::__construct();
}
public function init() {
Zend_Dojo::enableForm($this);
$this->setMethod('post');
$this->setAttribs(array(
'id' => 'formRegistration',
'name' => 'formRegistration',
));
//some decorators
if ($this->_admin) {
$this->addElement(
//blabla + inline javascript
'onChange' => "if(this == ".E_UserRole::OPERATOR.") dojo.query(\".perms\").style({ display:\"block\" }); else dojo.query(\".perms\").style({ display:\"none\" }); "
)
);
}
if (Application_Manager_Login::hasRole(E_UserRole::ADMIN)) {
//add some display:none elements
$permission_decorators = array(
"DijitElement",
"Errors",
array(array("data" => "HtmlTag"), array("tag" => "td", "class" => "perms", "style"=> "display:none", )),
array("Label", array("tag" => "td", "class" => "perms", "style"=> "display:none", 'escape' => false, 'requiredSuffix' => ' <span class="red">*</span>')),
array(array("row" => "HtmlTag"), array("tag" => "tr"))
);
//hidden element
$this->addElement(
'CheckBox',
'permission_content',
array(
'decorators' => $permission_decorators,
'label' => 'Gestione contenuti',
'checkedValue' => true,
'uncheckedValue' => false,
'checked' => $this->_user->permission_content,
)
);
}
//submit button and other stuff
}
}
As you can see I've put some inline javascript to show/hide some options when the user_role changes.
Now the situation is a bit complex. I could keep writing inline javascript but I'd like to declare a js function on the beginning and just call it from the onchange Event.
Since this form is called by several controllers I won't add this function manually each time a
new RegistrationForm();
is called.
Ok, I came up with this solution..
function addJavascript(){
echo "<script>
function toggle( e ){
alert(e);
if(e == ".E_UserRole::USER." || e == ".E_UserRole::ADMIN."){
dojo.query(\".perms\").style({ display:\"none\" });
}
else {
dojo.query(\".perms\").style({ display:\"block\" });
}
}
</script>
";
}
I declared this function inside the class and I just call it in the beginning with:
$this->addJavascript();
then in the onChange i call the toggle function I need (function that will become more complex, I need this workaround to make it readable) with:
$this->addElement(
//blabla
'onChange' => "toggle(this)",
)
);
hope this helps someone else :)