Giter Club home page Giter Club logo

validation's Introduction

Rakit Validation - PHP Standalone Validation Library

Build Status Coverage Status License

PHP Standalone library for validating data. Inspired by Illuminate\Validation Laravel.

Features

  • API like Laravel validation.
  • Array validation.
  • $_FILES validation with multiple file support.
  • Custom attribute aliases.
  • Custom validation messages.
  • Custom rule.

Requirements

  • PHP 7.0 or higher
  • Composer for installation

Quick Start

Installation

composer require "rakit/validation"

Usage

There are two ways to validating data with this library. Using make to make validation object, then validate it using validate. Or just use validate. Examples:

Using make:

<?php

require('vendor/autoload.php');

use Rakit\Validation\Validator;

$validator = new Validator;

// make it
$validation = $validator->make($_POST + $_FILES, [
    'name'                  => 'required',
    'email'                 => 'required|email',
    'password'              => 'required|min:6',
    'confirm_password'      => 'required|same:password',
    'avatar'                => 'required|uploaded_file:0,500K,png,jpeg',
    'skills'                => 'array',
    'skills.*.id'           => 'required|numeric',
    'skills.*.percentage'   => 'required|numeric'
]);

// then validate
$validation->validate();

if ($validation->fails()) {
    // handling errors
    $errors = $validation->errors();
    echo "<pre>";
    print_r($errors->firstOfAll());
    echo "</pre>";
    exit;
} else {
    // validation passes
    echo "Success!";
}

or just validate it:

<?php

require('vendor/autoload.php');

use Rakit\Validation\Validator;

$validator = new Validator;

$validation = $validator->validate($_POST + $_FILES, [
    'name'                  => 'required',
    'email'                 => 'required|email',
    'password'              => 'required|min:6',
    'confirm_password'      => 'required|same:password',
    'avatar'                => 'required|uploaded_file:0,500K,png,jpeg',
    'skills'                => 'array',
    'skills.*.id'           => 'required|numeric',
    'skills.*.percentage'   => 'required|numeric'
]);

if ($validation->fails()) {
	// handling errors
	$errors = $validation->errors();
	echo "<pre>";
	print_r($errors->firstOfAll());
	echo "</pre>";
	exit;
} else {
	// validation passes
	echo "Success!";
}

In this case, 2 examples above will output the same results.

But with make you can setup something like custom invalid message, custom attribute alias, etc before validation running.

Attribute Alias

By default we will transform your attribute into more readable text. For example confirm_password will be displayed as Confirm password. But you can set it anything you want with setAlias or setAliases method.

Example:

$validator = new Validator;

// To set attribute alias, you should use `make` instead `validate`.
$validation->make([
	'province_id' => $_POST['province_id'],
	'district_id' => $_POST['district_id']
], [
	'province_id' => 'required|numeric',
	'district_id' => 'required|numeric'
]);

// now you can set aliases using this way:
$validation->setAlias('province_id', 'Province');
$validation->setAlias('district_id', 'District');

// or this way:
$validation->setAliases([
	'province_id' => 'Province',
	'district_id' => 'District'
]);

// then validate it
$validation->validate();

Now if province_id value is empty, error message would be 'Province is required'.

Custom Validation Message

Before register/set custom messages, here are some variables you can use in your custom messages:

  • :attribute: will replaced into attribute alias.
  • :value: will replaced into stringify value of attribute. For array and object will replaced to json.

And also there are several message variables depends on their rules.

Here are some ways to register/set your custom message(s):

Custom Messages for Validator

With this way, anytime you make validation using make or validate it will set your custom messages for it. It is useful for localization.

To do this, you can set custom messages as first argument constructor like this:

$validator = new Validator([
	'required' => ':attribute harus diisi',
	'email' => ':email tidak valid',
	// etc
]);

// then validation belows will use those custom messages
$validation_a = $validator->validate($dataset_a, $rules_for_a);
$validation_b = $validator->validate($dataset_b, $rules_for_b);

