rakit / validation Goto Github PK
View Code? Open in Web Editor NEWPHP Standalone Validation Library
License: MIT License
PHP Standalone Validation Library
License: MIT License
Hi,
I have a bunch of fields like this:
<input type="checkbox" name="Other[checked]" value="1">
<div>
<input type="text" name="Other[rows][0][name]">
<input type="text" name="Other[rows][0][cost]">
</div>
<div>
<input type="text" name="Other[rows][1][name]">
<input type="text" name="Other[rows][1][cost]">
</div>
…
All is fine with validator rules:
'Other.rows.*.*' => 'required_if:Other.checked,1',
'Other.rows.*.cost' => 'numeric'
But I'm stuck in aliasing names…
The one that works is $validation->setAlias("Other.rows.*.*", "Other / Item");
but it's too generic and does not distinguish between name
and cost
fields, neither different "rows".
Strangely, the following two rules do not work (I was supposing them to), because I get the original name (i.e. Other rows 1 name
):
$validation->setAlias("Other.rows.*.name", "Other / Item / Name");
$validation->setAlias("Other.rows.*.cost", "Other / Item / Cost");
The one that works is a loop like this, but this seems a little weird to me:
foreach ($_POST['Other']['rows'] as $key => $value) {
if ($value['name'] == '') {
$validation->setAlias("Other.rows.{$key}.name", "Other / Item {$key} / Name");
}
if ($value['cost'] == '') {
$validation->setAlias("Other.rows.{$key}.cost", "Other / Item {$key} / Cost");
}
}
I'm sure I'm missing something... Please, is there an easier way to achieve this?
Thanks
Some companies won't let you incorporate your code into their project without a license file explicitly stating what rights others have to use your work.
How do I set message for the field with following constraints: required|uploaded_file:0,500K,jpeg
I'd expect something like this:
$this->validator->setMessages(
[
'uploaded_file:max_size' => __( 'The :attribute file is too large, maximum size is :max_size', 'webpage' ),
]
);
I've noticed that the getValidData() returns new elements when using the dot-notation.
This is a snippet of my data
$data['logoImagePaths'] = [
'1x' => 'http://example.com/1x.png',
'2x' => 'http://example.com/2x.png',
];
Part of my rules:
'logoImagePaths' => 'required|array',
'logoImagePaths.1x' => 'required|url',
'logoImagePaths.2x' => 'required|url',
And this is that getValidData returns:
print_r($validation->getValidData());
[logoImagePaths] => Array
(
[1x] => http://example.com/1x.png
[2x] => http://example.com/2x.png
)
[logoImagePaths.1x] => http://example.com/1x.png
[logoImagePaths.2x] => http://example.com/2x.png
Is this expected? Or is it a bug?
A regex rule containing the pipe (|
) character such as...
url|regex:/^.*\.(jpg|JPG|gif|GIF|doc|DOC|pdf|PDF)$/
... breaks the Regex validator:
Fatal error: Uncaught Rakit\Validation\RuleNotFoundException: Validator 'JPG' is not registered in ..vendor/rakit/validation/src/Validator.php on line 103
I'm trying to validate the extension based on an existing file's url. It would be nice if there was a built in validator similar to mime
to achieve this for when we're handling file urls/paths in the input rather than as a $_FILES upload. Although the regex would suffice if this can be fixed!
Awesome library by the way :)
Hi!
I'm trying to validate a list of array items. The problem is that the error message does not contain the "offset" / "index" of the array element with the error. Example:
$validator = new Validator([
'users' => [
[
'username' => 'batman',
'email' => '[email protected]',
],
[
'username' => 'robin',
'email' => 'invalid-email.com' // <--- invalid email address
]
]
]);
$validator->rule('required', ['users.*.username', 'users.*.email'])
->rule('alpha', 'users.*.username')
->rule('email', 'users.*.email');
if ($validator->validate()) {
echo "Yay! We're all good!";
} else {
print_r($validator->errors());
}
Output:
Array
(
[users.*.email] => Array
(
[0] => Users.*.email is not a valid email address
)
)
Expected output:
Array
(
[users.*.email] => Array
(
[1] => users.[1].email is not a valid email address
)
)
Is it possible to add the array-offset to the validation result (index and message)?
i have a field called email that is an array with multiple emails,when i print the getValidData the result is:
Array
(
[email.0] => [email protected]
[email.1] => [email protected]
)
it's possible to only return the 'raw' array of the valid emails?
something like this:
[email] => Array
(
[0] => [email protected],
[1] => [email protected]
)
used this rule:
'email.*' => 'required|email'
Hi!
When I try
'document_snils.*' => 'required|uploaded_file:0,10M,pdf,jpeg,jpg',
, required flag works.
When I try
'document_snils.*' => 'required_if:type,entrepreneur|uploaded_file:0,10M,pdf,jpeg,jpg',
required_if flag does not work.
I am having an issue using the same rule.
My use case is I am matching password
and confirm_password
fields.
and the same rule always fails.
here's is the snippet I am using.
$password = $POST['password'];
$confirm_password = $POST['confirm_password'];
$myvalidator = $validator->make([
'password' => $password,
'confirm_password' => $confirm_password,
], [
'password' => 'required|min:6'
'confirm_password' => 'same:password',
]);
$myvalidator->setAliases([
'confirm_password' => 'Confirm Password',
]);
$myvalidator->validate();
if ($myvalidator->fails()) {
$errors = $myvalidator->errors();
$vars['errors'] = $errors->firstOfAll();
} else {
// DO Stuffs
}
This code bellow from documentation don't work:
$validation = $validator->validate($data, [
'enabled' => [
'required',
$validator('in', [true, 1])->strict()
]
]);
Because strict() method return void
Edit documentation like this:
/** @var In $boolValidator */
$boolValidator = $validator('in', [true, 1]);
$boolValidator->strict();
$validation = $validator->validate($data, [
'enabled' => [ 'required', $boolValidator]
]);
Or replace returned type by Validator.
Hi
I have this rule set:
'id' => 'required|integer|unique:accounts,id|min:1',
'company' => 'required|max:255',
'domains' => 'required|array',
'domains.*.domain' => 'required|regex:/\A[\w:.-]+\z/|unique:domains,domain',
'domains.*.sslify' => 'bool|default:1',
'domains.*.redirect' => 'bool|default:0',
'domains.*.redirect_code' => 'in:301,302|default:301',
'domains.*.origin' => 'required|url',
And this query:
{
"id": 1,
"company": "asd",
"domains": [
{
"domain": "www.example.com",
"ssl": "true",
"origin": "https://www.google.com"
}
]
}
Mind the "ssl" key. It was not described in rules.
Still, I get it from getValidatedData()
call:
Array
(
[id] => 1
[company] => asd
[domains] => Array
(
[0] => Array
(
[domain] => www.example.com
[ssl] => true
[origin] => https://www.google.com
[sslify] => 1
[redirect] => 0
[redirect_code] => 301
)
)
)
Version is 1.1.1, PHP 7.3.3.
P. S. Same happens with getValidData().
Is there a way to specify a custom function to use for validation? The use case I have in mind is validating foreign keys. This requires a DB lookup to see if the given value exists. Ideally, I would be able to supply a function that could do this.
theres is some rule/option to validate only if the data array are equal to the predefined rules index?
imagine this situation, this is a registration form, and validates the POST data:
$validation_rules = array(
'name' => 'required'
);
$_POST['name'] = 'John Doe';
$validator = new Validator();
$validation = $validator->make($_POST, $validation_rules);
$validation->validate();
if(!$validation->fails()) {
//OK
//create user
}
if the user sends some random field, like:
$_POST['cash'] = 9999;
the validation still passes and, if theres a field called "cash", it sets to 999, theres some option to $validation->lockEquals();
?
Hi i noticed you don't include min php version needed for some of your packages.
Please update your composer.json files.
here is my composer.json file
{ "name": "rakit/validation", "description": "PHP Laravel like standalone validation library", "license": "MIT", "authors": [{ "email": "[email protected]", "name": "Muhammad Syifa" }], "autoload": { "psr-4": { "Rakit\\Validation\\": "src" } }, "autoload-dev": { "psr-4": { "Rakit\\Validation\\Tests\\": ["tests", "tests/Fixtures"] } }, "require": { "php": ">=7.0", "ext-mbstring": "*", "rakit/validation": "^1.1" }, "require-dev": { "phpunit/phpunit": "^6.5", "squizlabs/php_codesniffer": "^3" }, "scripts": { "test": [ "phpunit", "phpcs" ] } }
after i run composer require rakit/validation
. the cmd returns:
does anyone have this problem?
The error attribute is set to ErrorBag in the Validation constructor but is never declared as a class property. This can cause modern IDEs and code quality tools to display a warning.
I'll submit a PR to fix these warnings.
I have input:
<input type="file" name="document[]">
I made validation:
'document.*' => 'required|uploaded_file:0,10M,pdf,jpeg,jpg',
But, its did't work. An empty field is validated. Please, help me.
Hi,
First of all, I really appreciate your work on rakit/validaiton.
I was trying my hands on with this lib, but not able to figure out.
When I'm printing
json_encode($errors->firstOfAll())
I'm getting
["The Email is not valid email","The Password minimum is 10"]
Here we have no way relate these messages to which data member and further error is related to which rule. Is it possible to get some thing like this:
email : ['require': 'email is required', 'email:'not a valid email']
It would be really helpful.
Cheers
Prashant
Hi @emsifa ,
is_uploaded_file
. This seems very much safer than the current implementation available.Plus there seem to be a bug here 😀 https://github.com/rakit/validation/blob/master/src/Validator.php#L26-#L28
Hello!
As a developer I would like to use attribute value in error message. On my opinion it's very usable for forms validation.
i'm new at using this library, and i am looking for an option that only validates if the field is not empty, if empty "remove" from valid data, its because i have an update user page, and the blank fields are not to update
I think it's an encoding problem with the chars counter.
When i set "min:6" and try to validate the value "мин", the validation fails.
Hi, is there any support for a field which can have both alphabetical and numerical data, with spaces?
Thanks
Hi,
I think there is a bug in required_without
, it does not seem to work as expected. Please consider the following code:
use Rakit\Validation\Validator;
$validator = new Validator;
$data = [
'name' => 'SomeName',
'email' => 'someemail@somedomain',
'surname' => 'Surname'
];
$validation = $validator->validate($data, [
'name' => 'required_without:surname',
'email' => 'required',
'surname' => 'required_without:name'
]);
if($validation->fails()) {
print_r($validation->errors());
} else {
echo "Passed!";
}
My understanding is that if surname
is presented then there should be an error.
What I want to achieve is that only name
or surname
should be presented in $data
.
The library is not validating zip files. Am I doing something wrong? Here is my code:
'zipfile' => 'required_if:media_type,Art Work,Manuals,Sell Sheets,Warnings,Warranties|uploaded_file:0,50M,zip,rar,7zip',
also tried
'zipfile' => 'required_if:media_type,Art Work,Manuals,Sell Sheets,Warnings,Warranties|uploaded_file:0,50M|mimes:zip',
also tried
'zipfile' => 'required_if:media_type,Art Work,Manuals,Sell Sheets,Warnings,Warranties|uploaded_file:0,50M,application/x-rar-compressed,application/octet-stream,application/zip,application/x-zip-compressed,multipart/x-zip',
Thanks
:attribute is not the actual attribute value, please man, why not?
why make it start with capital letter?
e.g. attribute name is
'nextPayDate'
you return 'NextPayDate' man why... please man
i'm seding a request with an array with numeric values and when i print the validData result, it returns the $_POST content and the "new" valid data, here's my request:
items[]: 5
items[]: 8
output ( getValidData() ):
Array
(
[items] => Array
(
[0] => 5
[1] => 8
)
[items.0] => 5
[items.1] => 8
)
Code:
$validator = new Validator;
$validation = $validator->validate($_POST, [
'items' => 'required|array',
'items.*' => 'required|numeric'
]);
if ($validation->fails()) {
$errors = $validation->errors();
echo "<pre>";
print_r($errors->firstOfAll());
echo "</pre>";
exit;
} else {
print_r($validation->getValidData());
}
Hey hey,
I noticed some problem while using regex that contains comma.
when you have rule like this: regex:/^([a-zA-Z\,]*)$/
Final regex will be /^([a-zA-Z\
And that will result in following warning: Warning: preg_match(): No ending delimiter '/' found in ../rakit/validation/src/Rules/Regex.php on line 18
That is main problem with parseRule method, that splits params no mater what.
instead:
protected function parseRule($rule)
{
$exp = explode(':', $rule, 2);
$rulename = $exp[0];
$params = isset($exp[1])? explode(',', $exp[1]) : [];
return [$rulename, $params];
}
should be something like this:
protected function parseRule($rule)
{
$exp = explode(':', $rule, 2);
$rulename = $exp[0];
if ($rulename !== 'regex') {
$params = isset($exp[1])? explode(',', $exp[1]) : [];
} else {
$params = [$exp[1]];
}
return [$rulename, $params];
}
Could you please add a .gitattributes
file that excludes the /tests
directory?
Thanks a lot.
Awesome library btw 😃
I'm trying to validate input number from GET parameter with this rule - integer|min:1|max:100
. The value itself is a string '200'
since it's coming from $_GET
. In this case all rules pass, but I was hoping max:100
would fail. Do you have a suggestion how to force min/max rules to treat value as a number?
Is there away of having something like
This elements needs to be set if the parent is set. So for example:
[
'order' => [
0 => [
"itemName" => 'shoe',
"itemPrice" => '20.00',
"quantity" => '1'
]
]
]
Basically want only to verify itemName, ItemPrice and quantity if order is set and is an array.
I would make my own rule but best to see if its there first than to reinvent the wheel! :)
For example:
$validation = $this->validator->validate([
'must_present_field' => '',
], [
'must_present_field' => 'present|array',
]);
is passing the validation, whereas it should not.
One option to fix this issue is to set the present rule as required. I'll provide a PR using this.
Is there a possibility to translate attribute names. You can set custom messages, but the attribute which is used won't be translated.
Something like this: https://stackoverflow.com/a/35629920
There's no nullable
validator like in laravel. It allows to skip validations if user doesnt send the value
You hardcoding "new Rule", "new Validator" statements and dont use dependency injector (as i see you prefer extends
instead of decorator injection), so if i want to change default settings of all validators - i should copy and extend all the rules tree. Now i have 30 your validators, and 52 mine. I do nice work to prepare "complete solution" for my project
You forget method "setImplicit" in Rule, so if i want to change default implicit statement - i need to extend Rule class, but it is hardcoded in Validator and Validation, so i need to extend these ones too, and half-code will be copied in my local project folder
You hardcoded typehint return checkers for getMessage and so on statement to return string
. So now you need to define message for each validator. Allowing null opens for you feature to add nullable
validator that fails, but do not create any errors. But as i said, you hardcode it, and i need to rewrite and copy a lot of classes to solve it.
Validators should be able to made nullable by default like implicit
. If value isnt set - we just stops validation process like implicit
is set but without any errors. Its because set nullable near every damn attribute even when project has 20 DB tables - its really boring. 400 properties with its combinations and even should be marked nullable
, so Rule can be nullable
too
Registering new validators using new
statement it is spending non-cheap kilobytes of memory to store the objects. Its normal for frontend where i have access for users 32Gibs of memory, but when i have 128Gibs on my server and 10000 clients - i have only damn 12.8 mb for each one (and yes, its without relational DB that requires 60% of available memory). So i recommend to improve adding registering validators by classname and then create it when validators is needed to use.
The problem of extends
is the PHP interpreter not allows you to control new
statement and typehints. You prevent other developers from improving their own features. Would be great to composer will be dependencyInjector
+ eventDispatcher
too (because it knows where exactly positioned the files and also he works with class loading. Simple config allow you to make any function as dependency injector, and second config can maybe even allow to decorate any injected class with magic __call() method that raises outer event), but PHP devs prefer crying one-to-one instead of productive talk.
So in laravel i saw temporary solution that makes easier extending hardcoded values. See Illuminate\Database\Eloquent\Model file. There you can see methods like "newModelInstance" or "newBaseBuilder" - its about replacing hardcoded values.
All get{.*}
statements should allow null statement to be returned. Exclusion of this rule - the state-machines: example
Class A
{
protected $prop; // null, because requires logic
public function prop() // : mixed
{
// some logic here
return 'some';
}
public function getProp() : string
{
if (isset($this->prop)) return $this->prop;
$prop = $this->prop();
// some mappers here
return $this->prop = $prop;
}
}
There you able to define my own getter and next you define "class getter" that includes checking the property is bound. There is NO SOLID of course (yep, no Barbara tits here), juniors/middles can start to CRY right now. But it helps to updating your code later without the pain.
I'd like to talk more and wrote message to your email but you prefer silence. Good for now.
$data = [
"a"=>true,
"b"=>[
"b1"=>true
]
];
$validation = $validator->make($data, [
'a' => 'required',
'b.test' => 'accepted',
]);
got error:
The b.test must be accepted!
should be passed?
in SizeTrait.php
在用min验证规则时候出现错误。
从表单获取的值数字是字符串类型的,仅仅通过 is_int($value) || is_float($value) 来判断不正确。
希望加上 is_int($value) || is_float($value) || is_numeric($value)
In the readme
file, it says "Register/Modify Rule" but here( https://github.com/rakit/validation/blob/master/src/Validator.php#L109-#L113 ) it is explicitly set not to allow rule modification.
The question is do you really want rule modification ? If yes, i should be able to send a PR.
I tried to change the error message.
$validator->setMessages([
"required", ":attribute is empty",
"password:min", ":attribute characters should not less than 6"
]);
$validation = $validator->validate($request->post("all"), [
"username" => "required",
"password" => "required|min:6"
]
);
but the output is like this.
object(Rakit\Validation\ErrorBag)#678 (1) { ["messages":protected]=> array(2) {
["username"]=> array(1) { ["required"]=> string(24) "The Username is required" }
["password"]=> array(1) { ["min"]=> string(25) "The Password minimum is 6" } }
}
Some of the default validation error messages could do with some changes so that they read a bit better.
For example, the same:
rule error message is "The :attribute must be same with :field", and should instead read "The :attribute must be same as :field".
I'd also like to suggest removing the leading "The" from all default messages. In a lot of scenarios it doesn't read well, and omitting it makes more sense.
(I'll submit a PR to fix both of these if you're receptive to the changes).
The default message is as follows:
protected $message = "The :attribute only allows a-z, 0-8, _ and -";
Surely this should be "The :attribute only allows a-z, 0-9, _ and -"
I tried this expression: required|regex:/^\d$|^(?:\d+\,?)+\d+$/
, and catch the error with message "Uncaught exception: 'Rakit\Validation\RuleNotFoundException" with message 'Validator '^(?' is not registered". The symbol | don't work in an expression.
Beforehand, I want to say thank you for your contributions and inputs so far 🙇♂️
I wanna make some major changes to this package based on previous issues and my experience.
But actually, I've rarely used PHP lately, especially this package.
And because it would be a v1
(stable release), I want to implement best practices to our codes.
So I need your inputs and suggestions to do this.
So far, this is my to-do lists for v1
:
ErrorBag::firstOrAll
to return array assoc instead of indexed array. #64uploaded_file
rule to uploaded_filesize
and uploaded_filetype
so we get separate error messagemimes
to validate uploaded file mimes, and update min
, max
, and between
rules to be able to validate uploaded file size. #69And as I'm not fluent in English. Any misspelled correction in the documentation would be appreciated.
I have created branch v1
for this release. So we can make some PR to that branch. And start from now, only bugfixes are allowed to merged to master. Any other minor changes would be merged to v1. I will merge v1
to master
after we have done those to-do lists.
Thank you.
I have a use case where I have two checkbox fields, either of which when checked requires an email address field to be populated.
$validation = $validator->validate($_POST, [
'email' => [
'required_with:emailme',
'required_with:newsletter',
'email'
],
'emailme' => '',
'newsletter' => ''
]);
$validation = $validator->validate($_POST, [
'email' => 'required_with:emailme|required_with:newsletter|email',
'emailme' => '',
'newsletter' => ''
]);
Neither of these above examples work correctly. When the emailme checkbox is 'on' and the newsletter checkbox isn't, it doesn't require the email like I think it should. Other combinations are ok, so it appears that the first required_with is getting ignored.
Is it not possible to use required_with more than once for a field?
Hi, there. Thanks for sharing with us this amazing class!
Well, my validation code is working pretty well but I didn't understand how to custom validation messages. I want to do that cause I need generate messages into brazilian portuguese.
See the below code:
$validation = $validator->make($_POST, [
'name' => 'required|min:3',
'age' => 'required|numeric'
]);
How do I custom messages to those fields using rakit class?
Thanks in advance.
Hello, and first thanks for this great package!
I have an array like this:
[
'products' => [
'10' => [
'quantity' => 8
'has_notes' => 1
'notes' => ''
],
'12' => [
'quantity' => 0
'notes' => ''
],
'14' => [
'quantity' => 0
'notes' => ''
],
]
]
Basically I'd like that, for each array item, the field 'notes'
is required if corresponding 'has_notes'
field is present and it's 1 (it's a checkbox, so some items do not have this)
I tried with the following rule, but with no luck:
'products' => 'array',
'products.*.notes' => 'required_if:products.*.has_notes,1',
Is there a way to do this or do I have to create a custom rule?
Thanks :-)
Case:
In the incoming request application receives the json array like this:
["5662", "4c56ea8b-024f-3208-8f35-f998cc620f7e", 1, null]
It should be validated. How example, any of array value must be integer
. But if u use *
star match criteria, validating library will skip this input.
How to reproduce?
$body = ["5662", "4c56ea8b-024f-3208-8f35-f998cc620f7e", 1, null];
$validation = $validator->validate($body, [
'*' => 'required|integer',
]);
if ($validation->fails()) {
// no.
}
I think *
star criteria functionality must be extended for such cases.
What do you think about it?
Hi team,
Your work is really great but may you guide me that, is it possible or not to set error message like this.
$validation_a = $validator->validate($dataset_a, $rules_for_dataset_a, [
'["inputName"]required' => 'custom message for required but only for that input',
'["inputName"]string' => 'only string allowed',
'["inputName"]max=10' => 'string len should be maximum 10',
'email' => ':email tidak valid',
// etc
]);
See now these day requirement is very vast. you can not set generic required message for all 100 field. Let's say I have very very long form and most of the field need to be required but the required message also should be very customized.
Consider this scenario.
you have name [string ]field and your zone [number].
Here requirement is that both are the mandatory field but if zone have no value then you need to enter 0 for skip. So here what i will error show that,
"Zone id is missing, Please enter 0 if you don't have zone id".
FILTER_VALIDATE_URL
is a minimal validation filter, as documented in the PHP docs:
[
FILTER_VALIDATE_URL
] Validates value as URL (according to » http://www.faqs.org/rfcs/rfc2396), optionally with required components. Beware a valid URL may not specify the HTTP protocol http:// so further validation may be required to determine the URL uses an expected protocol, e.g. ssh:// or mailto:. Note that the function will only find ASCII URLs to be valid; internationalized domain names (containing non-ASCII characters) will fail.
@sauce
At a minimum, I think a secondary validation should be made to detect the presense of a URL protocol:
<?php
// update to the /src/Rules/Url.php file
public function check($value)
{
return filter_var($value, FILTER_VALIDATE_URL) !== false &&
preg_match('/^[\w]{2,6}:\/\//', $value);
}
I may look into issuing a PR later this evening/week when I can get to it but I've already tested and validated the REGEX provided works just fine.
For example, when using the same:
rule, the message is "The :attribute must be same with :field"
, which gives us:
The New Password (again) must be same with new_password
Ideally the attribute alias should be used on the new_password
field too. The field name often means nothing to the end user especially if they're not readable. So we want this...
The New Password (again) must be same with New Password
If you don't have time to look into this, could you give me a heads up on where the message aliases are filled and i'll work on a PR?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.