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

时间:2014-08-26 13:44:38

标签: php authentication laravel filter controller

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

  1. 仅授权用户可以访问控制器操作
  2. 仅限非授权用户可以访问控制器操作
  3. 任何用户均可访问控制器操作,但已完成身份验证
  4. 前两个场景由简单的过滤器处理,并且由于所有场景在逻辑上都相似,所以剩下的场景似乎也应该由过滤器处理。

    那么,我想做什么: 当用户访问某些特定的控制器操作(即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并编写一个方法,该方法将执行所有auth内容,并从需要auth(不设置$user属性)的操作中调用它。对于几行代码来说,这个解决方案似乎有点过头了。

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

    是否有任何"最佳做法"以描述的方式处理auth的解决方案? 有没有其他方法可以解决这个问题?

2 个答案:

答案 0 :(得分:1)

最佳做法可能是为每个注入用户存储库的控制器创建一个UserRepository类和服务提供程序,但就像你说的那样,可能有些过于简单。

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

public function setUser()
{
    $this->user = Auth::user();
}

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

答案 1 :(得分:1)

感谢@ 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驱动程序):

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

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

修改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方法,此外我们可以在视图之间共享模型,并通过在控制器操作中调用Auth::exposeUser()的任何操作来访问它。

获得有关此方法的一些反馈也很好。