Or using setMessages method like this:

$validator = new Validator;
$validator->setMessages([
	'required' => ':attribute harus diisi',
	'email' => ':email tidak valid',
	// etc
]);

// now validation belows will use those custom messages
$validation_a = $validator->validate($dataset_a, $rules_for_dataset_a);
$validation_b = $validator->validate($dataset_b, $rules_for_dataset_b);

Custom Messages for Validation

Sometimes you may want to set custom messages for specific validation. To do this you can set your custom messages as 3rd argument of $validator->make or $validator->validate like this:

$validator = new Validator;

$validation_a = $validator->validate($dataset_a, $rules_for_dataset_a, [
	'required' => ':attribute harus diisi',
	'email' => ':email tidak valid',
	// etc
]);

Or you can use $validation->setMessages like this:

$validator = new Validator;

$validation_a = $validator->make($dataset_a, $rules_for_dataset_a);
$validation_a->setMessages([
	'required' => ':attribute harus diisi',
	'email' => ':email tidak valid',
	// etc
]);

...

$validation_a->validate();

Custom Message for Specific Attribute Rule

Sometimes you may want to set custom message for specific rule attribute. To do this you can use : as message separator or using chaining methods.

Examples:

$validator = new Validator;

$validation_a = $validator->make($dataset_a, [
	'age' => 'required|min:18'
]);

$validation_a->setMessages([
	'age:min' => '18+ only',
]);

$validation_a->validate();

Or using chaining methods:

$validator = new Validator;

$validation_a = $validator->make($dataset_a, [
	'photo' => [
		'required',
		$validator('uploaded_file')->fileTypes('jpeg|png')->message('Photo must be jpeg/png image')
	]
]);

$validation_a->validate();

Translation

Translation is different with custom messages. Translation may needed when you use custom message for rule in, not_in, mimes, and uploaded_file.

For example if you use rule in:1,2,3 we will set invalid message like "The Attribute only allows '1', '2', or '3'" where part "'1', '2', or '3'" is comes from ":allowed_values" tag. So if you have custom Indonesian message ":attribute hanya memperbolehkan :allowed_values", we will set invalid message like "Attribute hanya memperbolehkan '1', '2', or '3'" which is the "or" word is not part of Indonesian language.

So, to solve this problem, we can use translation like this:

// Set translation for words 'and' and 'or'.
$validator->setTranslations([
    'and' => 'dan',
    'or' => 'atau'
]);

// Set custom message for 'in' rule
$validator->setMessage('in', ":attribute hanya memperbolehkan :allowed_values");

// Validate
$validation = $validator->validate($inputs, [
    'nomor' => 'in:1,2,3'
]);

$message = $validation->errors()->first('nomor'); // "Nomor hanya memperbolehkan '1', '2', atau '3'"

Actually, our built-in rules only use words 'and' and 'or' that you may need to translates.

Working with Error Message

Errors messages are collected in Rakit\Validation\ErrorBag object that you can get it using errors() method.

$validation = $validator->validate($inputs, $rules);

$errors = $validation->errors(); // << ErrorBag

Now you can use methods below to retrieves errors messages:

all(string $format = ':message')

Get all messages as flatten array.

Examples:

$messages = $errors->all();
// [
//     'Email is not valid email',
//     'Password minimum 6 character',
//     'Password must contains capital letters'
// ]

$messages = $errors->all('<li>:message</li>');
// [
//     '<li>Email is not valid email</li>',
//     '<li>Password minimum 6 character</li>',
//     '<li>Password must contains capital letters</li>'
// ]

firstOfAll(string $format = ':message', bool $dotNotation = false)

Get only first message from all existing keys.

Examples:

$messages = $errors->firstOfAll();
// [
//     'email' => Email is not valid email',
//     'password' => 'Password minimum 6 character',
// ]

$messages = $errors->firstOfAll('<li>:message</li>');
// [
//     'email' => '<li>Email is not valid email</li>',
//     'password' => '<li>Password minimum 6 character</li>',
// ]

