How to show validation message patchEntity - validation

I am using CakePHP3, I created de Config model with this table :
+----------------------+---------------------------+
| param | value |
+----------------------+---------------------------+
| dhcp_dns1 | 192.168.1.100 |
| dhcp_dns2 | 192.168.1.100 |
| dhcp_enabled | 1 |
| dhcp_end_ip | 192.168.1.200 |
| dhcp_netmask | 255.255.255.0 |
| dhcp_router | 192.168.1.100 |
| dhcp_start_ip | 192.168.1.100 |
| host_name | box |
I am using a pairs of param/value. param will not be alterable but only value will be alterable.
I have different kind of value (ip address, text, numeric) that I need to validate before change.
So the controller use multi-step save data, to validate different kind of values.
I created a Form (for test) to update host_name (alphaNumeric Validation) and dhcp_start_ip (ipv4 Validation).
For validation I used this :
http://book.cakephp.org/3.0/en/orm/validation.html#using-a-different-validation-set
Validation works fine but it not display message if validation not match. How I can show message to say Hostname or IP address is wrong format when patchEntity ?
Maybe I am in the wrong way to do it...
This is the view :
<div class="config form large-10 medium-9 columns">
<fieldset>
<legend><?= __('DHCP Config')?></legend>
<?= $this->Form->create('config') ?>
<?php
//$params = array('host_name', 'host_ip', 'host_netmask', 'host_gateway', 'host_dns1', 'host_dns2');
echo $this->Form->input('host_name',[
'label' => __('Hostname : '),
'default' => $host_name->value
]);
echo $this->Form->input('dhcp_start_ip',[
'label' => __('DHCP Pool start : '),
'default' => $dhcp_start_ip->value
]);
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</div>
Controller :
public function test()
{
$host_name = $this->Config->get('host_name', ['contain' => []]);
$dhcp_start_ip = $this->Config->get('dhcp_start_ip', ['contain' => []]);
if ($this->request->is(['patch', 'post', 'put'])) {
$confdata = array(
'param' => 'dhcp_start_ip',
'value' => $this->request->data['dhcp_start_ip']
);
$host_name_data = array(
'param' => 'host_name',
'value' => $this->request->data['host_name']
);
// 1ere methode de validation
$dataconfig = $this->Config->patchEntity($dhcp_start_ip, $confdata, [
'validate' => 'ipaddr',
]);
$this->Config->save($dataconfig);
$dataconfig = $this->Config->patchEntity($host_name, $host_name_data, [
'validate' => 'name',
]);
$this->Config->save($dataconfig);
}
$this->set('dhcp_start_ip', $dhcp_start_ip);
$this->set('host_name', $host_name);
}
Model :
public function validationIpaddr(Validator $validator)
{
$validator->notEmpty('value')
->add('value', 'notEmpty', [
'rule' => ['ip', 'ipv4'],
'message' => __('Invalid IP Address')
]);
return $validator;
}
public function validationName(Validator $validator)
{
$validator
->add('value', 'notEmpty', [
'rule' => ['alphaNumeric'],
'message' => __('Invalid Name')
]);
return $validator;
}

Try this, In your controller
$dataconfig = $this->Config->patchEntity($dhcp_start_ip, $confdata, [
'validate' => 'ipaddr',
]);
if (!$dataconfig->errors()) {
$this->Config->save($dataconfig);
}else{
debug($dataconfig->errors());
$this->Flash->error('Invalid IP Address!');
}

Related

Codeigniter 4 Undefined index: user_id

