Codeigniter3 - FormValidation - validate for boolean is always "false" - validation

I'm checking JSON input data with codeigniters native FormValidation library.
I've set up the validation rules like this:
$this->form_validation->set_rules(
'active', 'myCheckbox',
'required|is_bool'
);
here is the JSON data
{
"data": {
"type": "items",
"attributes": {
"category": "5",
"description" : "my description",
"active": false
}
}
}
Problem: The rule "required" interprets the input as not present as soon as the JSON value of active is false, so that the validation only succeed if value of active is true
Question: Is there a way around this, besides changing value of active into a numeric value 1or 0 and therefore change lots of other correspondending code?
EDIT: trying isset instead of required behaves different, but also not satisfying
$this->form_validation->set_rules(
'active', 'myCheckbox',
'isset|is_bool'
);
EDIT No.2: trying in_list[false,true] instead of is_bool behaves right, but the JSON does not look right anymore, because the boolean value must be sent as a string
$this->form_validation->set_rules(
'active', 'myCheckbox',
'required|in_list[false,true]'
);
here is the JSON data
{
"data": {
"type": "items",
"attributes": {
"category": "5",
"description" : "my description",
"active": "false"
}
}
}

I had the same probleam.
I fixed it creating my own "required" and my own "is_bool".
I created a "is_required_not_null" and "is_boolean" functions and put then in my helper, so I can use it where I need.
Note that I used Identical operator(===) to make sure of variables types and values.
See below...
Helper File:
/yourApplication/helpers/yourHelperFileName_helper.php
function is_boolean($value)
{
try {
if ($value === true || $value === false)
return true;
else
return false;
} catch (\Throwable $th) {
return false;
}
}
function is_required_not_null($value)
{
try {
if ($value === null)
return false;
if ($value === true || $value === false)
return true;
if (is_array($value) && count($value) == 0) {
return false;
} else {
if (trim($value) == "")
return false;
}
return true;
} catch (\Throwable $th) {
return false;
}
}
Usage sample:
$data = $this->input->post(); //yours inputs ...
$rules = [
[
'field' => 'fieldName',
'rules' => 'is_required_not_null|is_boolean',
'label' => 'Field Name',
'errors' => [
'is_required_not_null' => 'Field %s is required.',
'is_boolean' => 'Field %s must be boolean.',
],
],
]; //yours rules ...
$this->load->library('form_validation');
$this->form_validation->set_data($data);
$this->form_validation->set_rules($rules);
if ($this->form_validation->run()) {
//Valid Code ...
}
else{
//Not Valid Code ...
}
Source docs:
https://codeigniter.com/userguide3/libraries/form_validation.html#validating-an-array-other-than-post
https://codeigniter.com/userguide3/libraries/form_validation.html#setting-rules-using-an-array
https://codeigniter.com/userguide3/libraries/form_validation.html#callable-use-anything-as-a-rule
https://codeigniter.com/userguide3/libraries/form_validation.html#setting-validation-rules

Related

how to pass v-model value id to laravel controller?

