本文目录导读:

在 PHP 中实现回调校验(Callback Validation)通常有以下几种常见场景和方法:
函数回调校验
检查回调是否有效
<?php
// 检查是否是有效的回调
function validateCallback($callback) {
if (!is_callable($callback)) {
throw new InvalidArgumentException('Invalid callback provided');
}
return true;
}
// 使用示例
$callbacks = [
'myFunction', // 函数名字符串
['MyClass', 'method'], // 类方法数组
[$object, 'method'], // 对象方法数组
function ($data) { // 匿名函数
return $data;
},
'MyClass::staticMethod' // 静态方法字符串
];
foreach ($callbacks as $callback) {
try {
validateCallback($callback);
echo "Valid callback\n";
} catch (Exception $e) {
echo "Invalid callback: " . $e->getMessage() . "\n";
}
}
回调参数校验
<?php
class CallbackValidator {
/**
* 校验回调函数返回的数据
*/
public static function validateResult($callback, $data) {
if (!is_callable($callback)) {
throw new InvalidArgumentException('Callback is not callable');
}
$result = call_user_func($callback, $data);
// 验证返回结果
if ($result === false) {
throw new RuntimeException('Callback returned false');
}
return $result;
}
/**
* 带参数数量的回调校验
*/
public static function validateWithArgs($callback, $expectedArgs = 0) {
if (!is_callable($callback)) {
throw new InvalidArgumentException('Callback is not callable');
}
// 获取回调的参数数量(仅对函数有效)
if (is_string($callback) && function_exists($callback)) {
$reflection = new ReflectionFunction($callback);
$actualArgs = $reflection->getNumberOfParameters();
if ($actualArgs < $expectedArgs) {
throw new InvalidArgumentException(
"Callback expects {$actualArgs} arguments, but {$expectedArgs} required"
);
}
}
return true;
}
}
数组回调的高级校验
<?php
function validateArrayCallback($array, $callback) {
if (!is_callable($callback)) {
return false;
}
$results = array_map($callback, $array);
// 检查全部通过
foreach ($results as $key => $result) {
if (!$result) {
return [
'valid' => false,
'failed_key' => $key,
'message' => "Validation failed for key: {$key}"
];
}
}
return ['valid' => true];
}
// 使用示例
$data = [
'email' => 'user@example.com',
'age' => 25,
'name' => 'John Doe'
];
$validationRules = [
'email' => function ($value) {
return filter_var($value, FILTER_VALIDATE_EMAIL) !== false;
},
'age' => function ($value) {
return is_numeric($value) && $value >= 18;
},
'name' => function ($value) {
return is_string($value) && strlen($value) > 2;
}
];
foreach ($data as $key => $value) {
$result = validateArrayCallback([$value], $validationRules[$key]);
echo "Field '{$key}': " . ($result['valid'] ? 'Passed' : 'Failed') . "\n";
}
类型校验的回调
<?php
class TypeValidator {
/**
* 创建类型校验回调
*/
public static function makeTypeValidator($type) {
return function ($value) use ($type) {
switch ($type) {
case 'string':
return is_string($value);
case 'integer':
case 'int':
return is_int($value);
case 'float':
case 'double':
return is_float($value) || is_double($value);
case 'array':
return is_array($value);
case 'boolean':
case 'bool':
return is_bool($value);
case 'null':
return is_null($value);
case 'numeric':
return is_numeric($value);
default:
return false;
}
};
}
/**
* 校验多个字段
*/
public static function validateFields($data, $rules) {
$errors = [];
foreach ($rules as $field => $validator) {
if (!isset($data[$field])) {
$errors[$field] = "Field '{$field}' is missing";
continue;
}
if (is_callable($validator) && !$validator($data[$field])) {
$errors[$field] = "Field '{$field}' failed validation";
}
}
return empty($errors) ? true : $errors;
}
}
// 使用示例
$data = [
'username' => 'john_doe',
'email' => 'invalid-email',
'age' => 'twenty-five',
'active' => true
];
$rules = [
'username' => TypeValidator::makeTypeValidator('string'),
'email' => function ($value) {
return filter_var($value, FILTER_VALIDATE_EMAIL) !== false;
},
'age' => TypeValidator::makeTypeValidator('integer'),
'active' => TypeValidator::makeTypeValidator('boolean')
];
$result = TypeValidator::validateFields($data, $rules);
if ($result === true) {
echo "All validation passed!\n";
} else {
echo "Validation errors:\n";
foreach ($result as $field => $error) {
echo " - {$error}\n";
}
}
异步回调校验(Promise 模式)
<?php
class AsyncCallbackValidator {
public static function validateAsync($callback) {
if (!is_callable($callback)) {
return Promise::reject(new InvalidArgumentException('Invalid callback'));
}
return Promise::resolve()
->then(function () use ($callback) {
$result = call_user_func($callback);
if (!$result) {
throw new RuntimeException('Validation failed');
}
return $result;
});
}
}
最佳实践建议
<?php
/**
* 完整的回调校验框架
*/
class SecureCallbackValidator {
private $allowedNamespaces = ['App\\Validators\\'];
/**
* 安全的回调校验
*/
public function validate($callback, $options = []) {
// 1. 基本可调用性检查
if (!is_callable($callback)) {
throw new InvalidArgumentException('Callback is not callable');
}
// 2. 字符串回调安全检查(防止代码注入)
if (is_string($callback)) {
$this->checkStringCallback($callback);
}
// 3. 反射检查
$reflection = $this->getReflection($callback);
if (!$reflection->isUserDefined()) {
throw new SecurityException('Cannot use internal PHP functions as callback');
}
// 4. 参数数量验证
if (isset($options['expected_params'])) {
$this->checkParameterCount($reflection, $options['expected_params']);
}
return true;
}
private function checkStringCallback($callback) {
// 防止任意代码执行
if (strpos($callback, '::') !== false || strpos($callback, '->') !== false) {
throw new SecurityException('Unsafe callback string format');
}
}
private function getReflection($callback) {
if (is_array($callback)) {
return new ReflectionMethod($callback[0], $callback[1]);
}
if (is_string($callback)) {
return new ReflectionFunction($callback);
}
return new ReflectionFunction($callback);
}
private function checkParameterCount($reflection, $expected) {
$actual = $reflection->getNumberOfParameters();
if ($actual !== $expected) {
throw new InvalidArgumentException(
"Callback expects {$actual} parameters, {$expected} given"
);
}
}
}
实际应用示例
<?php
// 表单验证框架
class FormValidator {
private $rules;
public function addRule($field, $validator) {
$this->validateCallback($validator);
$this->rules[$field][] = $validator;
return $this;
}
public function validate($data) {
$errors = [];
foreach ($this->rules as $field => $validators) {
foreach ($validators as $validator) {
$result = call_user_func($validator, $data[$field] ?? null);
if (is_string($result)) {
// 返回错误消息
$errors[$field] = $result;
break;
} elseif ($result === false) {
$errors[$field] = "{$field} is invalid";
break;
}
}
}
return empty($errors) ? true : $errors;
}
private function validateCallback($callback) {
if (!is_callable($callback)) {
throw new InvalidArgumentException('Invalid callback');
}
}
}
// 使用
$validator = new FormValidator();
$validator
->addRule('username', function ($value) {
return preg_match('/^[a-zA-Z0-9_]{3,20}$/', $value) ?: 'Invalid username format';
})
->addRule('email', function ($value) {
return filter_var($value, FILTER_VALIDATE_EMAIL) ? 'Invalid email' : true;
});
$data = [
'username' => 'john',
'email' => 'invalid-email'
];
$result = $validator->validate($data);
if (is_array($result)) {
print_r($result);
}
这些方法覆盖了 PHP 回调校验的主要场景,根据你的具体需求,可以选择合适的方法来实现回调校验,关键是要确保:
- 回调确实可调用
- 回调的参数和返回值符合预期
- 考虑安全性,防止恶意代码执行
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播