I am trying to show display a "join" result and only want to show the user_id, username, email only once for users table even if there are many records on the other table, so I tried to make a query builder like below:
Table users | Table add_game
|
user_id | username | email | game_id | user_id | ign | acc_id
1 | userA | userA#email.com | 1 | 1 | ignA | accA
2 | userB | userB#gmail.com | 2 | 1 | ignB | accB
| 1 | 2 | ignB | accB
| 3 | 2 | ignD | accD
Model :
<?php namespace App\Models;
use CodeIgniter\Database\ConnectionInterface;
class LoginModel{
protected $db;
public function __construct(ConnectionInterface &$db){
$this->db =& $db;
}
public function login(string $str)
{
return $this->db->table('users')
->groupStart()
->where('username', $str)
->orWhere('email', $str)
->groupEnd()
->join('add_game', 'add_game.user_id = users.user_id')
//->distinct('users.user_id')
//->select(("GROUP_CONCAT(game_id, ign, acc_id) AS userdata"))
->get()
->getResultArray();
}
}
Controller :
public function login()
{
$data = [];
helper(['form']);
$validation = \Config\Services::validation();
$db = db_connect();
$model = new LoginModel($db);
$user = $model->login($this->request->getVar('userlogin'));
$this->setUserSession($user);
echo view('templates/header', $data);
echo view('account/login', $data);
echo view('templates/footer', $data);
}
private function setUserSession($user){
$data = [
'user_id' => $user['user_id'],
'username' => $user['username'],
'email' => $user['email'],
'firstname' => $user['firstname'],
'lastname' => $user['lastname'],
'dob' => $user['dob'],
'country' => $user['country'],
'country_code' => $user['c_code'],
'contact' => $user['contact'],
'game_id' => $user['game_id'],
'ign' => $user['ign'],
'acc_id' => $user['acc_id'],
'isLoggedIn' => true
];
session()->set($data);
return true;
}
But right now I am getting
Undefined index: user_id
error message. Previously there was no issue or error when I was using without query builder for my login :
public function login(string $str, string $fields, array $data)
{
return $this->where('username', $data['userlogin'])->orWhere('email', $data['userlogin'])
->first();
}
How to resolve this error?
As by your comment (image) your array looks like:
Array
(
[0]=>Array
(
[user_id]=>1,
[user_name]=>'test',
//etc.
)
)
You get the
Undefined index: user_id
error message, because of addressing wrongly the array while using 'user_id' => $user['user_id']
the correct way is to add the index you want to retrieve like:
$this->setUserSession($user[0]); // where 0 can be changed to the index you pretend
now the array is flattened and 'user_id' => $user['user_id'] doesn't throw an error anymore.

How to tell Validator to call another Rule checker

