在 Laravel 表单验证中我们常常会需要对一些非必填的字段进行校验,比如:string

但是如果如果 data 里面的对应字段是 null,则验证会失败,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$data = [
'num' => null
];

/** @var \Illuminate\Validation\Validator $validator */
$validator = app('validator')->make(
$data,
[
'num' => 'numeric'
]
);

if ($validator->fails()) {
dd($validator->messages()->toArray());
}

结果:

1
2
3
4
5
array:1 [
"num" => array:1 [
0 => "num字段值必须为数字"
]
]

如何让其通过验证?

如果我们的这个字段允许为 null 的话,可以加上 nullable 验证规则,比如:

1
2
3
$rules = [
'num' => 'nullable|numeric'
]

当然如果保存到数据库的时候不能为 null 的话,就不能这么写了。

dcat-admin 中的 Form, Show, Grid, Column 等内置类都 use 了 Dcat\Admin\Traits\HasBuilderEvents 这个 trait。

通过这个 trait,我们可以对 Form, Show, Grid, Column 的生命周期做一些类似勾子的操作。

resolving 主要用在统一自定义某些页面组件是否展示,composing 事件用于页面渲染时候做一些额外的操作。常用的主要是 resolving

resolving

1
2
3
4
5
6
7
// 默认禁用表单的一些 checkbox 以及 header
Form::resolving(function (Form $form) {
$form->disableHeader();
$form->disableViewCheck();
$form->disableEditingCheck();
$form->disableCreatingCheck();
});

composing

1
2
3
$form->composing(function ($form) {
static::addScript($form);
});
1
2
3
4
5
6
7
8
9
10
protected static function addScript(Form $form)
{
$confirm = json_encode($form->builder()->confirm);

Admin::script(
<<<JS
Dcat.FormConfirm = {$confirm};
JS
);
}

页面渲染的时候,添加一段自定义的 js 代码。

最近在使用 laravel/fortify 的过程中发现,在不同的环境中,一个环境 2fa 验证正常,但是另外一个环境验证一直失败,即使输入的是正确的验证码。

后来想起了 totp 算法相关的一个很关键的点,就是生成的验证码是基于时间的,这样一来,如果某一个环境上的时间是不对的(这里的不对是指不是那个环境时区上对应的准确时间),是不是和客户端生成的验证码不一样了。

后来经过验证发现,的确是这个原因导致的。

只有服务器的时间是正常的时间,UTC + 时区对应的小时数这样,验证都不会有问题。

另外,快速设置时间的方式:

1
date -s '20:09:41 2019-12-08'

bash 脚本:

script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/bin/sh
OSX_VERS=$(sw_vers -productVersion | awk -F "." '{print $2}')

# Get Xcode CLI tools
# https://devimages.apple.com.edgekey.net/downloads/xcode/simulators/index-3905972D-B609-49CE-8D06-51ADC78E07BC.dvtdownloadableindex
# https://developer.apple.com/downloads/index.action
TOOLS=clitools.dmg
if [ ! -f "$TOOLS" ]; then
if [ "$OSX_VERS" -eq 7 ]; then
DMGURL=http://devimages.apple.com/downloads/xcode/command_line_tools_for_xcode_os_x_lion_april_2013.dmg
elif [ "$OSX_VERS" -eq 8 ]; then
DMGURL=http://devimages.apple.com/downloads/xcode/command_line_tools_for_xcode_os_x_mountain_lion_april_2013.dmg
elif [ "$OSX_VERS" -eq 9 ]; then
DMGURL=http://adcdownload.apple.com/Developer_Tools/command_line_tools_os_x_mavericks_for_xcode__late_october_2013/command_line_tools_os_x_mavericks_for_xcode__late_october_2013.dmg
elif [ "$OSX_VERS" -eq 10 ]; then
DMGURL=http://adcdownload.apple.com/Developer_Tools/Command_Line_Tools_OS_X_10.10_for_Xcode_6.3.2/commandlinetoolsosx10.10forxcode6.3.2.dmg
elif [ "$OSX_VERS" -eq 11 ]; then
DMGURL=http://adcdownload.apple.com/Developer_Tools/Command_Line_Tools_OS_X_10.11_for_Xcode_7.3.1/Command_Line_Tools_OS_X_10.11_for_Xcode_7.3.1.dmg
elif [ "$OSX_VERS" -eq 12 ]; then
DMGURL=http://adcdownload.apple.com/Developer_Tools/Command_Line_Tools_macOS_10.12_for_Xcode_8.1/Command_Line_Tools_macOS_10.12_for_Xcode_8.1.dmg
elif [ "$OSX_VERS" -eq 14 ]; then
DMGURL=https://download.developer.apple.com/Developer_Tools/Command_Line_Tools_for_Xcode_11_GM_Seed/Command_Line_Tools_for_Xcode_11_GM_Seed.dmg
elif [ "$OSX_VERS" -eq 15 ]; then
DMGURL=https://download.developer.apple.com/Developer_Tools/Command_Line_Tools_for_Xcode_12.2/Command_Line_Tools_for_Xcode_12.2.dmg
fi
curl "$DMGURL" -o "$TOOLS"
fi
TMPMOUNT=`/usr/bin/mktemp -d /tmp/clitools.XXXX`
hdiutil attach "$TOOLS" -mountpoint "$TMPMOUNT"
installer -pkg "$(find $TMPMOUNT -name '*.mpkg' -o -name '*.pkg')" -target /
hdiutil detach "$TMPMOUNT"
rm -rf "$TMPMOUNT"
rm "$TOOLS"
exit
  1. 把上面脚本保存为 install.sh
  2. 执行 sudo sh install.sh

实现思路

我们按照普通二分查找的方式获取中点,这个时候和普通有序数组有一个不一样的地方,有可能这个数组不是单调递增的。 1. 如果是单调递增的,按照普通二分查找的方式查找即可 2. 如果不是单调递增的,判断 value 是否在这个区间内,如果不在,返回 -1 即可。判断方法比较简单,如果 $value < $array[$low] 并且 $value > $array[$high] 那就说明不在该区间内(因为是循环有序,比如[5,6,1]里面查找2)。 3. 如果在这个区间内,还需要判断是否等于临界点,因为 $array[$low] 或者 $array[$high] 有可能等于 value,比如 [5, 6, 1] 里面查找 1

PHP 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
$arr1 = [4, 5, 6, 1, 2, 3];

function bsearch($array, $value)
{
$low = 0;
$high = count($array) - 1;

while ($low <= $high) {
$mid = intval(($low + $high) / 2);

if ($array[$low] <= $array[$high]) {
if ($value > $array[$mid]) {
$low = $mid + 1;
} else if ($value < $array[$mid]) {
$high = $mid - 1;
} else {
return $mid;
}
} else {
// 不是递增区间
if ($value == $array[$high]) return $high;
if ($value == $array[$low]) return $low;

if ($value > $array[$high] && $value < $array[$low]) {
return -1;
} else if ($value < $array[$high]) {
$high--;
} else {
$low++;
}
}
}

return -1;
}

var_dump(bsearch($arr1, 2));
0%