【问题标题】:User in Laravel controllersLaravel 控制器中的用户
【发布时间】:2017-10-15 09:33:21
【问题描述】:

我在 laravel 5.3 中有一个系统,它使用了 40 多个控制器和可能有 200 个视图。

我正在尝试清理代码并使用最佳实践。鉴于某些调用几乎无处不在,因此将其定义为“半全局”的某个地方是有意义的。我假设这将在所有控制器扩展的Controller 中。

一个对象是$user,并且有子$user->organisations$user->organisation->locations

以基本控制器(或等效)方式加载它也会给我一个优势,即我可以确保以最佳方式急切加载子关系,确保任何foreach 样式代码永远不会导致多个小型数据库查找。还有许多其他的项目我想这样做,对数据库优化有类似的影响。这些都使用Auth::user(),它们会影响子对象的权限。

鉴于有大约 20 个要共享的属性/变量(全部依赖于 Auth::user()),从几乎所有方法中删除这些重复的代码是一个巨大的改进。

我的目标是能够从任何控制器引用$this->user,并且已经预加载了所有子/相关对象。

Laravel 5.3 重新组织了加载顺序,因此将登录的用户数据作为Controller::__construct 的一部分共享不再可行。

这是目前尝试的代码:

Controller::__construct

$this->middleware(function ($request, $next) {
           $this->user = Auth::user();
           view()->share('user', $this->user);

            return $next($request);
    });

不出所料,这在视图级别正确设置了$user 变量,但不是控制器级别。虽然我在视图级别执行 $user ,但这并没有帮助。

鉴于要共享大约 20 个使用属性/变量(全部依赖于 Auth::user()),我决定至少由一个 Helper 将其移动到一个集中位置。我将助手实例化为所有控制器的属性:$this->authentication_helper

在示例控制器中:SearchController

public function index(Request $request): View
{
    $this->authentication_helper->getAuthenticationData($this);
    //... logic for the search
}   

AuthenticationHelper 正在做(除其他外):

public function getAuthenticationData(Controller $controller) : void
{
    $user = Auth::user();
    $controller->user = User::with(
        organisations.locations', // .. other children .. //
    )->find($user->id);
    // share to the view
    View::share('user', $controller->user);
    // ... other $controller property setting
    return;
}

我不确定这是否是最佳做法。 edit - 先前提出的第二个问题已解决 - 主要问题仍然存在:

这种方法是否存在问题 - 将这 20 个左右的变量赋值移动到更高级别的等效方法是什么。

【问题讨论】:

  • 您也可以在控制器和视图中直接使用全局变量auth()->user()。因此,您不需要在 40 个控制器和更多方法中声明变量 $user = Auth::user();。和 $this->user->organisations 可以替换为 auth()->user()->organizations 但是,它不会帮助急切加载。
  • 不正确 - 该函数使用以下内容返回 null:public function __construct() { $user = auth()->user(); var_dump($user); exit; }
  • 那么请求很可能不是来自经过身份验证的用户。
  • 是的。我以管理员身份登录。我已通过身份验证。如果您在控制器方法中运行Auth:user(),它会按预期工作,只是不在构造函数中(5.3+ laravel 更改并且按预期工作)。
  • 如果view()->share('user', $this->user);导致$user 出现在您的视图中,这将导致我认为它正在工作。首先,我建议在$this->user = Auth::user(); 下方添加dd($this->user);,如果您确实获得了身份验证用户实例,那么我会检查您是否在设置后没有在其他地方更改$this->user

标签: laravel authentication controller laravel-5.3


【解决方案1】:

您可以使用 Laravel DI 在控制器中获取授权用户,只是您的代码应该是这样的

YourControlle extends Controller
{
     public function test(Request $request)
    $user = $requset->user(); //use auth user 

} 

【讨论】:

  • 这很有趣,但对主要问题没有帮助:我想通过构造函数内的帮助程序使用 20 个变量全局执行此操作。
【解决方案2】:

最好的方法是一个助手(或多个助手,您可以为此创建一个 app\Helpers 命名空间)并将所有逻辑都包含在其中。
Auth::user() 可以使用 Auth 外观从那个助手访问,并在那里有你的逻辑。 另一种更简单的方法是从您制作的自定义基本控制器(您将从 Controller 扩展)扩展您的控制器,并将 $user 成员附加到它并具有受保护的可见性,然后共享它到视图中,在构造函数或通过parent::magicMethod()调用的方法中完成

编辑
可以覆盖控制器类使用的callAction方法

/**
 * Execute an action on the controller.
 *
 * @param  string  $method
 * @param  array   $parameters
 * @return \Symfony\Component\HttpFoundation\Response
 */
public function callAction($method, $parameters)
{
    // insert your logic here
    return call_user_func_array([$this, $method], $parameters);
}

您无法通过构造函数访问 Auth 的原因是会话尚未启动。当它使用此事件侦听器时,您可以捕获它:

    Event::listen(Authenticated::class, function ($event) {
        $this->user = $event->user;
    });

未测试

带有闭包的中间件也可以完成这项工作。让它有你的逻辑,并在你所有的控制器中使用它。

【讨论】:

    猜你喜欢
    • 2015-10-13
    • 2020-07-07
    • 2018-01-24
    • 1970-01-01
    • 2017-04-26
    • 2017-02-12
    • 1970-01-01
    • 2017-08-30
    • 2021-09-26
    相关资源
    最近更新 更多