I have this table :
+-----+-------------+------------+--------------+---------+--------------+--------------------+-------------------+-------------+----------+------------+--------+---------+
| id | rule_number | profile_id | dest_ip_type | dest_ip | dest_ip_mask | dest_iprange_first | dest_iprange_last | dest_fqdn | protocol | dest_ports | target | enabled |
+-----+-------------+------------+--------------+---------+--------------+--------------------+-------------------+-------------+----------+------------+--------+---------+
| 187 | 3 | 56 | net | 8.8.8.8 | 32 | | | | both | 53 | ACCEPT | 1 |
| 188 | 2 | 56 | range | | 0 | 192.168.1.20 | 192.168.1.250 | | both | 53 | ACCEPT | 1 |
| 189 | 1 | 56 | fqdn | | 0 | | | my.host.com | both | 80 | ACCEPT | 1 |
+-----+-------------+------------+--------------+---------+--------------+--------------------+-------------------+-------------+----------+------------+--------+---------+
From my controller I call Validator depending on "dest_ip_type" :
public function validationNet(Validator $validator)
{
$validator = $this->validationDefault($validator);
$validator
->notEmpty('dest_ip', __('IP is required'))
->notEmpty('dest_ip_mask', __('Mask is required'))
->allowEmpty('dest_iprange_first')
->allowEmpty('dest_iprange_last')
->allowEmpty('dest_fqdn');
$validator
->add('dest_ip', 'notEmpty', [
'rule' => ['ip', 'ipv4'],
'message' => __('Invalid IP Address')
]);
return $validator;
}
public function validationIprange(Validator $validator)
{
$validator = $this->validationDefault($validator);
$validator
->notEmpty('dest_iprange_first', __('IP is required'))
->notEmpty('dest_iprange_last', __('IP is required'))
->allowEmpty('dest_ip')
->allowEmpty('dest_ip_mask')
->allowEmpty('dest_fqdn');
$validator
->add('dest_iprange_first', 'ipv4', [
'rule' => ['ip', 'ipv4'],
'message' => __('Invalid IP Address')
]);
$validator
->add('dest_iprange_last', 'ipv4', [
'rule' => ['ip', 'ipv4'],
'message' => __('Invalid IP Address')
]);
return $validator;
}
public function validationFqdn(Validator $validator)
{
$validator = $this->validationDefault($validator);
$validator
->notEmpty('dest_fqdn')
->allowEmpty('dest_iprange_first')
->allowEmpty('dest_iprange_last')
->allowEmpty('dest_ip')
->allowEmpty('dest_ip_mask');
$validator
->add('dest_fqdn', 'notEmpty', [
// Regex for FQDN
'rule' => ['custom', "/(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)+[a-zA-Z]{2,63}$)/i"],
'message' => __('Invalid Hostname')
]);
return $validator;
}
I created 3 RulesChecker bellow to check unique differently, but How can I tell Validator or Controller to not call default "buildRules" function but force to call alternative buildRules ?
public function buildNetRules(RulesChecker $rules)
{
$rules->add($rules->existsIn(['profile_id'], 'Profiles'));
$rules->add($rules->isUnique(['profile_id', 'dest_ip', 'protocol', 'dest_ports']));
return $rules;
}
public function buildRangeRules(RulesChecker $rules)
{
$rules->add($rules->existsIn(['profile_id'], 'Profiles'));
$rules->add($rules->isUnique(['profile_id', 'dest_iprange_first', 'dest_iprange_last', 'protocol', 'dest_ports']));
return $rules;
}
public function buildFqdnRules(RulesChecker $rules)
{
$rules->add($rules->existsIn(['profile_id'], 'Profiles'));
$rules->add($rules->isUnique(['profile_id', 'dest_fqdn', 'protocol', 'dest_ports']));
return $rules;
}
I found the solution by my self. buildRules is able to check different isunique rules inside de same function. Maybe buildRules don't check isUnique rules on values that are Empty or null...
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->existsIn(['profile_id'], 'Profiles'));
$rules->add($rules->isUnique(['profile_id', 'dest_ip', 'protocol', 'dest_ports']));
$rules->add($rules->isUnique(['profile_id', 'dest_iprange_first', 'dest_iprange_last', 'protocol', 'dest_ports']));
$rules->add($rules->isUnique(['profile_id', 'dest_fqdn', 'protocol', 'dest_ports']));
return $rules;
}

How to save data in model using Yii2 grid with Editable column

