本文目录导读:

在 PHP 中进行规则测试,主要有以下几种常见方式:
单元测试(PHPUnit)
安装 PHPUnit
composer require --dev phpunit/phpunit
示例:测试业务规则
<?php
use PHPUnit\Framework\TestCase;
class DiscountRuleTest extends TestCase
{
private $discountCalculator;
protected function setUp(): void
{
$this->discountCalculator = new DiscountCalculator();
}
/** @test */
public function testVIPCustomerGets20PercentDiscount()
{
$customer = new Customer('VIP');
$order = new Order(1000);
$finalPrice = $this->discountCalculator->calculate($order, $customer);
$this->assertEquals(800, $finalPrice);
}
/** @test */
public function testNormalCustomerGetsNoDiscount()
{
$customer = new Customer('NORMAL');
$order = new Order(1000);
$finalPrice = $this->discountCalculator->calculate($order, $customer);
$this->assertEquals(1000, $finalPrice);
}
}
验证规则(Validation Rules)
使用 Laravel 验证规则
<?php
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
class UserController extends Controller
{
public function store(Request $request)
{
$rules = [
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email',
'age' => 'required|integer|min:18|max:65',
'password' => 'required|min:8|confirmed',
'role' => ['required', Rule::in(['admin', 'user', 'moderator'])],
];
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
return response()->json([
'errors' => $validator->errors()
], 422);
}
}
}
自定义验证规则
<?php
// 自定义规则类
class ValidPhoneNumber implements Rule
{
public function passes($attribute, $value)
{
return preg_match('/^(\+86)?1[3-9]\d{9}$/', $value);
}
public function message()
{
return '手机号格式不正确';
}
}
// 使用
$rules = [
'phone' => ['required', new ValidPhoneNumber],
];
业务规则引擎测试
使用规则引擎包(如 RulerZ)
<?php
require 'vendor/autoload.php';
use RulerZ\RulerZ;
use RulerZ\Compiler\Compiler;
use RulerZ\Target\ArrayTarget;
// 定义规则
$rules = [
'user.is_active = true AND user.balance > 100',
'user.age >= 18 AND user.country IN ["CN", "US", "UK"]',
'user.is_vip OR user.purchase_count > 10'
];
// 创建引擎
$rulerz = new RulerZ(
Compiler::create(),
[new ArrayTarget()]
);
// 测试数据
$users = [
['name' => '张三', 'age' => 25, 'is_active' => true, 'balance' => 500, 'country' => 'CN', 'is_vip' => false, 'purchase_count' => 5],
['name' => '李四', 'age' => 17, 'is_active' => false, 'balance' => 50, 'country' => 'US', 'is_vip' => false, 'purchase_count' => 8],
];
// 测试规则
foreach ($users as $user) {
$isEligible = $rulerz->satisfies($user, $rules[0]);
var_dump("用户 {$user['name']} 是否符合规则: " . ($isEligible ? '是' : '否'));
}
规则验证函数
<?php
class BusinessRuleValidator
{
private $rules = [];
public function addRule($name, callable $rule, $errorMessage)
{
$this->rules[$name] = [
'validator' => $rule,
'message' => $errorMessage
];
}
public function validate($data)
{
$errors = [];
foreach ($this->rules as $name => $rule) {
if (!$rule['validator']($data)) {
$errors[$name] = $rule['message'];
}
}
return $errors;
}
}
// 使用示例
$validator = new BusinessRuleValidator();
$validator->addRule(
'minimum_order',
function($order) {
return $order['amount'] >= 100;
},
'订单金额不能低于 100 元'
);
$validator->addRule(
'max_quantity',
function($order) {
return count($order['items']) <= 10;
},
'单个订单最多 10 个商品'
);
$validator->addRule(
'valid_date',
function($order) {
return strtotime($order['date']) <= time();
},
'订单日期不能在未来'
);
$order = [
'amount' => 150,
'items' => [1, 2, 3, 4],
'date' => '2024-01-15'
];
$errors = $validator->validate($order);
print_r($errors);
数据验证辅助函数
<?php
function validateEmail($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
function validatePhone($phone) {
return preg_match('/^[0-9+\-\(\) ]{10,15}$/', $phone);
}
function validateIp($ip) {
return filter_var($ip, FILTER_VALIDATE_IP) !== false;
}
function validateUrl($url) {
return filter_var($url, FILTER_VALIDATE_URL) !== false;
}
function validateBetween($value, $min, $max) {
return $value >= $min && $value <= $max;
}
function validateIn($value, array $allowed) {
return in_array($value, $allowed, true);
}
// 测试
$email = "test@example.com";
$phone = "+86 138-0013-8000";
$userId = 25;
echo validateEmail($email) ? "邮箱有效" : "邮箱无效";
echo "<br>";
echo validatePhone($phone) ? "电话有效" : "电话无效";
echo "<br>";
echo validateBetween($userId, 18, 60) ? "年龄在范围内" : "年龄超出范围";
Web 框架中的规则测试
Symfony 表单验证
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Validation;
class UserRegistrationForm
{
/**
* @Assert\NotBlank(message="用户名不能为空")
* @Assert\Length(min=3, max=32)
*/
private $username;
/**
* @Assert\NotBlank
* @Assert\Email
*/
private $email;
/**
* @Assert\NotBlank
* @Assert\Length(min=6, max=128)
*/
private $password;
// ... getters/setters
}
$validator = Validation::createValidatorBuilder()
->enableAnnotationMapping()
->getValidator();
$user = new UserRegistrationForm();
$user->setUsername('abc');
// ... 设置其他属性
$errors = $validator->validate($user);
测试建议
编写有效测试的原则
<?php
class OrderValidationTest extends TestCase
{
/** @test */
public function testOrderValidationRules()
{
$validator = new OrderValidator();
// 测试成功场景
$validData = [
'customer_name' => '张三',
'items' => ['item1', 'item2'],
'total_amount' => 150.00,
'payment_method' => 'credit_card'
];
$this->assertTrue($validator->validate($validData));
// 测试失败场景
$invalidData = [
'customer_name' => '',
'items' => [],
'total_amount' => -1,
'payment_method' => 'invalid_method'
];
$this->assertFalse($validator->validate($invalidData));
// 测试边界情况
$boundaryData = [
'customer_name' => 'A',
'items' => ['item'],
'total_amount' => 0.01,
'payment_method' => 'cash'
];
$this->assertTrue($validator->validate($boundaryData));
}
}
PHP 规则测试的核心方式:
- 单元测试:使用 PHPUnit 等框架测试业务逻辑
- 验证规则:使用内置或框架验证功能
- 规则引擎:处理复杂的业务规则
- 自定义验证器:根据需求创建专用验证工具
- Web 框架集成:使用框架提供的验证功能
选择哪种方式取决于你的具体需求:
- 简单的数据验证 → 使用验证函数
- 复杂业务逻辑 → 单元测试
- Web 表单 → 框架验证功能
- 动态规则 → 规则引擎