【问题标题】:Laravel how do I get info from several Controllers into ONE viewLaravel 如何从多个控制器中获取信息到一个视图中
【发布时间】:2018-09-26 03:20:58
【问题描述】:

我正在使用 Laravel 构建一个应用程序。它的结构如下:

一个用户 -> haOne -> 个人资料 -> hasMany -> 讨论 -> HasMany -> 回复 HasMany -> 赞

像往常一样,每个模型都有一个具有典型 CRUD 功能的控制器:DiscussionController、PaymentController、ImageController、ProfileController、RoleController、PostsControllers、MessageController。

在管理区域中,我管理和查看每个用户的所有相关信息。

web.php中的路由是:

Route::resource('admin-profiles', 'AdminProfileController');

我的问题出在 admin.profiles.show 视图中,该视图由该方法 AdminProfileController@show 提供:

public function show($slug)
{
    $profile = Profile::where('slug', $slug)->first();
    $page_name = $profile->name;

    return view('admin.profiles.show', compact('profile', 'page_name'));
}

在这里,我需要有关用户的所有信息(个人资料、讨论、帖子的答案、图片、喜欢、付款、频道等)。

我可以在 AdminController 中构建一个 GIANT show 方法并将一大堆变量传递给该视图,如下所示:

    $discussions = Discussion::where('profile_id', $profile->id)get);
    $replies= Reply::where('profile_id', $profile->id)->paginate(4);
...
    and so on until 27 queries

但在我看来这是一个糟糕的解决方案,因为我已经为每个模型配备了一个控制器。

我确实像这样调用了 UserController:

    <span class="mt-3 small pull-right">
Accumulated Likes: {{ $user->profile->all_likes($user->id) }}
</span>

在 userController 中我做了:

public function all_likes($id) {

    $user = User::find($id);
    $profile = Profile::where('user_id', $user->id);
    $discussions = Discussion::where('profile_id', $profile->id)->get();
    $replies = array();
    $all_likes = "";
    foreach ($discussions as $discussion) {
        foreach ($discussion->replies as $reply) {
            $all_likes = $all_likes + count($reply->likes);
        }
    }

    return $all_likes;
}

但它不起作用。

如何在 HTML 视图中调用不同控制器中的方法?

【问题讨论】:

  • {{ WhatController::public_staticFunction() }}
  • @Amarnasan,感谢您的回答,但是如何从 HTML 视图中调用“whateverController”?因为我收到错误:未定义的变量:all_likes(查看:...\views\admin\users\show.blade.php)。另一方面,这意味着我必须将所有控制器中的所有方法都设为静态?
  • {{ \App\Http\Controllers\WhateverController::public_staticFunction() }}。控制器只是另一个类。如果你想访问它的方法,你需要实例化它或者调用静态方法。

标签: laravel model-view-controller


【解决方案1】:

如果你的一切都建立在关系之上,那么就使用它们

一个用户 -> hasOne -> Profile -> hasMany -> Discussions -> HasMany -> Replies -> HasMany -> Likes

一个用户 -> hasOne -> 个人资料

在用户模型中:

public function profile()
{
  return $this->hasOne(ProfileModel::class);
}

在控制器中:

$user->profile;

在 ProfileModel 中:

public function discussions()
{
  return $this->belongsToMany(DiscussionsModel::class, ... youre fields);
}

//类似下面的关系回帖

在控制器中:

$profile->discussions;

$user->profile; //it's Collections relationships one by one
$user->profile->discussions; //it's Collections relationships hasMany
$user->profile->discussions->first()->replies; //replies to first user discussions. you can go foreach. and so on

并且在视图中:

控制器

public function show(int $id)
{
    $user = UserModel::find($id);

    return view('admin.profiles.show', [
      'user' => $user
    ]);
}

查看

<body>
    {{ $user->profile; }} 
    {{ $user->profile->discussions; }}
    {{ $user->profile->discussions->first()->replies; }}
</body>

【讨论】:

  • 我的问题是关于 HTML 的。如何将所有这些变量从不同的控制器中获取到单个视图中。因为我需要一个视图中的所有内容。我已经建立了所有的关系。我可以毫无问题地获取控制器中的所有信息。我的问题是如何从 HTML 调用该信息
  • 也许我无法解释自己。问题是我如何调用该函数(在您的示例 SHOW 中)。因为我需要在不同的控制器(在 DiscussionController、PaymentController、ImageController、ProfileController、RoleController、PostsControllers、MessageController 等)中调用几个自定义函数来提供我的管理仪表板。最终,我将在不同的控制器中拥有多个具有相同名称的函数。如果我只是以 {{ $variable }} 为例,我会收到一条消息错误:未定义变量:all_likes (View:....)
【解决方案2】:

最好的方法是使用资源和集合。

例如您可以使用以下命令为用户创建资源:

php artisan make:resource UserResource
php artisan make:resource UserCollection

然后你将它包含到你的控制器中,像这样导入它:

使用 App\Http\Resources\UserCollection;

在您的方法中,您可以返回如下内容:
return new UserCollection(User::all());

最后第二步是确保您在模型中正确定义了关系:

例如,在用户模型中:

public function discussions() {
   return $this->hasMany(Discussion::class);
}
public function profile() {
   return $this->belongsTo(Profile::class);
}

最后一步是在你的资源中调用这个关系,所以在你的资源中,你会像这样返回:

return [
    'id' => $this->id,
    'profile' => $this->profile, // model relationship
    'discussions' => $this->discussions, // model relationship
];

使用此方法,您可以为用户获取所有需要的关系。

最后,最佳做法是使用 whenLoaded 来处理资源中的关系:

return [
    'id' => $this->id,
    'profile' => $this->whenLoaded('profile'),
    'discussions' => $this->whenLoaded('discussions'),
];

只有在控制器内部使用 with() 时,它才会加载讨论和配置文件:

return new UserCollection(User::with('discussions')->with('profile')->get());

这也可以防止不必要的循环,例如 用户->讨论->用户....等

希望这会有所帮助,祝你的项目好运:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-29
    • 2020-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多