Laravel 4:将模型从过滤器传递到控制器动作

Posted

技术标签:

【中文标题】Laravel 4:将模型从过滤器传递到控制器动作【英文标题】:Laravel 4: Pass model from filter to controller action 【发布时间】:2014-10-19 20:54:11 【问题描述】:

我的应用程序有 3 种不同的场景:

    只有授权用户才能访问控制器操作 控制器操作仅供非授权用户访问 任何用户都可以访问控制器操作,但已完成身份验证检查

前两个场景由简单的过滤器处理,由于所有场景在逻辑上都相似,看来其余场景也应该由过滤器处理。

所以,我想做的是: 当用户访问某些特定的控制器操作(即HomeController@getIndex)时,过滤器应检查用户是否被授权,将控制器的$user 属性设置为Auth::user() 值并在所有视图之间共享此值。这是我想出的代码:

Router::filter('auth', function() 
    $route = Str::parseCallback(Route::currentRouteAction(), null); // 0 - controller name, 1 - controller action name

    $controller = App::make($route[0]);

    $user = Auth::user();
    $controller->user = $user;
    View::share('user', $user);

    return $controller->$route[1]();
);

此代码有效,但是控制器被调用了两次(即当控制器操作没有 return 构造时),并且 auth 过滤器在调用任何其他 'before' 过滤器之前调用控制器。

第二种解决方案: 创建AuthController,并使用它的构造函数设置$user 属性,但是将为每个子控制器操作调用构造函数(我只想在特定操作上运行它,所以我认为过滤器是要走的路)。

第三种解决方案: 创建UserRepository 并编写一个方法,该方法将执行所有身份验证内容,并从需要身份验证的操作中调用它(不设置$user 属性)。对于几行代码,这种解决方案似乎有点过头了。

第四个解决方案:Auth::user() 值直接传递给控制器​​操作(作为参数),但我还没有找到任何方便的方法。

是否有任何一种“最佳实践”解决方案来以所述方式处理身份验证? 有没有其他方法可以解决这个问题?

【问题讨论】:

当您使用App::make() 实例化您的控制器时,您是否设置了服务提供商?您是否有理由不能在控制器中使用自动依赖注入?如果您只想将经过身份验证的用户模型传递给您的所有视图,为什么不直接使用View::share('user', Auth::user()); @user3158900 不,我没有任何控制器的自定义服务提供商。 “有没有理由你不能在你的控制器中使用自动依赖注入” - 这部分我不清楚。你能举个例子吗?是的,我想在视图之间共享变量并且(设置控制器属性或以任何其他方式将变量传递给特定(不是每个)控制器操作) 【参考方案1】:

最佳实践可能是为每个将注入用户存储库的控制器创建一个 UserRepository 类和服务提供者,但就像你说的那样,对于一些简单的事情来说可能有点矫枉过正。

也许更简单的解决方案是向 BaseController.php 添加一个设置用户的函数。

public function setUser()

    $this->user = Auth::user();

然后,当您需要设置用户时,只需调用$controller->setUser();。如果您总是需要控制器来执行此操作,只需在构造函数中调用$this->setUser(),这样它就始终可用。

【讨论】:

我没想过这种方式可以达到预期的效果。您的解决方案非常简单,但解决了问题。我想我应该朝这个方向前进,并使用current 方法扩展User 模型(如$user = User::current())。明天去试试。谢谢!【参考方案2】:

感谢@user3158900,我做了一些研究并提出了另一个解决方案。 由于将expose 方法放在User 模型中有点不直观,因此扩展授权外观似乎是正确的。

这是我的最终解决方案:

在 app/extensions/Auth/ 目录下创建一个 Guard 类。这个类扩展了 Laravel 原生的 Illuminate\Auth\Guard 类。

<?php namespace Extensions\Auth;

class Guard extends \Illuminate\Auth\Guard 

    public function exposeUser() 
        $user = \Auth::user();

        \View::share('user', $user);

        return $user;
    


在 app 目录下创建一个 extensions.php 文件,并将该文件包含在 app/global/start.php 中。

require app_path().'/filters.php';
require app_path().'/extensions.php';

新的 extensions.php 文件包含以下代码(此代码添加了新的身份验证驱动程序):

Auth::extend('eloquent+', function() 
    return new \Extensions\Auth\Guard(
        new \Illuminate\Auth\EloquentUserProvider(App::make('hash'), \Config::get('auth.model')),
        App::make('session.store')
    );
);

将身份验证配置的 (app/config/auth.php) $model 属性设置为 'eloquent+'(这使得我们的身份验证使用 'eloquent+' 作为身份验证驱动程序)。

修改 composer.json 以反映新的自动加载类映射。

"autoload": 
    "classmap": [
        "app/commands",
        "app/controllers",
        "app/models",
        "app/database/migrations",
        "app/database/seeds",
        "app/tests/TestCase.php",
        "app/extensions"
    ]
,

最后运行composer dump-autoload

现在您可以像往常一样使用您的 Auth::user() 和其他身份验证方法,此外,我们可以在视图之间共享模型并通过任何操作访问它,只需在我们的控制器操作中调用 Auth::exposeUser()

如果能得到一些关于这种方法的反馈也很好。

【讨论】:

以上是关于Laravel 4:将模型从过滤器传递到控制器动作的主要内容,如果未能解决你的问题,请参考以下文章

在 RAILS 中将模型从一个控制器动作传递到另一个控制器动作的替代方法

在 ASP.net MVC 4 中将类对象从一个控制器动作传递到不同的控制器动作

Laravel 将参数从路由传递到过滤器

将数组从 AuthController 传递到 Laravel 5 中的登录视图

如何:在 Laravel 4 中将数据从控制器传递到 JavaScript?

如何使用 axios 将数组从 javascript 传递到 laravel 控制器