I have a problem passing the select option id to laravel controller using axios post. What i want to achieve here is that i want to pass the id value in v-model to laravel controller so that i can fetch other value of the device based on the id.
Here is my select option:
<div class="form-group">
<select class="form-select form-select-lg mb-3" v-model="choosed">
<option :value="null">Choose Device to Send SMS</option>
<option v-for="item in devices" :key="item.id" v-bind:value="item.id">{{ item.device_name }}</option>
</select>
</div>
Here is my data:
export default {
data() {
return {
search: "",
contacts: {},
devices: {},
file: '',
paginate: 5,
selected: [],
choosed: null,
select_all: false,
maxCount: 320,
remainingCount: 320,
hasError: false,
form: {
first_name: null,
last_name: null,
mobile_number: null,
},
sms: {
// secret: null,
// deviceID: null,
message: null,
},
}
},
Here is my axios post to connect to controller:
Send(selected, choosed) {
const vm = this;
vm.sms.ids = selected;
vm.sms.chooseds = choosed;
axios.post("/api/send-sms", this.sms)
.then(function(response) {
if(response.data.status == 'success'){
vm.getContact();
vm.select_all = false;
vm.selected = [];
vm.choosed = null;
// this.sms.secret = null;
// this.sms.deviceID = null;
vm.sms.message = null;
swal('Send Success!', response.data.message,'success');
}
else{
swal('Error',response.data.message,'error');
}
// if(response.data.status == 'error'){
// swal('Error',response.data.message,'error');
// }
// if(response.data.status == 'errors'){
// swal('Error',response.data.message,'error');
// }
})
.catch(function (error) {
console.log(error)
});
},
Here is my controller:
public function sendMessage(Request $request){
date_default_timezone_set('Asia/Manila');
ini_set('max_execution_time', '0');
// $secret = $request->input('secret');
// $deviceID = $request->input('deviceID');
$message = $request->input('message');
$device = $request->input('chooseds');
if(empty($request->input('ids'))) {
return response()->json([
'status' => 'error',
'message' => 'Please Select Contact!'
]);
}
if($device == null) {
return response()->json([
'status' => 'error',
'message' => 'Please Select Device!'
]);
}
// if(empty($secret) || empty($deviceID) || empty($message)) {
if(empty($message)) {
return response()->json([
'status' => 'error',
'message' => 'Input fields are required!'
]);
}
else
{
if(!empty($request->input('ids')) || !empty($device)) {
$single_user_id = $request->input('ids');
$device_secret = Device::where('id', $device)->value('device_secret');
$device_id = Device::where('id', $device)->value('device_id');
$time = time();
$secretMd5 = md5($device_secret.$time);
foreach ($single_user_id as $id) {
$number = Contact::where('id', $id)->value('mobile_number');
file_get_contents("http://server_url/?to=".urlencode(trim($number))."&text=".urlencode($message)."&secret=$secretMd5&time=$time&deviceID=".$device_id);
sleep(20);
}
return response()->json([
'status' => 'success',
'message' => 'Selected Contact Succesfully Send SMS!'
]);
}
}
}
First you don't need to define 'this' in your function if u used Laravel+inertia+vue. your code is a little messy ill give you how you should pass and get parameters So try the axios call like below
axios.post("/api/send/sms", {'name' : 'Unswaa'});
then in your controller you can get the name like below
$request->name;

do not show the success message if the data hasnt been updated n a form laravel

i have a form whereby on updating the data and storing it to the database it shows a success message.if one of the inputs isn't filled it shows an error.am getting a bug whereby when i want to re-update the data and i open the form with the existing inputs when i click save the data should just redirect back to the previous page and not show the success message as the data hasnt being updated.how can i achieve this,am looking for a logic here fellow devs..here is my update function code
public function update(Request $request)
{
try {
$validation = Validator::make($request->all(), [
'systemid' => 'required',
'category' => 'required',
'subcategory' => 'required',
'prdcategory' => 'required',
'prdbrand' => 'required'
]);
Log::debug('Request: '.json_encode($request->file()));
if ($validation->fails()) {
throw new \Exception("validation_error", 19);
}
$systemid = $request->systemid;
$product_details = product::where('systemid', $systemid)->first();
$changed = false;
if ($request->has('product_name')) {
if ($product_details->name != $request->product_name) {
$product_details->name = $request->product_name;
$changed = true;
}
}
if ($request->has('category')) {
if ($product_details->prdcategory_id != $request->category) {
$product_details->prdcategory_id = $request->category;
$changed = true;
}
}
if ($request->has('subcategory')) {
if ($product_details->prdsubcategory_id != $request->subcategory) {
$product_details->prdsubcategory_id = $request->subcategory;
$changed = true;
}
if ($product_details->ptype == 'voucher') {
$voucher = voucher::where('product_id', $product_details->id)->first();
if($voucher->subcategory_id != $request->subcategory){
$voucher->subcategory_id = $request->subcategory;
$voucher->save();
$changed = true;
}
}
}
if ($request->has('prdcategory')) {
if ($product_details->prdprdcategory_id != $request->prdcategory) {
$product_details->prdprdcategory_id = $request->prdcategory;
$changed = true;
}
}
if ($request->has('prdbrand')) {
if ($product_details->brand_id != $request->prdbrand) {
$product_details->brand_id = $request->prdbrand;
$changed = true;
}
}
if ($request->has('description')) {
if ($product_details->description != $request->description) {
$product_details->description = $request->description;
$changed = true;
}
}
if ($changed == true || true) {
$product_details->save();
$msg = "Product information updated successfully";
$data = view('layouts.dialog', compact('msg'));
//i have added this code but it doesnt work
} else if($changed == false) {
return back();
$data = '';
}
}
return $data;
}
my laravel project version is 5.8
The following line will always evaluate to True
$changed == true || true
And you have a catch statement missing at the end so I had to add it.
And I advise you to simply get the dirty version of $product_details.
You can use $product_details->isDirty() // boolean.
Or even better way is to use $product_details->wasChanged() // boolean
Here is the code after some tweaks:
public function update(Request $request)
{
try {
$validation = Validator::make($request->all(), [
'systemid' => 'required',
'category' => 'required',
'subcategory' => 'required',
'prdcategory' => 'required',
'prdbrand' => 'required'
]);
Log::debug('Request: '.json_encode($request->file()));
if ($validation->fails()) {
throw new \Exception('validation_error', 19);
}
$systemid = $request->systemid;
$product_details = Product::where('systemid', $systemid)->first();
$changed = false;
// Looping for all inputs:
$fieldsToCheck = [
'name' => 'product_name',
'prdcategory_id' => 'category',
'prdsubcategory_id' => 'subcategory',
'prdprdcategory_id' => 'prdcategory',
'brand_id' => 'prdbrand',
'description' => 'description',
];
foreach ($fieldsToCheck as $productColumnName => $requestFieldName) {
$requestInput = $request->{$requestFieldName};
if ($request->has($requestFieldName)) {
if ($product_details->$productColumnName != $requestInput) {
$product_details->$productColumnName = $requestInput;
$changed = true;
}
}
// Exception for Sub Category to check for the voucher.
if ($requestFieldName == 'subcategory') {
$this->handleVoucher($requestInput);
}
}
// here I advise you to simply get the dirty version of $product_details
// you can use $product_details->isDirty() // boolean
// or even better use $product_details->wasChanged() // boolean
if ($changed) {
$product_details->save();
$msg = 'Product information updated successfully';
$data = view('layouts.dialog', compact('msg'));
} else {
return back();
// Todo Mo: No need for this line so I commented it out.
//$data = '';
}
} catch (\Exception $e) {
dd($e->getMessage(), 'Oops, error occurred');
}
return $data;
}
private function handleVoucher($product_details, $subcategory)
{
if ($product_details->ptype == 'voucher') {
$voucher = voucher::where('product_id', $product_details->id)->first();
if ($voucher->subcategory_id != $subcategory) {
$voucher->subcategory_id = $subcategory;
$voucher->save();
}
}
}

How to call Laravel helper method in Config/Constants.php

I am giving this error
Call to undefined function getDefaultConfigByHost()
In constants.php line 5:
In helper.php
function getDefaultConfigByHost($developmentValue = null, $testValue = null,
$productionValue = null)
{
try {
if (! isset($_SERVER['HTTP_HOST'])) {
return null;
}
$domain = $_SERVER['HTTP_HOST'];
switch ($domain) {
case 'xxx.gglemd.com':
return $developmentValue;
case '192.168.1.18:8001':
return $testValue;
case 'yyy.service.com':
return $productionValue;
default:
return '';
}
} catch (Exception $exception) {
return '';
}
}
In constants.php
<?php
return [
'api' => [
'base' => env('API_BASE', getDefaultConfigByHost(),
'sfile_base' => env('SXFILE_API_BASE', getDefaultConfigByHost('')),
'private_key' => env('API_REQUEST_PRIVATE_KEY', 'bn-sjaddasdsadsadasdas'),
],
];

Yii2: How to validate relation?

I have a model with the relation called "reviews":
class ReportStructure extends \yii\db\ActiveRecord
{
const REVIEW_LIST_NAME = 'reviews';
public function getReviewList()
{
return $this->hasOne(FileIndexList::className(), ['id_owner' => 'id_report'])
->where('list_name = :list_name', [':list_name' => self::REVIEW_LIST_NAME]);
}
public function getReviews()
{
return $this->hasMany(FileIndex::className(), ['id_file_index' => 'id_file_index'])->via('reviewList');
}
}
In View, the reviews are displayed by GridView widget. The user can add or delete reviews by the other View. The user should specify at least one review. I added the validation rule to the model:
public function rules()
{
return [
['reviews', 'checkReviews'],
];
}
public function checkReviews($attribute)
{
if (count($this->reviews) === 0) {
$this->addError($attribute, 'You should add at least one review');
}
}
But it seems that rule even not fired.
public function actionIndex($idSupply, $restoreTab = false) {
$this->initData($idSupply, $report, $reestrData, $structure, $elements);
$ok = $report->load(Yii::$app->request->post()) &&
$reestrData->load(Yii::$app->request->post()) &&
Model::loadMultiple($elements, Yii::$app->request->post());
if($ok) {
$ok = $report->validate() &&
$reestrData->validate() &&
Model::validateMultiple($elements) &&
$structure->validate();
if($ok) {
$report->id_status = Status::STATUS_VERIFIED;
$this->saveData($report, $reestrData, $structure, $elements);
return $this->redirect(['supplies/update', 'id' => $idSupply]);
}
}
return $this->render('index', [
'structure' => $structure,
'report' => $report,
'reestrData' => $reestrData,
'elements' => $elements,
'restoreTab' => $restoreTab
]);
}
That's how the data is initialized. $elements are the objects of one class, I use tabular input for them.
private function initData($idSupply, &$report, &$reestrData, &$structure, &$elements) {
$report = \app\models\Reports::findOne($idSupply);
$reestrData = \app\models\ReestrData::findOne($report->id_reestr_data);
$structure = \app\models\report\ReportStructure::findOne($report->id_supply);
$elements = [
'titleIndex' => FileIndex::getInstance($structure->id_title_index, $structure->getAttributeLabel('id_title_index')),
'abstractIndex' => FileIndex::getInstance($structure->id_abstract_index, $structure->getAttributeLabel('id_abstract_index')),
'technicalSpecificationIndex' => FileIndex::getInstance($structure->id_technical_specification_index, $structure->getAttributeLabel('id_technical_specification_index')),
'contentsIndex' => FileIndex::getInstance($structure->id_contents_index, $structure->getAttributeLabel('id_contents_index')),
'imageListIndex' => FileIndex::getInstance($structure->id_image_list_index, $structure->getAttributeLabel('id_image_list_index'), false),
'tableListIndex' => FileIndex::getInstance($structure->id_table_list_index, $structure->getAttributeLabel('id_table_list_index'), false),
'textAnnexListIndex' => FileIndex::getInstance($structure->id_text_annex_list_index, $structure->getAttributeLabel('id_text_annex_list_index'), false),
'graphAnnexListIndex' => FileIndex::getInstance($structure->id_graph_annex_list_index, $structure->getAttributeLabel('id_graph_annex_list_index'), false),
'glossaryIndex' => FileIndex::getInstance($structure->id_glossary_index, $structure->getAttributeLabel('id_glossary_index'), false),
'reportIntroductionIndex' => FileIndex::getInstance($structure->id_report_introduction_index, $structure->getAttributeLabel('id_report_introduction_index')),
'reportMainPartIndex' => FileIndex::getInstance($structure->id_report_main_part_index, $structure->getAttributeLabel('id_report_main_part_index')),
'reportConclusionIndex' => FileIndex::getInstance($structure->id_report_conclusion_index, $structure->getAttributeLabel('id_report_conclusion_index')),
'bibliographyIndex' => FileIndex::getInstance($structure->id_bibliography_index, $structure->getAttributeLabel('id_bibliography_index')),
'metrologicalExpertiseIndex' => FileIndex::getInstance($structure->id_metrologicalexpertise_index, $structure->getAttributeLabel('id_metrologicalexpertise_index')),
'patentResearchIndex' => FileIndex::getInstance($structure->id_patent_research_index, $structure->getAttributeLabel('id_patent_research_index')),
'costStatementIndex' => FileIndex::getInstance($structure->id_cost_statement_index, $structure->getAttributeLabel('id_cost_statement_index')),
];
}
And tht's how the data is saved:
private function saveData($report, $reestrData, $structure, $elements) {
$reestrData->save(false);
$report->save(false);
foreach ($elements as $element) {
$element->save(false);
}
$structure->id_title_index = $elements['titleIndex']->id_file_index;
$structure->id_abstract_index = $elements['abstractIndex']->id_file_index;
$structure->id_technical_specification_index = $elements['technicalSpecificationIndex']->id_file_index;
$structure->id_contents_index = $elements['contentsIndex']->id_file_index;
$structure->id_image_list_index = $elements['imageListIndex']->id_file_index;
$structure->id_table_list_index = $elements['tableListIndex']->id_file_index;
$structure->id_text_annex_list_index = $elements['textAnnexListIndex']->id_file_index;
$structure->id_graph_annex_list_index = $elements['graphAnnexListIndex']->id_file_index;
$structure->id_glossary_index = $elements['glossaryIndex']->id_file_index;
$structure->id_report_introduction_index = $elements['reportIntroductionIndex']->id_file_index;
$structure->id_report_main_part_index = $elements['reportMainPartIndex']->id_file_index;
$structure->id_report_conclusion_index = $elements['reportConclusionIndex']->id_file_index;
$structure->id_bibliography_index = $elements['bibliographyIndex']->id_file_index;
$structure->id_metrologicalexpertise_index = $elements['metrologicalExpertiseIndex']->id_file_index;
$structure->id_patent_research_index = $elements['patentResearchIndex']->id_file_index;
$structure->id_cost_statement_index = $elements['costStatementIndex']->id_file_index;
$structure->save(false);
}
I eventually decided not to use validation for the relation at all and simply check reviews count in the controller:
if (count($structure->reviews) === 0) {
$ok = false;
Yii::$app->session->setFlash('danger', 'You should add at least one review!');
}
I think it's better to check it in beforeDelete method.
you can add this method to your model, and check, if it's the only review, then returns false.
public function beforeDelete()
{
if (!parent::beforeDelete()) {
return false;
}
if(self::find()->count() >1)
return true;
else
return false;
}

Why does this webform uploaded file via ajax throw an error in Drupal 7?

I have a webform and mymodule which alters it. The webform has a field stelle which gets populated based on the url query. For instance, if ?stelle=10 the field gets populated by the title of node with nid 10. If the query ?stelle is non-existant or followed by a nid which does not exist (is not of a certain content type) or does not contain a certain string the form will be redirecting to mynode?stelle=initiativ. The form has 2 fields to upload files via ajax, works good so far. Here is my code:
<?php
/**
* Altering the form! this will add class to the file upload/ remove buttons
*/
function mymodule_form_alter(&$form, &$form_state, $form_id) {
$conf = mymodule_defaults();
if ($form_id == 'webform_client_form_' . $conf['nid']) {
if (isset($form['submitted']['field1'])) {
$form['submitted']['field1']['#process'] = array('mymodule_my_file_element_process');
}
if (isset($form['submitted']['field2'])) {
$form['submitted']['field2']['#process'] = array('mymodule_my_file_element_process');
}
$nid = $form['#node']->nid;
$form['actions']['submit']['#ajax'] = array(
'callback' => 'mymodule_webform_js_submit',
'wrapper' => 'webform-client-form-' . $nid,
'method' => 'replace',
'effect' => 'fade',
);
$redirect_form = false;
$maintenance = false;
if (isset($form['submitted']['stelle']['#default_value']) && $form['submitted']['stelle']['#default_value'] !== '') {
$hide_components = array(
'einleitung_standard',
'einleitung_initiativ',
);
$unhide_components = array();
if ($form['submitted']['stelle']['#default_value'] == '') {
$redirect_form = true;
}
elseif (is_numeric($form['submitted']['stelle']['#default_value'])) {
$nid = $form['submitted']['stelle']['#default_value'];
$node = node_load($nid);
if ($node === false || (isset($node->type) && $node->type !== 'job')) {
$redirect_form = true;
}
else {
$type = $node->type;
if ($type == 'job') {
$form['submitted']['stelle']['#default_value'] = $node->title;
$form['submitted']['stelle']['#attributes']['disabled'] = 'disabled';
$form['submitted']['related']['#value'] = $nid;
$unhide_components = array(
'einleitung_standard'
);
}
}
}
elseif ($form['submitted']['stelle']['#default_value'] == 'initiativ') {
// unset($form['submitted']['stelle']);
$form['submitted']['related']['#value'] = 'initiativ';
$unhide_components = array(
'einleitung_initiativ'
);
}
}
else {
// $redirect_form = true;
// this causes an error
}
This is the weird part:
$redirect_form = false;
$maintenance = false;
if (isset($form['submitted']['stelle']['#default_value']) && $form['submitted']['stelle']['#default_value'] !== '') {
...
else {
// $redirect_form = true;
// this causes an error
}
When I active the line to redirect the form when the if condition is false, the button to upload a file via ajax throws an error alert on click (see bottom for error). To me, this looks like the form alter hook is being called again when the file upload button is clicked without having my field stelle available - is that right? How to fix this?
And now the rest of the module, basically just alterings:
else {
// $redirect_form = true;
// this causes an error
}
foreach ($unhide_components as $key => $component) {
if (is_array($component)) {
foreach ($component as $_key => $_component) {
$index = array_search($_component, $hide_components[$key]);
if ($index !== false) {
unset($hide_components[$key][$index]);
}
}
}
else {
$index = array_search($component, $hide_components);
if ($index !== false) {
unset($hide_components[$index]);
}
}
}
// hide
foreach ($hide_components as $k=>$hc1){
if (is_array($hc1)) {
foreach ($hc1 as $hc2) unset($form['submitted'][$k][$hc2]);
} else {
unset($form['submitted'][$hc1]);
}
}
if ($redirect_form) drupal_goto('node/'.$conf['nid'], array('query'=>array('stelle'=>'initiativ')), 301);
}
}
function mymodule_my_file_element_process($element, &$form_state, $form) {
$element = file_managed_file_process($element, $form_state, $form);
$element['upload_button']['#attributes'] = array('class' => array('button'));
$prefix = '<label class="browse-slave">';
$prefix .= '<span class="button">' . t('Choose a file') . '</span>';
$element['upload']['#prefix'] = $prefix;
$element['upload_button']['#prefix'] = '</label>';
$element['remove_button']['#attributes'] = array('class' => array('button'));
$element['remove_button']['#prefix'] = '</label>';
return $element;
}
function mymodule_webform_js_submit($form, $form_state) {
// define the $sid variable (submission id from webform)
$sid = $form_state['values']['details']['sid'];
// if we have a sid then we know the form was properly submitted, otherwise, we'll just return the existing $form array
if ($sid) {
// first we have to load up the webform node object
$node = node_load($form_state['values']['details']['nid']);
// create an array up with the confirmation message, retreived from the webform node
$confirmation = array(
'#type' => 'markup',
'#markup' => check_markup($node->webform['confirmation'], $node->webform['confirmation_format'], '', TRUE),
);
// return the confirmation message
return $confirmation;
}
else {
// return the form
return $form;
}
}
The AJAX error is something like described here. Changing server/php settings didnt help it.
Thanks!
The form builder (and any hook alters) will be run when a form is validated, which happens on #ajax actions.
I like to throw static custom data in $form['#someProperty'] so that it's available in the build, validate, and submit functions. Something like this should help you:
function mymodule_form_alter(&$form, &$form_state, $form_id) {
// ...
if (isset($_GET['stelle'])) {
$form['#stelle'] = $_GET['stelle']; // This will always be there.
}
// ...
}
Another option would be to throw the $node that you load in the form, like $form['#stelle_node'] = node_load(...) and obviously only do that when the nid is actually available to you, so that you don't overwrite it with empty data when the form builder runs again in the future.
When i was working with ajax in drupal 6 the hash symbol in url or request caused an error everytime..... so i replaced url with this
data.url.replace(/%2523/, '%23');

Resources