Argument $dotNotation is for array validation. If it is false it will return original array structure, if it true it will return flatten array with dot notation keys.

For example:

$messages = $errors->firstOfAll(':message', false);
// [
//     'contacts' => [
//          1 => [
//              'email' => 'Email is not valid email',
//              'phone' => 'Phone is not valid phone number'
//          ],
//     ],
// ]

$messages = $errors->firstOfAll(':message', true);
// [
//     'contacts.1.email' => 'Email is not valid email',
//     'contacts.1.phone' => 'Email is not valid phone number',
// ]

first(string $key)

Get first message from given key. It will return string if key has any error message, or null if key has no errors.

For example:

if ($emailError = $errors->first('email')) {
    echo $emailError;
}

toArray()

Get all messages grouped by it's keys.

For example:

$messages = $errors->toArray();
// [
//     'email' => [
//         'Email is not valid email'
//     ],
//     'password' => [
//         'Password minimum 6 character',
//         'Password must contains capital letters'
//     ]
// ]

count()

Get count messages.

has(string $key)

Check if given key has an error. It returns bool if a key has an error, and otherwise.

Getting Validated, Valid, and Invalid Data

For example you have validation like this:

$validation = $validator->validate([
    'title' => 'Lorem Ipsum',
    'body' => 'Lorem ipsum dolor sit amet ...',
    'published' => null,
    'something' => '-invalid-'
], [
    'title' => 'required',
    'body' => 'required',
    'published' => 'default:1|required|in:0,1',
    'something' => 'required|numeric'
]);

You can get validated data, valid data, or invalid data using methods in example below:

$validatedData = $validation->getValidatedData();
// [
//     'title' => 'Lorem Ipsum',
//     'body' => 'Lorem ipsum dolor sit amet ...',
//     'published' => '1' // notice this
//     'something' => '-invalid-'
// ]

$validData = $validation->getValidData();
// [
//     'title' => 'Lorem Ipsum',
//     'body' => 'Lorem ipsum dolor sit amet ...',
//     'published' => '1'
// ]

$invalidData = $validation->getInvalidData();
// [
//     'something' => '-invalid-'
// ]

Available Rules

Click to show details.

required

The field under this validation must be present and not 'empty'.

Here are some examples:

Value Valid
'something' true
'0' true
0 true
[0] true
[null] true
null false
[] false
'' false

For uploaded file, $_FILES['key']['error'] must not UPLOAD_ERR_NO_FILE.

required_if:another_field,value_1,value_2,...

The field under this rule must be present and not empty if the anotherfield field is equal to any value.

For example required_if:something,1,yes,on will be required if something value is one of 1, '1', 'yes', or 'on'.

required_unless:another_field,value_1,value_2,...

The field under validation must be present and not empty unless the anotherfield field is equal to any value.

required_with:field_1,field_2,...

The field under validation must be present and not empty only if any of the other specified fields are present.

required_without:field_1,field_2,...

The field under validation must be present and not empty only when any of the other specified fields are not present.

required_with_all:field_1,field_2,...

The field under validation must be present and not empty only if all of the other specified fields are present.

required_without_all:field_1,field_2,...

The field under validation must be present and not empty only when all of the other specified fields are not present.

uploaded_file:min_size,max_size,extension_a,extension_b,...

This rule will validate data from $_FILES. Field under this rule must be follows rules below to be valid:

  • $_FILES['key']['error'] must be UPLOAD_ERR_OK or UPLOAD_ERR_NO_FILE. For UPLOAD_ERR_NO_FILE you can validate it with required rule.
  • If min size is given, uploaded file size MUST NOT be lower than min size.
  • If max size is given, uploaded file size MUST NOT be higher than max size.
  • If file types is given, mime type must be one of those given types.

Here are some example definitions and explanations:

  • uploaded_file: uploaded file is optional. When it is not empty, it must be ERR_UPLOAD_OK.
  • required|uploaded_file: uploaded file is required, and it must be ERR_UPLOAD_OK.
  • uploaded_file:0,1M: uploaded file size must be between 0 - 1 MB, but uploaded file is optional.
  • required|uploaded_file:0,1M,png,jpeg: uploaded file size must be between 0 - 1MB and mime types must be image/jpeg or image/png.

Optionally, if you want to have separate error message between size and type validation. You can use mimes rule to validate file types, and min, max, or between to validate it's size.

For multiple file upload, PHP will give you undesirable array $_FILES structure (here is the topic). So we make uploaded_file rule to automatically resolve your $_FILES value to be well-organized array structure. That means, you cannot only use min, max, between, or mimes rules to validate multiple file upload. You should put uploaded_file just to resolve it's value and make sure that value is correct uploaded file value.

For example if you have input files like this:

<input type="file" name="photos[]"/>
<input type="file" name="photos[]"/>
<input type="file" name="photos[]"/>

You can simply validate it like this:

$validation = $validator->validate($_FILES, [
    'photos.*' => 'uploaded_file:0,2M,jpeg,png'
]);

// or

$validation = $validator->validate($_FILES, [
    'photos.*' => 'uploaded_file|max:2M|mimes:jpeg,png'
]);

Or if you have input files like this:

<input type="file" name="images[profile]"/>
<input type="file" name="images[cover]"/>

You can validate it like this:

$validation = $validator->validate($_FILES, [
    'images.*' => 'uploaded_file|max:2M|mimes:jpeg,png',
]);

// or

$validation = $validator->validate($_FILES, [
    'images.profile' => 'uploaded_file|max:2M|mimes:jpeg,png',
    'images.cover' => 'uploaded_file|max:5M|mimes:jpeg,png',
]);

Now when you use getValidData() or getInvalidData() you will get well array structure just like single file upload.

mimes:extension_a,extension_b,...

The $_FILES item under validation must have a MIME type corresponding to one of the listed extensions.

default/defaults

This is special rule that doesn't validate anything. It just set default value to your attribute if that attribute is empty or not present.

For example if you have validation like this

$validation = $validator->validate([
    'enabled' => null
], [
    'enabled' => 'default:1|required|in:0,1'
    'published' => 'default:0|required|in:0,1'
]);

$validation->passes(); // true

// Get the valid/default data
$valid_data = $validation->getValidData();

$enabled = $valid_data['enabled'];
$published = $valid_data['published'];

Validation passes because we sets default value for enabled and published to 1 and 0 which is valid. Then we can get the valid/default data.

email

The field under this validation must be valid email address.

uppercase

The field under this validation must be valid uppercase.

lowercase

The field under this validation must be valid lowercase.

json

The field under this validation must be valid JSON string.

alpha

The field under this rule must be entirely alphabetic characters.

numeric

The field under this rule must be numeric.

alpha_num

The field under this rule must be entirely alpha-numeric characters.

alpha_dash

The field under this rule may have alpha-numeric characters, as well as dashes and underscores.

alpha_spaces

The field under this rule may have alpha characters, as well as spaces.

in:value_1,value_2,...

The field under this rule must be included in the given list of values.

This rule is using in_array to check the value. By default in_array disable strict checking. So it doesn't check data type. If you want enable strict checking, you can invoke validator like this:

$validation = $validator->validate($data, [
    'enabled' => [
        'required',
        $validator('in', [true, 1])->strict()
    ]
]);

Then 'enabled' value should be boolean true, or int 1.

not_in:value_1,value_2,...

The field under this rule must not be included in the given list of values.

This rule also using in_array. You can enable strict checking by invoking validator and call strict() like example in rule in above.

min:number

The field under this rule must have a size greater or equal than the given number.

For string value, size corresponds to the number of characters. For integer or float value, size corresponds to its numerical value. For an array, size corresponds to the count of the array. If your value is numeric string, you can put numeric rule to treat its size by numeric value instead of number of characters.

