【问题标题】:Laravel - Initialize class only for specific routesLaravel - 仅为特定路线初始化类
【发布时间】:2018-06-22 17:13:37
【问题描述】:

在我的应用中,我有一组路线需要在调度之前进行一些引导。

为了说明情况:

有一个带有前缀“app”的特殊路由组。所有这些路线也都有一些参数:

site.dev/app/index?age=11&else=af3fs4ta21

如果没有这些参数,用户不应该被允许访问路由。我通过创建一个简单的路由中间件来完成它。

if (!$request->exists('age') || !$request->exists('else')) {
        return redirect('/');
}

下一步是初始化一个将路由参数作为构造参数的类。然后参数“else”被用作数据库调用的参数。我需要从 /app 路由组访问每个路由中的此类。

为了实现我尝试设置服务提供者:

public function register()
{
    $this->app->singleton(Dual::class, function ($app) {
        return new Dual($this->app->request->all());
    });
}

然后我创建了一个特殊的控制器扩展 BaseController 并将 Dual 类传递给它的构造函数。

class DualController extends Controller
{
    public function __construct(Request $request, Dual $dual)
    {
        $this->middleware(\App\Http\Middleware\DualMiddleware::class);

        $this->dual = $dual;
    }
}

然后每个控制器都在扩展 DualController 并通过 $this->dual->method() 访问 Dual 类。

如果路由参数在他们的位置并且数据库中已经有一行,它就可以工作。

问题

这个中间件在 ServiceProvider 和 DualController 初始化类 Dual 之后执行。所以,中间件并没有真正起作用。如果路由参数不存在,它将失败。

此外,如果由于某种原因数据库中没有必需的行,则不会初始化 Dual 类(因为它取决于对 db 的调用)并且整个应用程序将崩溃,说我正在尝试对 null 执行操作。

期望的行为

首先检查路由是否存在参数。

其次,检查 db 中是否存在带有路由键的行。

第三 - 尝试初始化 Dual 类并将其传递给路由组 /app 使用的所有控制器。

如果任何步骤失败 -> 显示正确的消息。

部分双班:

class Dual
{
    protected $client = null;
    public $config = [];

    public function __construct($config)
    {
        $this->config = $config;
        $this->bootstrap();
    }

    public function getEli()
    {
        $eli = Eli::where(['else' => $this->config['else']])->first();
        return $eli;
    }

    public function instantiateClient()
    {
        $client = Client::factory(Client::ADAPTER_OAUTH, [
            'entrypoint' => $this->getEli()->eli_url,
            'client_id' => '111',
            'client_secret' => '111',
        ]);

        $client->setAccessToken($this->getEli()->accessToken()->first()->access_token);

        return $client;
    }

    public function getClient()
    {
        if ($this->client === null)
        {
            throw new \Exception('Client is NOT instantiated');
        }

        return $this->client;
    }

    public function bootstrap()
    {
        $this->client = $this->instantiateClient();
    }

【问题讨论】:

  • 为什么不能检查用户是否被允许进入中间件?
  • @AlexeyMezenin 如果您所说的用户是指已注册和登录的用户 - 这个应用程序中没有这样的东西,也不会。我试图检查 params 以及中间件中的 DB 中是否存在这样的模型,但只要 laravel 在控制器中构造和初始化类 Dual 后执行路由中间件,它就不会工作。
  • 尝试将其作为路由中间件在app/Http/Kernel.php 中添加一个键,然后在您的路由文件->middleware('something') 中定义它
  • @ahmad 感谢您的回复。起初我尝试过,仍然 - 中间件在服务提供者之后执行。另一方面,全局中间件工作正常(第一个中间件然后构造),但是全局是全局的,阻止了应用程序中的所有其他路由。
  • @AlexeyMezenin 我已经更新了导致问题的双重类的部分问题。问题主要出在 getEli()->accessToken() 部分,因为它尝试在 null 上执行它。

标签: php laravel laravel-middleware service-provider


【解决方案1】:

您可以在中间件中执行此操作:

$isElseExists = Model::where('else', request('else'))->first();
if (request('age') && request('else') && $isElseExists) {
    return $next($request);
} else {
    return back()->with('error', 'You are not allowed');
}

如果一切正常,控制器方法将被执行。然后你就可以注入Dual 类而无需任何额外的逻辑。

如果出现问题,用户将被重定向到之前的 URI,并在会话中闪现错误消息。

【讨论】:

  • 是的,问题是由于某种原因控制器方法在这个中间件之前执行。
  • 如果你检查一切都是中间件并且不允许用户访问路由,那么控制器方法中的逻辑将不会被执行。
  • 即使我在中间件中执行 dd() 或 exit() 或其他任何操作,控制器 __construct 中的逻辑也会首先执行。我想它的工作方式是:->创建控制器类->检查中间件->检查控制器中的指定方法?
  • @ficus 你问过一种方法。您可以从构造函数中移动逻辑并在控制器方法中解析类。另外,如果Dual 类会被注入,为什么会很糟糕?
  • @ficus 你可以绑定类并在所有控制器、视图、模型等中全局执行app('dual')->instantiateClient()
猜你喜欢
  • 2012-05-04
  • 1970-01-01
  • 2020-05-14
  • 1970-01-01
  • 1970-01-01
  • 2023-02-04
  • 2020-05-12
  • 2021-03-01
  • 1970-01-01
相关资源
最近更新 更多