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 中将类对象从一个控制器动作传递到不同的控制器动作
将数组从 AuthController 传递到 Laravel 5 中的登录视图