Can anyone help on editable column in gridview.I am using Yii2 and stuck with it.
I can't save data in my model.I can post from gridview column.
In my grid view:
$gridColumns= [
'patient_no',
'category_name',
'sdv_text',
[
'class' => 'kartik\grid\EditableColumn',
'attribute'=>'sdv_status',
'pageSummary' => true,
'editableOptions'=> [
'header' => 'profile',
'format' => Editable::FORMAT_BUTTON,
'inputType' => Editable::INPUT_DROPDOWN_LIST,
'data'=> $StatusList,
]
],
// 'date_sdv_performed',
[
'class' => 'kartik\grid\EditableColumn',
'attribute'=>'date_sdv_performed',
'editableOptions' => [
'header' => 'Date Sdv Performed',
'inputType'=>\kartik\editable\Editable::INPUT_WIDGET,
'format'=>\kartik\datecontrol\DateControl::FORMAT_DATE,
'widgetClass'=> 'kartik\datecontrol\DateControl',
],
],
[
'class' => 'kartik\grid\EditableColumn',
'attribute'=>'comments',
'hAlign' => 'top',
'vAlign' => 'middle',
'width'=>'100px',
'headerOptions' => ['class' => 'kv-sticky-column'],
'contentOptions' => ['class' => 'kv-sticky-column'],
'pageSummary' => true,
],
];
GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'layout'=>"{items}\n{pager}",
'pjax'=>true,
'toolbar' => [
'{export}',
'{toggleData}'
],
'responsive'=>true,
'hover'=>true,
'columns' => $gridColumns
]);
In my controller action:
public function actionMonitoring($site_name)
{
$this->layout = 'sdv-carolina-main';
$Countries = new Countries;
$model = new Flagging;
$searchModel = new FlaggingSearch();
$dataProvider = $searchModel->monitoringsearch($site_name);
$allocatedsites = new AllocatedSites;
if (Yii::$app->request->post('hasEditable'))
{
$model = $this->findModel($model['flagging_id']);
$out = Json::encode(['output'=>'', 'message'=>'']);
$post = [];
$posted = current($_POST['Flagging']);
$post['Flagging'] = $posted;
if ($model->load($post)) {
$model->save();
$output = '';
if (isset($posted['sdv_status']))
{
$output = $model->sdv_status;
}
$out = Json::encode(['output'=>$output, 'message'=>'']);
}
echo $out;
return;
}
return $this->render('monitoring',
[
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'Countries' => $Countries,
'model'=>$model,
'allocatedsites' => $allocatedsites,
]);
}
The problem is I can't update my model because of I can't get the id.
I just need the id to update specific row.How can I get the id while using editable column?
Thanks in advance.
Actually the solution is easy. I just need the id of that specific row to update that.And in my ajax post I got something like this:
Flagging[0][status] NO
_csrf TlhyUm5kajAoNxgVNy0/ZCoyHApZUlNUFh0rB1gRPGoAFSIdGSAifQ==
editableIndex 0
editableKey 13
hasEditable 1
and found the editableKey is the id of that specific row!
Now in my controller I write down this code given below:
$_id=$_POST['editableKey'];
$model = $this->findModel($_id);
Here $_id is the posted editableKey value which is the id of the specific row.
and with the id I use it to get the specific model and just update data based on that id.

CakePHP 2 & Translate Behavior: save multiple translations in a single form

