在 laravel 9 或 10 php 中向中间件响应添加自定义数据

问题描述 投票:0回答:1

我想实现一个用户跟踪系统,经过搜索我意识到我必须在中间件中做到这一点。我遇到的问题是我只能将值添加到中间件中答案中的响应标头。保存它们的信息后,在中间件响应中删除它们。请指导我如何将自定义数据添加到中间件响应中,谢谢

为此,我找到了 2 个在 json 模式下工作的示例,但如果我想将用户转移到路由,我必须使用标头。

json 响应示例代码:

return $response->json([
                    'status' => $status,
                    'code' => $code,
                    'errors' => [$errors],
                ], $status);
php laravel laravel-middleware
1个回答
0
投票

我在我的项目中做了完全相同的系统,但没有使用标头,请参阅下面的示例

例如: 我们计划为每个用户在软件中的表现创建一个跟踪系统,以便将其报告存储在系统中。

迁移:

Schema::create('user_trackings', function (Blueprint $table) {
            $table->id();
            $table->boolean('transaction')->default(1);
            $table->string('event');
            $table->string('class');
            $table->longText('request_params')->nullable();
            $table->string('request_method');
            $table->string('request_ip');
            $table->string('request_userAgent');
            $table->longText('params')->nullable();
            $table->foreignId('user_id')->constrained()->onUpdate('cascade')->onDelete('cascade');
            $table->timestamps();
            $table->softDeletes();
        });

角色控制器:

use App\Traits\Response;

class RoleController extends Controller
{
    use Response;

    public function store(Request $request)
    {
        $Validator = Validator::make($request->all(), [
            'display_name' => ['required', 'unique:roles,display_name', 'max:255'],
            'name' => ['required', 'unique:roles,name', 'persian_not_accept', 'max:255'],
            'permissions' => ['nullable', "array","min:1"],
            'permissions.*' => ['nullable', 'exists:permissions,name'],
            'parent' => [new ParentRule('roles,name')]
        ]);
        if ($Validator->fails()) {
            $this->Validation($Validator);
            return back();
        }

        DB::beginTransaction();
        try {
            $Role = Role::create([
                'name' => $request->name,
                'display_name' => $request->display_name
            ]);
            $Role->syncPermissions($request->permissions);
            if($request->parent != 'no-parent'){
                $RoleParent = Role::findByName($request->parent);
                $Role->parent()->associate($RoleParent);
                $Role->save();
            }

            DB::commit();
        } catch (\Exception $e) {
            DB::rollback();
            $this->Error([
                'Permission' => $Role,
                'Exception' => $e->getMessage()
            ]);
        }
        return $this->Success([
            'Permission' => $Role
        ], 'role.index');
    }

}

响应特征:

trait Response {
    use SweetAlert;

    public function Success($Params = [], $Route = null , $RouteParams = [], $title = null, $message = null){
        $title = is_null($title) ? __('message.response.title.Success') : $title;
        $message = is_null($message) ? __('message.response.message.Success') : $message;

        if($Route){
            return (new RedirectResponse(route($Route, $RouteParams)))->bag(true, $Params);
        }

        return (new HttpResponse)->json(['status' => true, 'message' => $message])->bag(true, $Params);
    }

    public function Error($Params = [], $Route = null , $RouteParams = [], $title = null, $message = null){
        $title = is_null($title) ? __('message.response.title.Error') : $title;
        $message = is_null($message) ? __('message.response.message.Error') : $message;

        if($Route){
            $this->AlertError( $title , $message );
            return (new RedirectResponse(route($Route, $RouteParams)))->bag(false, $Params);
        }

        return (new HttpResponse)->json(['status' => false, 'message' => $message])->bag(false, $Params);
    }

}

提示: 在中间件响应中,您将收到 2 种类型的响应,它们由 2 个类组成(Illuminate\Http\Response、Illuminate\Http\RedirectResponse),因此我们必须为此创建 2 个自定义类并扩展这 2 个类。

创建自定义响应:

1- 第一级:

namespace App\Library\Response;

use Illuminate\Http\RedirectResponse as BaseRedirectResponse;

class RedirectResponse extends BaseRedirectResponse {

    public $bag;

    public function bag($Status = null, $Data = null){
        $this->bag = (object) [
            'Status' => $Status,
            'Data' => $Data
        ];
        return $this;
    }
}

2- 第二类:

namespace App\Library\Response;

use Illuminate\Http\Response;

class HttpResponse extends Response {

    public $bag;

    public function bag($Status = null, $Data = null){
        $this->bag = (object) [
            'Status' => $Status,
            'Data' => $Data
        ];
        return $this;
    }
}

我们创建用户跟踪存储特征

namespace App\Traits;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;
use App\Models\UserTracking as ModelUserTracking;

trait UserTracking{

    public function Track($Transaction = true, $Params = []){
        DB::beginTransaction();
        try {
            $UserTracking = new ModelUserTracking;
            $UserTracking->transaction = $Transaction;
            $UserTracking->event = Route::currentRouteName();
            $UserTracking->class = Route::currentRouteAction();
            $UserTracking->request_params = json_encode(request()->all());
            $UserTracking->request_method = Route::current()->methods()[0];
            $UserTracking->request_ip = request()->ip();
            $UserTracking->request_userAgent = request()->userAgent();
            if(!empty($Params)): $UserTracking->params = json_encode($Params); endif;
            $UserTracking->User()->associate(Auth::user());
            $UserTracking->save();

            DB::commit();
        } catch (\Exception $e) {
            DB::rollback();

            Log::error("Insert User Tracking Data Error", [
                'UserTracking' => $UserTracking,
                'Exception' => $e->getMessage()
            ]);
        }
    }

}

现在我们开始构建自定义中间件

自定义中间件:

namespace App\Http\Middleware;

use Closure;
use App\Traits\UserTracking as TraitUserTracking;
use Illuminate\Http\Request;

class UserTracking
{
    use TraitUserTracking;
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure(\Illuminate\Http\Request): (\App\Library\Response\HttpResponse|\App\Library\Response\RedirectResponse)  $next
     * @return \App\Library\Response\HttpResponse|\App\Library\Response\RedirectResponse
     */
    public function handle(Request $request, Closure $next)
    {
        $response = $next($request);

        if(property_exists($response, 'bag'))
            $this->Track($response->bag->Status, $response->bag->Data);

        return $response;
    }
}

本指南的要点是,您应该创建响应的自定义类,并从 (Illuminate\Http\Response, Illuminate\Http\RedirectResponse) 类扩展它。通过这个技巧,您可以发送和处理任何您喜欢的值。祝你好运

© www.soinside.com 2019 - 2024. All rights reserved.