簡體   English   中英

根據登錄的用戶字段在哪里切換到其他服務?

[英]Where to switch to other service depending on logged user field?

在 laravel 9 app 我嘗試切換到不同的服務

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        if ($this->app->environment('local')) {
            $this->app->register(\Laravel\Telescope\TelescopeServiceProvider::class);
            $this->app->register(TelescopeServiceProvider::class);

            $this->app->register(\Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class);
        }
        
        // Error pointing at this line
        $loggedUser  = Auth::user();


        if( $loggedUser->membership_mark === 'G') { // G=>Gold Membership
            $this->app->bind('App\Interfaces\PageMembershipMarkStrategyInterface',
                'App\Implementations\PageGoldMemberStrategy');

        }
    }

但是我得到了錯誤:

 Target class [hash] does not exist. in...

當我需要登錄用戶時,注冊方法似乎不適合 app->bind。 但是我應該在哪里進行綁定呢? 在定制服務提供商中? 我是中間件?

修改塊:我用命令創建一個中間件:

php artisan make:middleware SetPageMembershipMarkService

在 app/Http/Kernel.php 中我添加了它:

protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,

    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,

    // I added this line : 
    \App\Http\Middleware\SetPageMembershipMarkService::class,

    'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,

但是我得到了錯誤:

Illuminate\Contracts\Container\BindingResolutionException: Target [App\Interfaces\PageMembershipMarkStrategyInterface] is not instantiable while building [App\Http\Controllers\InformOnPageInStockController]....

我不確定我必須在 Kernel.php 的哪個位置添加 ref 到 PageMembershipMarkStrategyInterface? 檢查日志似乎我的 SetPageMembershipMarkService 在錯誤之前沒有被觸發...

修改后的塊 2:

在文件 app/Http/Kernel.php 中,我添加了我的中間件參考:

protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,

    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,

    // I set it AFTER auth
    'setPageMembership' =>\App\Http\Middleware\SetPageMembershipMarkService::class,

    'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
    'can' => \Illuminate\Auth\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
    'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    'verified' => \Illuminat`enter code here`e\Auth\Middleware\EnsureEmailIsVerified::class,
];

abd 在路線/api.php 中:

Route::middleware('auth:api')->prefix('v1') /*->name('api.v1')*/ ->group(function () {
    Route::get('/user', function (Request $request) {
        return $request->user();
    });

    ...
    
    Route::middleware(['setPageMembership'])->group(function () {
        Route::resource('/inform-on-page-in-stock', InformOnPageInStockController::class)->except(['edit', 'add']);
   });

我仍然有錯誤:

Illuminate\Contracts\Container\BindingResolutionException: Target [App\Interfaces\InformOnPageInStockStrategyInterface] is not instantiable while building [App\Http\Controllers\InformOnPageInStockController]. 
  1. 檢查日志我沒有找到我在 SetPageMembershipMarkService 中間件中設置的日志消息,所以看起來它沒有在我的控制器之前設置...有什么問題嗎?

  2. 您提到了使用 RouteServiceProvider。 哪個是正確的語法?

文件app/Http/Middleware/SetPageMembershipMarkService.php有幾行:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Auth;

class SetPageMembershipMarkService
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse)  $next
     * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
     */
    public function handle(Request $request, Closure $next)
    {

        $loggedUser  = Auth::user();
        \Log::info(varDump($loggedUser, ' -1 SetPageMembershipMarkService $loggedUser::'));

        $membershipMark = $loggedUser->membership_mark;

        if( $membershipMark === 'S') { // G=>Silver Membership
            app()->bind('App\Interfaces\InformOnPageInStockStrategyInterface',
                'App\Implementations\HasNoInformOnPageInStockStrategy');
        }

        if( $membershipMark === 'G') { // G=>Gold Membership
            app()->bind('App\Interfaces\InformOnPageInStockStrategyInterface',
                'App\Implementations\InformOnPageInStockGoldMembersStrategy');
        }

        return $next($request);
    }
}

但是在日志文件中我沒有看到我在這個中間件中的任何日志消息......

謝謝!

您將無法在 Service Provder 中獲取Auth:user()數據。 因為服務提供商在 Laravel 設置Auth數據之前運行,所以您必須使用一些 hacky 方法來處理它。

我認為處理與auth相關的數據的更好方法是在中間件上而不是在服務提供商中。

可以在這個問題的答案Laravel 中找到其他解釋 - 如何在 AppServiceProvider 中獲取當前用戶

修改塊的編輯

您的中間件注冊錯誤。

$routeMiddleware這個數組用於注冊一個自定義中間件,你將使用它並手動定義

例如:

    protected $routeMiddleware = [
    .....
    // I added this line : 
    'setPageMembership' => \App\Http\Middleware\SetPageMembershipMarkService::class,

然后你要在你的路由組中使用這個中間件,比如:

Route::middleware(['auth', 'setPageMembership'])->group(function () {
    Route::get('test', [TestController::class, 'test']);
});

如果您希望中間件針對所有路由運行,最好將其添加到$middleware數組中,或者如果您想要在特定路由組 (web/api) 中,則在$middlewareGroups單獨的webapi數組中。

如果您希望每個路由都有中間件,則在 RouteServiceProvder 中添加中間件也可以。

但是,對於您的用例,綁定之前需要進行身份驗證。 因此,在執行這些綁定操作之前,您需要首先觸發auth中間件。 因此,像我上面顯示的那樣將中間件添加到您的路由文件中就足以滿足您的用例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM