rougin/valla 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

rougin/valla

Composer 安装命令:

composer require rougin/valla

包简介

A simple validation package in PHP.

README 文档

README

Latest Version on Packagist Software License Build Status Coverage Status Total Downloads

A simple validation package for PHP inspired by Valitron.

use Rougin\Valla\Valid;

$data = array('name' => '', 'email' => 'not-an-email');

$valid = new Valid($data);

$valid->addRule('name', 'required');
$valid->addRule('email', 'required|email');

if (! $valid->passed())
{
    // "Name is required"
    echo $valid->firstError();
}

Installation

Install the package using Composer:

$ composer require rougin/valla

Basic usage

The core of Valla is the Valid class. Create an instance with the data to validate, then add rules with addRule():

use Rougin\Valla\Valid;

$data = array('age' => 'abc');
$data['email'] = 'not-an-email';
$data['name'] = '';

$valid = new Valid($data);

$valid->addRule('age', 'required|numeric');
$valid->addRule('email', 'required|email');
$valid->addRule('name', 'required');

if (! $valid->passed())
{
    $errors = $valid->getErrors();

    // "Age must be numeric"
    echo $valid->firstError();
}

Setting labels

Labels provide user-friendly field names in error messages:

use Rougin\Valla\Valid;

$data = array('email' => 'not-an-email');

$valid = new Valid($data);

$labels = array('email' => 'Email Address');

$valid->setLabels($labels);

$valid->addRule('email', 'email');

if (! $valid->passed())
{
    // "Email Address is not a valid email address"
    echo $valid->firstError();
}

Adding custom rules

Custom rules can be added by implementing to RuleInterface:

namespace Rougin\Test\Rules;

use Rougin\Valla\RuleInterface;
use Rougin\Valla\Ruleset;

class Uppercase implements RuleInterface
{
    public function getError()
    {
        return 'must be uppercase';
    }

    public function getName()
    {
        return 'uppercase';
    }

    public function passed($value, array $data)
    {
        return strtoupper($value) === $value;
    }

    public function setValue(array $values)
    {
        return $this;
    }
}

To register the custom rule, add it to a Ruleset class then set it to the Valid class:

use Rougin\Test\Rules\Uppercase;
use Rougin\Valla\Valid;
use Rougin\Valla\Ruleset;

// Register the custom rule ---
$rules = new Ruleset;

$rules->addRule(new Uppercase);
// ----------------------------

// Inject the ruleset to check ---
$data = array('name' => 'Valla');

$valid = new Valid($data);

$valid->setRuleset($rules);
// -------------------------------

$valid->addRule('name', 'uppercase');

if (! $valid->passed())
{
    // "Name must be uppercase"
    echo $valid->firstError();
}

Using Check class

The Check class provides a declarative, class-based approach to validation by defining rules and labels as properties. It wraps a Valid instance internally.

Using labels, rules

The $labels property defines user-friendly names for the fields, while $rules specifies the validation rules:

use Rougin\Valla\Check;

class UserCheck extends Check
{
    protected $labels = array(
        'age' => 'Age',
        'email' => 'Email',
        'name' => 'Name',
    );

    protected $rules = array(
        'age' => 'required|numeric',
        'email' => 'required|email',
        'name' => 'required',
    );
}

Validating data

Once the Check class is created, validate an array of data using valid():

$check = new UserCheck;

$data = array('name' => 'John');
$data['age'] = 20;
$data['email'] = 'john@example.com';

if (! $check->valid($data))
{
    echo $check->firstError();
}

Dynamic labels, rules

For more validation scenarios, the labels and rules methods can be overridden to define them dynamically:

use Rougin\Valla\Check;

class UserCheck extends Check
{
    /**
     * @return array<string, string>
     */
    public function labels()
    {
        $labels = $this->labels;

        $labels['is_company'] = 'Is a Company?';

        return $labels;
    }

    /**
     * @param array<string, mixed> $data
     *
     * @return array<string, string>
     */
    public function rules(array $data)
    {
        $rules = $this->rules;

        if (array_key_exists('is_company', $data))
        {
            $rules['company_name'] = 'required';
        }

        return $rules;
    }
}

Using PSR-7 requests

If using ServerRequestInterface from PSR-7, the Request class provides a convenient way to validate request data:

use Rougin\Valla\Request;

class UserCheck extends Request
{
    /**
     * @var array<string, string>
     */
    protected $aliases = array(

        'username' => 'name',
        'email_add' => 'email',
        'new_age' => 'age',

    );

    // ...
}

The Request class provides two methods for validation: isParamsValid for validating query parameters and isParsedValid for validating the parsed body:

$check = new UserCheck;

// Returns the "ServerRequestInterface" ---
$request = Http::getServerRequest();
// ----------------------------------------

// Checks against data from "getQueryParams" ---
if ($check->isParamsValid($request))
{
    // Query parameters are valid
}
// ---------------------------------------------

// Checks against data from "getParsedBody" ---
if ($check->isParsedValid($request))
{
    // Parsed body is valid
}
// --------------------------------------------

When an alias is specified, it will be used to look for the field in the ServerRequestInterface data. For example, if the request data contains a username field, it will be validated against the rules defined for the name field.

Overriding valid

When extending the Request class and overriding the valid method, the setAlias method must be called to apply the defined aliases:

use Rougin\Valla\Request;

class UserCheck extends Request
{
    // ...

    public function valid($data)
    {
        // Always include this if aliases are defined ---
        $data = $this->setAlias($data);
        // ----------------------------------------------

        if (! parent::valid($data))
        {
            return count($this->errors) === 0;
        }

        // Add extra custom validation conditions here

        return count($this->errors) === 0;
    }
}

Built-in rules

Valla ships with 43 built-in rules, each pre-loaded in the default Ruleset:

contains

Checks that the value contains the given substring with non-string values fail automatically:

use Rougin\Valla\Valid;

$data = array('name' => 'Jane');

$valid = new Valid($data);

$valid->addRule('name', 'contains:Doe');

if (! $valid->passed())
{
    // "Name must contain Doe"
    echo $valid->firstError();
}

creditCard

Validates a credit card number using the Luhn algorithm with dashes and spaces stripped before checking:

use Rougin\Valla\Valid;

$data = array('card' => '123456789');

$valid = new Valid($data);

$valid->addRule('card', 'creditCard');

if (! $valid->passed())
{
    // "Card must be a valid credit card number"
    echo $valid->firstError();
}

email

Validates a properly formatted email address with non-string values fail automatically:

use Rougin\Valla\Valid;

$data = array('email' => 'not-an-email');

$valid = new Valid($data);

$valid->addRule('email', 'email');

if (! $valid->passed())
{
    // "Email is not a valid email address"
    echo $valid->firstError();
}

in

Checks that the value matches one of the listed values:

use Rougin\Valla\Valid;

$data = array('role' => 'guest');

$valid = new Valid($data);

$valid->addRule('role', 'in:admin,editor');

if (! $valid->passed())
{
    // "Role contains invalid value"
    echo $valid->firstError();
}

instanceOf

Validates that the value is an instance of the given class with non-object values fail automatically:

use Rougin\Valla\Valid;

$data = array('obj' => new \stdClass);

$valid = new Valid($data);

$valid->addRule('obj', 'instanceOf:\DateTime');

if (! $valid->passed())
{
    // "Obj must be an instance of 'DateTime'"
    echo $valid->firstError();
}

lengthMax

Checks that the value does not exceed the given character length with non-string values fail automatically:

use Rougin\Valla\Valid;

$data = array('name' => 'too long');

$valid = new Valid($data);

$valid->addRule('name', 'lengthMax:5');

if (! $valid->passed())
{
    // "Name must not exceed 5 characters"
    echo $valid->firstError();
}

lengthMin

Checks that the value meets the given minimum character length with non-string values fail automatically:

use Rougin\Valla\Valid;

$data = array('name' => 'Jo');

$valid = new Valid($data);

$valid->addRule('name', 'lengthMin:5');

if (! $valid->passed())
{
    // "Name must be at least 5 characters long"
    echo $valid->firstError();
}

notIn

Checks that the value does not match any of the listed values:

use Rougin\Valla\Valid;

$data = array('role' => 'admin');

$valid = new Valid($data);

$valid->addRule('role', 'notIn:admin,editor');

if (! $valid->passed())
{
    // "Role contains invalid value"
    echo $valid->firstError();
}

numeric

Checks that the value is numeric:

use Rougin\Valla\Valid;

$data = array('age' => 'abc');

$valid = new Valid($data);

$valid->addRule('age', 'numeric');

if (! $valid->passed())
{
    // "Age must be numeric"
    echo $valid->firstError();
}

required

Ensures the field is present and not empty with an optional strict mode rejecting only null:

use Rougin\Valla\Valid;

$data = array('name' => '');

$valid = new Valid($data);

$valid->addRule('name', 'required');

if (! $valid->passed())
{
    // "Name is required"
    echo $valid->firstError();
}

requiredWith

Makes the field required when at least one of the listed fields is present and non-empty:

use Rougin\Valla\Valid;

$data = array('company_name' => '', 'is_company' => 'yes');

$valid = new Valid($data);

$valid->addRule('company_name', 'requiredWith:is_company');

if (! $valid->passed())
{
    // "Company_name is required"
    echo $valid->firstError();
}

requiredWithout

Makes the field required when at least one of the listed fields is absent or empty:

use Rougin\Valla\Valid;

$data = array('phone' => '');

$valid = new Valid($data);

$valid->addRule('phone', 'requiredWithout:email');

if (! $valid->passed())
{
    // "Phone is required"
    echo $valid->firstError();
}

subset

Checks that every item in the array belongs to the listed set with non-array values fail automatically:

use Rougin\Valla\Valid;

$data = array('options' => array('a', 'd'));

$valid = new Valid($data);

$valid->addRule('options', 'subset:a,b,c');

if (! $valid->passed())
{
    // "Options contains an item that is not in the list"
    echo $valid->firstError();
}

accepted

Checks that the value is one of yes, on, 1, or true:

use Rougin\Valla\Valid;

$data = array('terms' => 'no');

$valid = new Valid($data);

$valid->addRule('terms', 'accepted');

if (! $valid->passed())
{
    // "Terms is not accepted"
    echo $valid->firstError();
}

alpha

Checks that the value contains only alphabetic characters:

use Rougin\Valla\Valid;

$data = array('name' => '123');

$valid = new Valid($data);

$valid->addRule('name', 'alpha');

if (! $valid->passed())
{
    // "Name must contain only alphabetic characters"
    echo $valid->firstError();
}

alphaNum

Checks that the value contains only alpha-numeric characters:

use Rougin\Valla\Valid;

$data = array('name' => 'test!@#');

$valid = new Valid($data);

$valid->addRule('name', 'alphaNum');

if (! $valid->passed())
{
    // "Name must contain only alpha-numeric characters"
    echo $valid->firstError();
}

array

Checks that the value is an array:

use Rougin\Valla\Valid;

$data = array('items' => 'string');

$valid = new Valid($data);

$valid->addRule('items', 'array');

if (! $valid->passed())
{
    // "Items must be an array"
    echo $valid->firstError();
}

arrayHasKeys

Checks that the array value contains all of the specified keys:

use Rougin\Valla\Valid;

$data = array('data' => array('a' => 1));

$valid = new Valid($data);

$valid->addRule('data', 'arrayHasKeys:a,b');

if (! $valid->passed())
{
    // "Data must contain the required keys"
    echo $valid->firstError();
}

ascii

Checks that the value contains only ASCII characters:

use Rougin\Valla\Valid;

$data = array('name' => "J\xC3\xA1ne");

$valid = new Valid($data);

$valid->addRule('name', 'ascii');

if (! $valid->passed())
{
    // "Name must contain only ASCII characters"
    echo $valid->firstError();
}

between

Checks that the numeric value falls between the given minimum and maximum:

use Rougin\Valla\Valid;

$data = array('age' => 25);

$valid = new Valid($data);

$valid->addRule('age', 'between:1,20');

if (! $valid->passed())
{
    // "Age must be between 1 and 20"
    echo $valid->firstError();
}

boolean

Checks that the value is a boolean:

use Rougin\Valla\Valid;

$data = array('flag' => 'yes');

$valid = new Valid($data);

$valid->addRule('flag', 'boolean');

if (! $valid->passed())
{
    // "Flag must be a boolean"
    echo $valid->firstError();
}

containsUnique

Checks that the array value contains only unique values:

use Rougin\Valla\Valid;

$data = array('items' => array('a', 'b', 'a'));

$valid = new Valid($data);

$valid->addRule('items', 'containsUnique');

if (! $valid->passed())
{
    // "Items must contain unique values only"
    echo $valid->firstError();
}

date

Checks that the value is a valid date string:

use Rougin\Valla\Valid;

$data = array('birthday' => 'not-a-date');

$valid = new Valid($data);

$valid->addRule('birthday', 'date');

if (! $valid->passed())
{
    // "Birthday must be a valid date"
    echo $valid->firstError();
}

dateAfter

Checks that the value is a date after the specified date:

use Rougin\Valla\Valid;

$data = array('date' => '2020-01-01');

$valid = new Valid($data);

$valid->addRule('date', 'dateAfter:2023-01-01');

if (! $valid->passed())
{
    // "Date must be a date after 2023-01-01"
    echo $valid->firstError();
}

dateBefore

Checks that the value is a date before the specified date:

use Rougin\Valla\Valid;

$data = array('date' => '2024-01-01');

$valid = new Valid($data);

$valid->addRule('date', 'dateBefore:2023-01-01');

if (! $valid->passed())
{
    // "Date must be a date before 2023-01-01"
    echo $valid->firstError();
}

dateFormat

Checks that the value matches the specified date format (e.g., Y-m-d):

use Rougin\Valla\Valid;

$data = array('date' => '01-01-2023');

$valid = new Valid($data);

$valid->addRule('date', 'dateFormat:Y-m-d');

if (! $valid->passed())
{
    // "Date must be a valid date format"
    echo $valid->firstError();
}

different

Checks that the value is different from the value of another field:

use Rougin\Valla\Valid;

$data = array('a' => 'hello', 'b' => 'hello');

$valid = new Valid($data);

$valid->addRule('a', 'different:b');

if (! $valid->passed())
{
    // "A must be different from b"
    echo $valid->firstError();
}

emailDNS

Checks that the value is an email address with an active domain (MX record):

use Rougin\Valla\Valid;

$data = array('email' => 'test@nonexistent-domain.invalid');

$valid = new Valid($data);

$valid->addRule('email', 'emailDNS');

if (! $valid->passed())
{
    // "Email must be a valid email address with active domain"
    echo $valid->firstError();
}

equals

Checks that the value equals the value of another field:

use Rougin\Valla\Valid;

$data = array('a' => 'hello', 'b' => 'world');

$valid = new Valid($data);

$valid->addRule('a', 'equals:b');

if (! $valid->passed())
{
    // "A must be equal to b"
    echo $valid->firstError();
}

integer

Checks that the value is an integer with an optional strict mode:

use Rougin\Valla\Valid;

$data = array('age' => 'abc');

$valid = new Valid($data);

$valid->addRule('age', 'integer');

if (! $valid->passed())
{
    // "Age must be an integer"
    echo $valid->firstError();
}

ip

Checks that the value is a valid IP address:

use Rougin\Valla\Valid;

$data = array('ip' => 'not-an-ip');

$valid = new Valid($data);

$valid->addRule('ip', 'ip');

if (! $valid->passed())
{
    // "Ip must be a valid IP address"
    echo $valid->firstError();
}

ipv4

Checks that the value is a valid IPv4 address:

use Rougin\Valla\Valid;

$data = array('ip' => '::1');

$valid = new Valid($data);

$valid->addRule('ip', 'ipv4');

if (! $valid->passed())
{
    // "Ip must be a valid IPv4 address"
    echo $valid->firstError();
}

ipv6

Checks that the value is a valid IPv6 address:

use Rougin\Valla\Valid;

$data = array('ip' => '192.168.1.1');

$valid = new Valid($data);

$valid->addRule('ip', 'ipv6');

if (! $valid->passed())
{
    // "Ip must be a valid IPv6 address"
    echo $valid->firstError();
}

length

Checks that the string length matches an exact value or falls between min and max:

use Rougin\Valla\Valid;

$data = array('name' => 'Jo');

$valid = new Valid($data);

$valid->addRule('name', 'length:5');

if (! $valid->passed())
{
    // "Name must be exactly 5 characters"
    echo $valid->firstError();
}

lengthBetween

Checks that the string length falls between the given min and max:

use Rougin\Valla\Valid;

$data = array('name' => 'too long');

$valid = new Valid($data);

$valid->addRule('name', 'lengthBetween:1,5');