Its possibile save multiple translations of the same field in a single form?
I have a model with Behavior Translate to translate the name field. The three translations (deu, eng, ita) are properly recorded in the i18n table but the field is not properly validated! Any suggestions?
app/Model/Category.php
class Category extends AppModel {
public $actsAs = array('Translate' => array('name' => 'TranslateName'));
public $validate = array(
'name' => array(
'notempty' => array(
'rule' => array('notempty'),
'message' => 'Error notempty',
),
),
);
...
app/View/Categories/admin_edit.ctp
<?php
echo $this->Form->create('Category');
echo $this->Form->input('Category.id');
echo $this->Form->input('Category.name.deu', array('label' => __d('Category', 'Name Deu')));
echo $this->Form->input('Category.name.eng', array('label' => __d('Category', 'Name Eng')));
echo $this->Form->input('Category.name.ita', array('label' => __d('Category', 'Name Ita')));
echo $this->Form->end(__d('app', 'Submit'));
?>
app/View/Controller/CategoriesController.php
if ($this->Category->save($this->request->data)) {
$this->Session->setFlash(__d('Category', 'The category has been saved'));
} else {
$this->Session->setFlash(__d('Category', 'The category could not be saved. Please, try again.'));
}
I have a similar Problem
But you can try out this - it should solve it for you: https://github.com/zoghal/cakephp-MultiTranslateBehavior

Why aren't validation errors being displayed in CakePHP?

I'm trying to perform validation in the login page for the name,email and password fields. If the input fails validation,the error message should be displayed.
But here,when I fill in the details and submit, it is redirected to the next page. Only the value is not saved in the database.
Why is the message not displayed?
This is my model:
class User extends AppModel {
var $name = 'User';
var $validate = array(
'name' => array(
'alphaNumeric' => array(
'rule' => 'alphaNumeric',
'required' => true,
'message' => 'Alphabets and numbers only'
),
'between' => array(
'rule' => array('between', 5, 15),
'message' => 'Between 5 to 15 characters'
)
),
'password' => array(
'rule' => array('minLength', '8'),
'message' => 'Mimimum 8 characters long'
),
'email_id' => 'email'
);
function loginUser($data) {
$this->data['User']['email_id'] = $data['User']['email_id'];
$this->data['User']['password'] = $data['User']['password'];
$login = $this->find('all');
foreach ($login as $form):
if ($this->data['User']['email_id'] == $form['User']['email_id'] && $this->data['User']['password'] == $form['User']['password']) {
$this->data['User']['id'] = $this->find('all',
array(
'fields' => array('User.id'),
'conditions' => array(
'User.email_id' => $this->data['User']['email_id'],
'User.password'=>$this->data['User']['password']
)
)
);
$userId=$this->data['User']['id'][0]['User']['id'];
return $userId;
}
endforeach;
}
function registerUser($data) {
if (!empty($data)) {
$this->data['User']['name'] = $data['User']['name'];
$this->data['User']['email_id'] = $data['User']['email_id'];
$this->data['User']['password'] = $data['User']['password'];
if($this->save($this->data)) {
$this->data['User']['id']= $this->find('all', array(
'fields' => array('User.id'),
'order' => 'User.id DESC'
));
$userId=$this->data['User']['id'][0]['User']['id'];
return $userId;
}
}
}
}
This is my controller:
class UsersController extends AppController {
var $name = 'Users';
var $uses=array('Form','User','Attribute','Result');
var $helpers=array('Html','Ajax','Javascript','Form');
function login() {
$userId = $this->User->loginUser($this->data);
if($userId>0) {
$this->Session->setFlash('Login Successful.');
$this->redirect('/forms/homepage/'.$userId);
break;
} else {
$this->flash('Login Unsuccessful.','/forms');
}
}
function register() {
$userId=$this->User->registerUser($this->data);
$this->Session->setFlash('You have been registered.');
$this->redirect('/forms/homepage/'.$userId);
}
}
EDIT
Why is the message,example,"Minimum 8 characters long", is not being displayed when give less than 8 characters in the password field?
<!--My view file File: /app/views/forms/index.ctp -->
<?php
echo $javascript->link('prototype.js');
echo $javascript->link('scriptaculous.js');
echo $html->css('main.css');
?>
<div id="appTitle">
<h2> formBuildr </h2>
</div>
<div id="register">
<h3>Register</h3>
<?php
echo $form->create('User',array('action'=>'register'));
echo $form->input('User.name');
echo $form->error('User.name','Name not found');
echo $form->input('User.email_id');
echo $form->error('User.email_id','Email does not match');
echo $form->input('User.password');
echo $form->end('Register');
?>
</div>
<div id="login">
<h3>Login</h3>
<?php
echo $form->create('User',array('action'=>'login'));
echo $form->input('User.email_id');
echo $form->input('User.password');
echo $form->end('Login');
?>
</div>
Your validation seems correct
How about trying the following:
Make sure set your $form->create to the appropriate function
Make sure there is no $this->Model->read() before issuing Model->save();
Edit
Did you have the following?:
function register()
{
//do not put any $this->User->read or find() here or before saving pls.
if ($this->User->save($this->data))
{
//...
}
}
Edit2
IF you're doing a read() or find() before saving the Model then that will reset the fields. You should be passing the variable as type=hidden in the form. I hope i am making sense.
Edit3
I think you need to move your registerUser() into your controller because having that function in the model doesn't provide you a false return. it's always going to be true even if it has validation errors.
Comment out the redirect line and set the debug to 2 in config/core.php. Then look at the sql that is being generated to see if your insert is working. If the errors are not being displayed, maybe in the view, you are using $form->text or $form->select instead of the $form->input functions. Only the $form->input functions will automatically display the error messages.

Resources