yii2中ip校验需区分ipv4、ipv6及非法输入:推荐用精确正则校验ipv4;混合场景用内联验证器并辅以filter_var提升ipv6兼容性;多模型复用时应封装为独立validator类。

在Yii2项目中对用户提交的IP地址字段做格式校验,防止非法字符串入库或触发后续逻辑异常,必须严格区分IPv4、IPv6及非法输入三类情况。
用match规则配合正则表达式校验IPv4
这一步操作起来很简单,直接在Model的rules()方法里加一条规则即可。
方法一:使用精确IPv4正则(推荐)
在rules()中写:[['ip'], 'match', 'pattern' => '/^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}$/']。
这个正则能准确拦截带前导零的IP(如192.168.01.1),也能拒绝256、-1这类越界数值,比简单d{1,3}更安全。
方法二:用宽松点的点分四段结构校验
['ip', 'match', 'pattern' => '/^(d{1,3}.){3}d{1,3}$/'],但【它不校验每段是否在0–255范围内】,仅适合前端初步过滤或日志字段宽松录入场景。
用自定义内联验证器统一处理IPv4/IPv6
当一个字段需同时接受IPv4和IPv6时,内置match无法分支判断,必须用内联验证器手动拆解逻辑。
第一步:在rules()中添加内联规则:
['ip', function ($model, $attribute) {
$value = $model->$attribute;
if (empty($value)) return;
if ($this->isValidIPv4($value) || $this->isValidIPv6($value)) return;
$model->addError($attribute, '请输入有效的IPv4或IPv6地址');
}],
第二步:在Model类中定义两个私有方法:
private function isValidIPv4($ip) { return preg_match('/^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}$/', $ip); }
private function isValidIPv6($ip) { return preg_match('/^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/', $ip); }
注意:IPv6正则未覆盖缩写形式(如::1),如需完整支持,应改用filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)。
用独立验证类复用IP校验逻辑
若多个Model都要校验IP,把逻辑抽成Validator类是更规范的做法。
创建文件:common/validators/IPAddressValidator.php
内容必须继承yiialidatorsValidator,并在init()中调用parent::init()。
核心验证逻辑写在validateAttribute()里:
public function validateAttribute($model, $attribute) {
$value = $model->$attribute;
if (empty($value)) {
if (!$this->skipOnEmpty) $model->addError($attribute, $this->message ?: 'IP地址不能为空');
return;
}
if (!filter_var($value, FILTER_VALIDATE_IP)) {
$model->addError($attribute, $this->message ?: 'IP地址格式无效');
}
}
在rules()中使用:
['ip', 'common\validators\IPAddressValidator']。
这样写的好处是天然支持IPv4/IPv6双校验,且filter_var已内置RFC标准解析,比手写正则更可靠。