if (! $valid->passed())
{
    // "Name must be between 1 and 5 characters"
    echo $valid->firstError();
}

listContains

Checks that the array value contains the specified item:

use Rougin\Valla\Valid;

$data = array('items' => array('a', 'b'));

$valid = new Valid($data);

$valid->addRule('items', 'listContains:c');

if (! $valid->passed())
{
    // "Items must contain the specified value"
    echo $valid->firstError();
}

max

Checks that the numeric value does not exceed the given maximum:

use Rougin\Valla\Valid;

$data = array('age' => 25);

$valid = new Valid($data);

$valid->addRule('age', 'max:20');

if (! $valid->passed())
{
    // "Age must not exceed 20"
    echo $valid->firstError();
}

min

Checks that the numeric value is at least the given minimum:

use Rougin\Valla\Valid;

$data = array('age' => 5);

$valid = new Valid($data);

$valid->addRule('age', 'min:10');

if (! $valid->passed())
{
    // "Age must be at least 10"
    echo $valid->firstError();
}

optional

Always passes regardless of the value, allowing a field to be optional:

use Rougin\Valla\Valid;

$data = array('field' => '');

$valid = new Valid($data);

$valid->addRule('field', 'optional');

// [NOTE] Optional rules always pass
$valid->passed();

regex

Checks that the value matches the given regular expression:

use Rougin\Valla\Valid;

$data = array('name' => 'hello');

$valid = new Valid($data);

$valid->addRule('name', 'regex:/^[0-9]+$/');

if (! $valid->passed())
{
    // "Name does not match the required pattern"
    echo $valid->firstError();
}

slug

Checks that the value is a valid slug (alpha-numeric, dashes, underscores):

use Rougin\Valla\Valid;

$data = array('slug' => 'not a slug!');

$valid = new Valid($data);

$valid->addRule('slug', 'slug');

if (! $valid->passed())
{
    // "Slug must be a valid slug"
    echo $valid->firstError();
}

url

Checks that the value is a valid URL starting with http, https, or ftp:

use Rougin\Valla\Valid;

$data = array('link' => 'not-a-url');

$valid = new Valid($data);

$valid->addRule('link', 'url');

if (! $valid->passed())
{
    // "Link must be a valid URL"
    echo $valid->firstError();
}

urlActive

Checks that the value is a valid URL with an active domain (DNS record):

use Rougin\Valla\Valid;

$data = array('link' => 'http://nonexistent-domain.invalid');

$valid = new Valid($data);

$valid->addRule('link', 'urlActive');

if (! $valid->passed())
{
    // "Link must be a valid URL with active domain"
    echo $valid->firstError();
}

Migrating from Valitron

As this was inspired from Valitron, migrating to Valla is simple as changing its namespace and the class name. Valla provides the same rule method for mirroring Valitron's:

-use Valitron\Validator;
+use Rougin\Valla\Valid;

-$valid = new Validator($data);
+$valid = new Valid($data);

 $valid->rule('required', 'name');
 $valid->rule('min', 'age', 5);
 $valid->rule('required', array('name', 'email'));

 if (! $valid->validate())
 {
     print_r($valid->errors());
 }

Once migrated, update the said method to addRule with its required parameters:

-$valid->rule('required', 'name');
+$valid->addRule('name', 'required');
-$valid->rule('min', 'age', 5);
+$valid->addRule('age', 'min:5');
-$valid->rule('required', array('name', 'email'));
+$valid->addRule('name', 'required');
+$valid->addRule('email', 'required');

Warning

The rule method only accepts string rule names (e.g. 'required', 'min:5'). Callable rules will not be supported. Kindly see Adding custom rules for how to create one.

Changelog

Please see CHANGELOG for more recent changes and latest updates.

Contributing

See CONTRIBUTING on how to contribute to the project.

License

The MIT License (MIT). Please see LICENSE for more information.

rougin/valla 适用场景与选型建议

rougin/valla 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 1.07k 次下载、GitHub Stars 达 0, 最近一次更新时间为 2025 年 10 月 26 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「php-validation」 「php-validator」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 rougin/valla 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 rougin/valla 我们能提供哪些服务?
定制开发 / 二次开发

基于 rougin/valla 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 1.07k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 5
  • 依赖项目数: 3
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-10-26