I have the following php code using the codeigniter framework
$this->form_validation->set_rules('money', 'Money', 'integer|required|xss_clean');
It validates a money field as an integer. How can i validate the field as an integer OR a decimal number.
I guessed it would be something simple like
$this->form_validation->set_rules('money', 'Money', '(decimal||integer)|required|xss_clean');
but it doesnt work!
From the CI Form Validation docs:
Note: You can also use any native PHP functions that permit one parameter.
is_numeric() could work for you, but it accepts some formats that are very unlike money.
is_float() would work, except it will fail on strings and integers.
Both these functions are also too lenient in validating a numeric integer or decimal that you would normally accept as a money value. The built in CI decimal() function requires the decimal point and allows + and - characters.
Yeah, I know - not helpful, but hopefully it gets you thinking. The syntax you would like to use will simply not work. I'd suggest creating your own form validation rule for validating money by extending the Form_validation library.
Create the file /application/libraries/MY_Form_validation.php
Something like this:
class MY_Form_validation extends CI_Form_validation {
function is_money($input = '')
{
// Validate input here and return TRUE or FALSE
}
}
I had written a broken example initially, then I tried writing something that would work and realized that it's up to you. You may or may not want to allow characters like $, €, -, +, or decimals beyond two places, or a decimal with only one place, or commas in the digit to separate thousands... Use whatever validation method you see fit.
There's a good example here on money format validation: How to check if an entered value is currency
use numeric directly .... numeric|required
This is what I use in MY_Form_validation class.
/**
* Money, decimal or integer
*
* #access public
* #param string
* #return bool
*/
public function money($str)
{
//First check if decimal
if(!parent::decimal($str))
{
//Now check if integer
return (bool) parent::integer($str);
}
return TRUE;
}
And of course in your /system/language/english/form_validation_lang.php you should add appropriate message for validation error.
You could try a custom callback :
$this->form_validation->set_rules('money', 'Money', 'callback_money_type');
function money ($param) {
//conditional statements here
if(is_int($param) || is_float($param){
$this->form_validation->set_message('money_type', 'Your message here');
return false;
} else {
return true;
}
}
ctype_digit may be of use, it's a built-in PHP function.
Instead of using decimal||integer now we can use numeric to validate the numeric characters.
You can use like below
$this->form_validation->set_rules('reward', 'Reward', 'callback_validate_money');
public function validate_money ($input) {
if(preg_match('/^[0-9]*\.?[0-9]+$/', $input)){
return true;
} else {
$this->form_validation->set_message('validate_money','Please enter valid reward!');
return false;
}
}
Related
useful for say, laravel components, where often text can be handed by mistake e.g.
<x-mything render="false"/>
this will be string "false" and
if("false"){
// is truthy
}
the php way to handle this is here
https://stackoverflow.com/a/15075609/533426
is there a laravel way to do it?
the answer:
do
<x-mything :render="false"/>
is not the answer I'm looking for. I'm looking for a laravel way to cast string to boolean like in the linked post
if(!filter_var($render, FILTER_VALIDATE_BOOLEAN)) {
// is falsy
}
Encapsulate this in a string macro. In the AppServiceProvider boot method add;
use Illuminate\Support\Str;
public function boot()
{
Str::macro('isFalsy', function ($str) {
return !filter_var($str, FILTER_VALIDATE_BOOLEAN);
});
}
now in code Str::isFalsy($render) or in Laravel 9 str($render)->isFalsy()
or swap the logic and create an isTruthy() macro
I recently met an issue with validator (illuminate/validation) under Lumen (5.4.6) (Laravel Components 5.4.*). It seems like the integer rule doesn't work.
I used Paw(or postman) to send companyName with type string and it can pass the validation and 'here i am' can printed out. Even a boolean type, let's say (boolean)companyName=TRUE can pass the validation. Have you met the same issue? this bug is quite obvious but I didn't find the similar discussion on google.
I also tested the string rule 'required|string|min:1' and it works accordingly, neither integer nor boolean parameters can pass the validation.
code screen-shot
Laravel/Lumen makes use of PHP filter_var() function for integer rule validation:
Class Illuminate\Validation\Concerns\ValidatesAttributes:
protected function validateInteger($attribute, $value)
{
return filter_var($value, FILTER_VALIDATE_INT) !== false;
}
As mentioned in the docs:
Note that scalar values are converted to string internally before they are filtered.
So boolean true is converted to string 1 internally and therefore passes validation.
It's not considered a bug, but an implementation detail.
Lets say in my lang/en/general.php there are multiple translation lines for example:
"token" => "This password reset token is invalid.",
"sent" => "Password reminder sent!",
"reset" => "Password has been reset!",
But in my lang/de/general.php these lines are missing.
So later, when I use the Lang::get('general.token') or simply trans('general.token')
The english version will return
This password reset token is invalid.
And the german (de) version will return
general.token
Is there any way I can handle a 'translation not found' function, like a filter but not creating a special class for it? For example, when a line has no translation, I want to throw an Exception.
Thanks in advance!
In Laravel 4 only, you can use Lang::has() as below, here is the doc
if (\Lang::has('general.token')) {
// line exists.
} else {
// line not exist.
}
In current Laravel versions you can just use trans helper like so:
#if (trans()->has('general.token'))
{{ trans('general.token') }}
#endif
This question is getting a little bit old but as per version 5.8 you can simply check as this :
array_key_exists('your-word-key', trans('your-file'))
or
array_key_exists('your-word-key', trans('your-file.array_key'))
for nested translations
You might want to write a helper similar to the one below to help with fallbacks:
/**
* Makes translation fall back to specified value if definition does not exist
*
* #param string $key
* #param null|string $fallback
* #param null|string $locale
* #param array|null $replace
*
* #return array|\Illuminate\Contracts\Translation\Translator|null|string
*/
function trans_fb(string $key, ?string $fallback = null, ?string $locale = null, ?array $replace = [])
{
if (\Illuminate\Support\Facades\Lang::has($key, $locale)) {
return trans($key, $replace, $locale);
}
return $fallback;
}
Note: The helper only works on PHP 7.1 (which has support nullable types). Adjust it to your PHP version if it's lower than 7.1.
You can create your own TranslationServiceProvider and Translator and override the get() method in translator to throw an exception when the parent::get() returns a translation string that is equal to the translation key that was passed in. Both #lang() and trans() functions call the get() method of the translator.
Seems like a whole lot of trouble only to get another reason for a "Whoops! something went wrong!" on your site. You will only get the exception when the translation is encountered.
Another solution: you can use the barryvdh/laravel-translation-manager package, it has a translation service provider that logs missing translation keys and a web interface for managing translations. It will log missing translation keys per locale and let you edit them through a web interface.
It is simple to setup and easy to modify. So you can replace the logging with throwing an exception.
I'm using 2.4.7 and I want to include some validation for two fields which take in prices (e.g. €1 or 2 for €3). Originally I thought that perhaps I would need to resort to validating user input but as the answer suggests it was a database issue.
The encoding within SilverStripe was defaulting to ASCII which converted the symbols such as the euro symbol. In the end I need to add
$this->response->addHeader("Content-Type", "application/json; charset='utf-8'");
to the init method in the controller. This corrected the encoding issue and prevented a hacky workaround taking place. Many thanks for the insight on this one.
Thanks
I'm assuming you want to do this in the CMS. If that's the case, the easiest way is probably to create a new class which extends the TextField class and adds a public function validate() method which performs your validation (see the CreditCardField class for an example).
class FancyCurrencyField extends TextField {
public function validate($validator) {
// Do your validation
if ($invalid) {
$validator->validationError(
$this->name,
"Please don't use currency symbols.",
"validation",
false
);
return false;
}
return true;
}
}
Once you've created your class, you can modify the form fields in your getCMSFields() function on the DataObject and use the new class in place of TextField.
Having said that, it feels like output encoding and not input validation is the root cause of your problem. I'd check to make sure that everything is setup to use UTF-8.
I encountered a problem with the PHP function substr. I just used mb_substr instead and it solved my issue.
Please view http://www.silverstripe.org/general-questions/show/11797#post369831
I would like to override the standard URL validation rule to make it more tolerant of a whitespace character before or after the URL. Basically use the trim() function on the url before passing it to the standard URL validation handler.
I know I need to override that rule but I'm not exactly where and how I need to do it.
(Plus, the CakePHP API and book documentation are currently offline. Upgrades, I know...)
You can add custom validation rules in your Model classes, your Behavior classes, or in the AppModel class:
http://book.cakephp.org/view/150/Custom-Validation-Rules#Adding-your-own-Validation-Methods-152
Since you want to override an existing method, just give it the same name and signature as the original. Something like this might do the trick:
function url($check, $strict = false) {
return Validation::url(trim($check), $strict);
}
Why would you wanna do that?
Simply make sure all posted data is always trimmed.
Thats cleaner and more secure, anyway.
I have a component doing that in beforeFilter:
/** DATA PREPARATION **/
if (!empty($controller->data) && !Configure::read('DataPreparation.notrim')) {
$controller->data = $this->trimDeep($controller->data);
}
The trimDeep method:
/**
* #static
*/
function trimDeep($value) {
$value = is_array($value) ? array_map(array(&$this, 'trimDeep'), $value) : trim($value);
return $value;
}