Laravel10 中间件 如何过滤空和NULL参数?

1. 运行环境

1). 当前使用的 Laravel 版本?

Laravel 10

2. 问题描述?

如何在 Middleware 中进行参数过滤,并在控制器中获取到过滤后的参数?
在 Middleware 中过滤参数后,打印 $request->all() 是成功过滤后的参数,但在控制器里再次打印 $request->all(),又变成了过滤前的参数。

提交参数

[
    'login_name' => 'test - 1',
    'real_name' => 'test - 2',
    'describe' => '',
]

Middleware 与 Controller 输出结果

Middleware 断点输出
Array
(
    [login_name] => 'test - 1'
    [real_name] => 'test - 2',
)

Controller 断点输出
Array
(
    [login_name] => 'test - 1'
    [real_name] => 'test - 2',
    [describe] => '',
)

Middleware 代码

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class FilterParameter
{
    public function handle(Request $request, Closure $next): Response
    {
        $request = collect($request)->filter(function ($request) {
            return $request != '' && !is_null($request);
        });

//        print_r($request->all());exit();

        return $next($request);
    }
}

3. 您期望得到的结果?

在控制器中获取过滤后的参数

4. 解决方案

public function handle(Request $request, Closure $next): Response
    {
        $parameter = $request->all();
        foreach ($parameter as $key => $value) {
            if ($value == '') {
                // 成功从 $request->all() 中删除了参数
                $request->query->remove($key);
            }
        }

        return $next($request);
    }

此前尝试了

$request->replace();
$request->offsetUnset();
$request->except();

等各种方法,但在控制器中依旧能获取被删除的参数,最后跟了下 $request->all() 源码,发现是从 $this->input()里拿的参数。

$input = array_replace_recursive($this->input(), $this->allFiles());

于是又跟了下 $this->input(),看到 $this->query->all()

 $this->getInputSource()->all() + $this->query->all(), $key, $default

最后尝试从 $this->query 里删除,结果成功了。

《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
最佳答案

因为

 $request = collect($request)->filter(function ($request) {
            return $request != '' && !is_null($request);
        });

这段代码改变了,Request类的属性了

laravel 有个 \Illuminate\Foundation\Http\Middleware\TrimStrings 中间件专门过滤参数值的空格,你可以参照这个中间件修改成自己的业务需求,而且它可以过滤多维数组的参数,完全满足你的需求

9个月前 评论
讨论数量: 5

因为

 $request = collect($request)->filter(function ($request) {
            return $request != '' && !is_null($request);
        });

这段代码改变了,Request类的属性了

laravel 有个 \Illuminate\Foundation\Http\Middleware\TrimStrings 中间件专门过滤参数值的空格,你可以参照这个中间件修改成自己的业务需求,而且它可以过滤多维数组的参数,完全满足你的需求

9个月前 评论

你可以在表单验证类里面处理这部分逻辑,表单验证《Laravel 10 中文文档》

use Illuminate\Support\Str;

/**
 * 准备验证数据。
 */
protected function prepareForValidation(): void
{
    $this->merge([
        'slug' => Str::slug($this->slug),
    ]);
}
use Illuminate\Support\Str;

/**
 * Handle a passed validation attempt.
 */
protected function passedValidation(): void
{
    $this->replace(['name' => 'Taylor']);
}
9个月前 评论
徵羽宫 (作者) 9个月前

这里有两个问题:

  1. $request = collect($request)->filter(function ($request) {
       return $request != '' && !is_null($request);
    });

这里不能直接把通过 collect 方法处理后的结果重新赋值给 $request 对象,因为 $request 对象还要作为上下文进行传参,其类型不可改变。这里需要处理的仅仅是 $request 对象的参数部分。

  1. 中间件处理完请求参数以后如果想覆盖原本的请求参数部分,需要调用 $request->replace() 进行替换,逻辑如下:
// 参数处理
$parameter = collect($request)->filter(function ($request) {
    return $request != '' && !is_null($request);
})->toArray();

// $request 对象参数替换
$request->replace($parameter);

return $next($request);
9个月前 评论

collect() 返回 Collection 对象,非 $request 对象,不过它也有个 all 方法。删除一个参数有点复杂。可以用 FormRequest,$request->validated() 返回过滤后的参数。

9个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!