在回答社群中,我提問了這個問題 :Laravel 的表單驗證 , 如何做到驗證並改變 ( 轉換 ) 資料 ?
最終,我找到了一種使用中介軟體的方法 ,這種方法比驗證的同時並轉換更好 。
注意 :所針對的是非路由引數 。
首先,先看看 Laravel 的 2 箇中介軟體 :TrimStrings 和 ConvertEmptyStringsToNull
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
// 此中介軟體繼承了 TrimStrings 中介軟體基類
class TrimStrings extends Middleware
{
protected $except = [
'password',
'password_confirmation',
];
}
// 找到 TrimStrings 中介軟體基類
namespace Illuminate\Foundation\Http\Middleware;
class TrimStrings extends TransformsRequest
{
protected $except = [
//
];
// 重要方法
protected function transform($key, $value)
{
if (in_array($key, $this->except, true)) {
return $value;
}
// 這裡已經寫的很清楚了
return is_string($value) ? trim($value) : $value;
}
}
ConvertEmptyStringsToNull 中介軟體同理,就不上程式碼了 。
我們完全可以模仿這個中介軟體的寫法,構造我們自己的中介軟體,去做一些引數的 “ 預轉換 ” ,下面上程式碼 :
class ConvertNumericStringsToInt extends TransformsRequest
{
/**
* The attributes that should not be trimmed.
*
* @var array
*/
protected $except = [
//
];
/**
* Transform the given value.
*
* @param string $key
* @param mixed $value
* @return mixed
*/
protected function transform($key, $value)
{
$transform = false;
if ($key === 'id') {
// 引數為 id
$transform = true;
} else if (1 === preg_match('/^[a-zA-Z][0-9a-zA-Z]*_id$/', $key)) {
// 引數為 *_id
$transform = true;
} else if (1 === preg_match('/^[a-zA-Z][0-9a-zA-Z]*Id$/', $key)) {
// 引數為 *Id
$transform = true;
}
if ($transform) {
if (!is_numeric($value)) {
// 我自己做的處理,會直接丟擲異常,不會再向下進行
return responseJsonOfFailure([], 4444, $key . '引數必須是整數');
}
return is_numeric($value) ? intval($value) : $value;
}
// 返回原值
return $value;
}
}
我在這個中介軟體中處理所有名稱中有 id 的引數 ,如果引數符合並且不是數字就丟擲異常 ,如果引數符合並且是數字( 此時還是字串 ) 就強轉為 int 型別 ,之後程式中就不用做任何強轉了。
同理很多情況下,我們如果想對引數做任何的預處理,都可以使用這種方法 ,我們可以根據實際情況,決定如何設定這些 “ 引數預轉換中介軟體 ” 的作用域範圍 。