You can also validate uploaded file using this rule to validate minimum size of uploaded file. For example:

$validation = $validator->validate([
    'photo' => $_FILES['photo']
], [
    'photo' => 'required|min:1M'
]);
max:number

The field under this rule must have a size lower or equal than the given number. Value size calculated in same way like min rule.

You can also validate uploaded file using this rule to validate maximum size of uploaded file. For example:

$validation = $validator->validate([
    'photo' => $_FILES['photo']
], [
    'photo' => 'required|max:2M'
]);
between:min,max

The field under this rule must have a size between min and max params. Value size calculated in same way like min and max rule.

You can also validate uploaded file using this rule to validate size of uploaded file. For example:

$validation = $validator->validate([
    'photo' => $_FILES['photo']
], [
    'photo' => 'required|between:1M,2M'
]);
digits:value

The field under validation must be numeric and must have an exact length of value.

digits_between:min,max

The field under validation must have a length between the given min and max.

url

The field under this rule must be valid url format. By default it check common URL scheme format like any_scheme://.... But you can specify URL schemes if you want.

For example:

$validation = $validator->validate($inputs, [
    'random_url' => 'url',          // value can be `any_scheme://...`
    'https_url' => 'url:http',      // value must be started with `https://`
    'http_url' => 'url:http,https', // value must be started with `http://` or `https://`
    'ftp_url' => 'url:ftp',         // value must be started with `ftp://`
    'custom_url' => 'url:custom',   // value must be started with `custom://`
    'mailto_url' => 'url:mailto',   // value must conatin valid mailto URL scheme like `mailto:[email protected],[email protected]`
    'jdbc_url' => 'url:jdbc',       // value must contain valid jdbc URL scheme like `jdbc:mysql://localhost/dbname`
]);

For common URL scheme and mailto, we combine FILTER_VALIDATE_URL to validate URL format and preg_match to validate it's scheme. Except for JDBC URL, currently it just check a valid JDBC scheme.

integer The field under t rule must be integer.
boolean

The field under this rule must be boolean. Accepted input are true, false, 1, 0, "1", and "0".

ip

The field under this rule must be valid ipv4 or ipv6.

ipv4

The field under this rule must be valid ipv4.

ipv6

The field under this rule must be valid ipv6.

extension:extension_a,extension_b,...

The field under this rule must end with an extension corresponding to one of those listed.

This is useful for validating a file type for a given a path or url. The mimes rule should be used for validating uploads.

array

The field under this rule must be array.

same:another_field

The field value under this rule must be same with another_field value.

regex:/your-regex/

The field under this rule must be match with given regex.

date:format

The field under this rule must be valid date format. Parameter format is optional, default format is Y-m-d.

accepted

The field under this rule must be one of 'on', 'yes', '1', 'true', or true.

present

The field under this rule must be exists, whatever the value is.

different:another_field

Opposite of same. The field value under this rule must be different with another_field value.

after:tomorrow

Anything that can be parsed by strtotime can be passed as a parameter to this rule. Valid examples include :

  • after:next week
  • after:2016-12-31
  • after:2016
  • after:2016-12-31 09:56:02
before:yesterday

This also works the same way as the after rule. Pass anything that can be parsed by strtotime

callback

You can use this rule to define your own validation rule. This rule can't be registered using string pipe. To use this rule, you should put Closure inside array of rules.

For example:

$validation = $validator->validate($_POST, [
    'even_number' => [
        'required',
        function ($value) {
            // false = invalid
            return (is_numeric($value) AND $value % 2 === 0);
        }
    ]
]);

You can set invalid message by returning a string. For example, example above would be:

$validation = $validator->validate($_POST, [
    'even_number' => [
        'required',
        function ($value) {
            if (!is_numeric($value)) {
                return ":attribute must be numeric.";
            }
            if ($value % 2 !== 0) {
                return ":attribute is not even number.";
            }
            // you can return true or don't return anything if value is valid
        }
    ]
]);

Note: Rakit\Validation\Rules\Callback instance is binded into your Closure. So you can access rule properties and methods using $this.

nullable

Field under this rule may be empty.

Register/Override Rule

Another way to use custom validation rule is to create a class extending Rakit\Validation\Rule. Then register it using setValidator or addValidator.

For example, you want to create unique validator that check field availability from database.

First, lets create UniqueRule class:

<?php

use Rakit\Validation\Rule;

class UniqueRule extends Rule
{
    protected $message = ":attribute :value has been used";

    protected $fillableParams = ['table', 'column', 'except'];

    protected $pdo;

    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
    }

    public function check($value): bool
    {
        // make sure required parameters exists
        $this->requireParameters(['table', 'column']);

        // getting parameters
        $column = $this->parameter('column');
        $table = $this->parameter('table');
        $except = $this->parameter('except');

        if ($except AND $except == $value) {
            return true;
        }

        // do query
        $stmt = $this->pdo->prepare("select count(*) as count from `{$table}` where `{$column}` = :value");
        $stmt->bindParam(':value', $value);
        $stmt->execute();
        $data = $stmt->fetch(PDO::FETCH_ASSOC);

        // true for valid, false for invalid
        return intval($data['count']) === 0;
    }
}

Then you need to register UniqueRule instance into validator like this:

use Rakit\Validation\Validator;

$validator = new Validator;

$validator->addValidator('unique', new UniqueRule($pdo));

Now you can use it like this:

$validation = $validator->validate($_POST, [
    'email' => 'email|unique:users,email,[email protected]'
]);

In UniqueRule above, property $message is used for default invalid message. And property $fillable_params is used for fillParameters method (defined in Rakit\Validation\Rule class). By default fillParameters will fill parameters listed in $fillable_params. For example unique:users,email,[email protected] in example above, will set:

$params['table'] = 'users';
$params['column'] = 'email';
$params['except'] = '[email protected]';

If you want your custom rule accept parameter list like in,not_in, or uploaded_file rules, you just need to override fillParameters(array $params) method in your custom rule class.

Note that unique rule that we created above also can be used like this:

$validation = $validator->validate($_POST, [
    'email' => [
    	'required', 'email',
    	$validator('unique', 'users', 'email')->message('Custom message')
    ]
]);

So you can improve UniqueRule class above by adding some methods that returning its own instance like this:

<?php

use Rakit\Validation\Rule;

class UniqueRule extends Rule
{
    ...

    public function table($table)
    {
        $this->params['table'] = $table;
        return $this;
    }

    public function column($column)
    {
        $this->params['column'] = $column;
        return $this;
    }

    public function except($value)
    {
        $this->params['except'] = $value;
        return $this;
    }

    ...
}

Then you can use it in more funky way like this:

$validation = $validator->validate($_POST, [
    'email' => [
    	'required', 'email',
    	$validator('unique')->table('users')->column('email')->except('[email protected]')->message('Custom message')
    ]
]);

Implicit Rule

Implicit rule is a rule that if it's invalid, then next rules will be ignored. For example if attribute didn't pass required* rules, mostly it's next rules will also be invalids. So to prevent our next rules messages to get collected, we make required* rules to be implicit.

To make your custom rule implicit, you can make $implicit property value to be true. For example:

<?php

use Rakit\Validation\Rule;

class YourCustomRule extends Rule
{

    protected $implicit = true;

}

Modify Value

In some case, you may want your custom rule to be able to modify it's attribute value like our default/defaults rule. So in current and next rules checks, your modified value will be used.

To do this, you should implements Rakit\Validation\Rules\Interfaces\ModifyValue and create method modifyValue($value) to your custom rule class.

For example:

<?php

use Rakit\Validation\Rule;
use Rakit\Validation\Rules\Interfaces\ModifyValue;

class YourCustomRule extends Rule implements ModifyValue
{
    ...

    public function modifyValue($value)
    {
        // Do something with $value

        return $value;
    }

    ...
}

Before Validation Hook

You may want to do some preparation before validation running. For example our uploaded_file rule will resolves attribute value that come from $_FILES (undesirable) array structure to be well-organized array structure, so we can validate multiple file upload just like validating other data.

To do this, you should implements Rakit\Validation\Rules\Interfaces\BeforeValidate and create method beforeValidate() to your custom rule class.

For example:

<?php

use Rakit\Validation\Rule;
use Rakit\Validation\Rules\Interfaces\BeforeValidate;

class YourCustomRule extends Rule implements BeforeValidate
{
    ...

    public function beforeValidate()
    {
        $attribute = $this->getAttribute(); // Rakit\Validation\Attribute instance
        $validation = $this->validation; // Rakit\Validation\Validation instance

        // Do something with $attribute and $validation
        // For example change attribute value
        $validation->setValue($attribute->getKey(), "your custom value");
    }

    ...
}

validation's People

Contributors

asdert92 avatar coderi-sk avatar denislavparvanov avatar devhammed avatar dhonx avatar emsifa avatar jaystream avatar kidstell avatar netsco avatar peter279k avatar phannaly avatar pnoexz avatar thhareau avatar thomasfw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

validation's Issues

Custom Validation Message

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.

Rules following present are not checked after an empty value

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.

String type number use min rules error

in SizeTrait.php
在用min验证规则时候出现错误。
从表单获取的值数字是字符串类型的,仅仅通过 is_int($value) || is_float($value) 来判断不正确。
希望加上 is_int($value) || is_float($value) || is_numeric($value)

Typo in AlphaDash default message

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 -"

Error message without index

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)?

Composer Installation Package Failed

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:
image

does anyone have this problem?

Min and max don't work properly

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.

Discussion and Progress for v1 Release

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:

  • Drop support for PHP 5. Minimum support is PHP 7.0. #62
  • Change ErrorBag::firstOrAll to return array assoc instead of indexed array. #64
  • Split uploaded_file rule to uploaded_filesize and uploaded_filetype so we get separate error message. Add mimes to validate uploaded file mimes, and update min, max, and between rules to be able to validate uploaded file size. #69
  • Adding doc comments to methods and properties. #67
  • Adding type hint and return type. #67
  • Fixing some inconsistency in variable naming and format. #66
  • Improve documentation. #70 #72
  • Support multiple file upload. #71

And 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.

Setting aliases for arrays: how to?

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

Regex with | symbol

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.

getValidData() returns new elements when using dot notation

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?

Custom Rule Callback

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.

getValidData returning request data + valida data

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());
		}

Correct English in default validation messages

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).

Regex rule - unexpected warning with comma character

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];
}

Too many issues for me, but best solution, so i will write it here

  1. There's no nullable validator like in laravel. It allows to skip validations if user doesnt send the value

  2. 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

  3. 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

  4. 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.

  5. 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

  6. 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.

getValidatedData returns unknown keys

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().

Documentation issue IN Rule

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.

required only if value exists/not empty?

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

required_without is not working properly

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.

alpha_num (with spaces)

Hi, is there any support for a field which can have both alphabetical and numerical data, with spaces?

Thanks

How to get detailed error response

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

validate only if data array is equal to rule array

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();?

How to make a multiple file input required?

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.

Set message for uploaded_file:max_size

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' ),
    ]
);

Required if with uploaded file does not work

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.

Require field when either of two fields are present

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?

Required if with array and checkboxes

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 :-)

Required If

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! :)

Not possible to validate incoming json array

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?

Validating min/max numbers

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?

Mime Type for zip not working

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

Pass value to error message

Hello!
As a developer I would like to use attribute value in error message. On my opinion it's very usable for forms validation.

Regex rule breaks when the regex contains pipe character(s)

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 :)

'same' rule not working properly

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
                }

Attribute aliases should replace all instances of field names in validation error messages

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?

How to set custom error message by per input not by error type

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".

URL validation is minimal at best

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.

Error message not changing

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" } }
}

Please include a license file.

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.