前提・実現したいこと
Cloud9でLaravel 5.1 LTSを用いてTwitterクローンを開発しています。
現在、以下の2点を同時に実現しようとしているところですが、どちらかを実現させるともう片方が実現できないという状態で、対処法が分からない状況です。
- DBのUsersテーブル上に存在する全ユーザー一覧のページを表示
- ログインしたユーザーが自分のプロフィールページにアクセスするためのリンクをナビバーに設置
発生している問題・エラーメッセージ
1.を実現した場合のエラーメッセージ(ナビバーの"My profile"をクリックした時):
1/1
FatalErrorException in UsersController.php line 26:
Call to a member function microposts() on a non-object
※ナビバーに設置したログインユーザーのプロフィールページへのリンクは ワークスペース名.c9users.io:8080/users/userのid
となるべきですが、 ワークスペース名.c9users.io:8080/users/%7Busers%7D
となってしまいます。
アドレスバーに直接 ワークスペース名.c9users.io:8080/users/1
等と入力してアクセスすると正常に目当てのページが表示されます。
2.を実現した場合:
/microposts/resources/views/commons/navbar.blade.php
の20行目の link_to_route()
に渡している第3引数を削除すると、ナビバーに設置したログインユーザーのプロフィールページへのリンクが正常に ワークスペース名.c9users.io:8080/users/1
等になり、目当てのページにアクセスできるようになりますが、この場合、1.が実現できなくなります。
ワークスペース名.c9users.io:8080/usersにアクセスした時のエラーメッセージ:
4/4
ErrorException in 2a5576d3a3140862ca55ac1bbbf9bb65 line 20:
Undefined variable: user (View: /home/ubuntu/workspace/microposts/resources/views/commons/navbar.blade.php) (View: /home/ubuntu/workspace/microposts/resources/views/commons/navbar.blade.php) (View: /home/ubuntu/workspace/microposts/resources/views/commons/navbar.blade.php)
3/4
ErrorException in 2a5576d3a3140862ca55ac1bbbf9bb65 line 20:
Undefined variable: user (View: /home/ubuntu/workspace/microposts/resources/views/commons/navbar.blade.php) (View: /home/ubuntu/workspace/microposts/resources/views/commons/navbar.blade.php)
2/4
ErrorException in 2a5576d3a3140862ca55ac1bbbf9bb65 line 20:
Undefined variable: user (View: /home/ubuntu/workspace/microposts/resources/views/commons/navbar.blade.php)
1/4
ErrorException in 2a5576d3a3140862ca55ac1bbbf9bb65 line 20:
Undefined variable: user
ヒントになりそうなこと
UsersController.php の index()
に以下を追記すると1.と2.を両方とも実現することができます。
public function index()
{
$users = User::paginate(10);
$user = User::find(2); // 追記。 動作確認としてidを直接指定。$userにログインユーザーのidを代入することができれば実現可能?
return view('users.index', [
'users' => $users,
'user' => $user, // 追記。ユーザー一覧ページのviewに渡す
]);
}
試したこと
UsersController.php の show(){}
の様に、
public function index($id)
{
$users = User::paginate(10);
$user = User::find($id);
return view('users.index', [
'users' => $users,
'user' => $user,
]);
}
とすれば index.blade.php にログインユーザーの情報を渡すことができるのではないかと思ったのですが、それをすると Missing Argument エラーが出てしまいます。
1/1
ErrorException in UsersController.php line 14:
Missing argument 1 for App\Http\Controllers\UsersController::index()
該当のソースコード
※GitHubで下記以外のファイルのコードもご確認頂けます。
https://github.com/KIYZ/sns
/microposts/resources/views/commons/navbar.blade.php
<header>
<nav class="navbar navbar-inverse navbar-static-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">Microposts</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
@if (Auth::check())
<li>{!! link_to_route('users.index', 'Users') !!}</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{{ Auth::user()->name }} <span class="caret"></span></a>
<ul class="dropdown-menu">
<li>{!! link_to_route('users.show', 'My profile', ['id' => $user->id]) !!}</li>
<li>{!! link_to_route('micropost.favorites', 'Favorites') !!}</li> <!--TODO-->
<li role="separator" class="divider"></li>
<li>{!! link_to_route('logout.get', 'Logout') !!}</li>
</ul>
</li>
@else
<li>{!! link_to_route('signup.get', 'Signup') !!}</li>
<li>{!! link_to_route('login.get', 'Login') !!}</li>
@endif
</ul>
</div>
</div>
</nav>
</header>
/microposts/app/Http/Controllers/UsersController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\User;
class UsersController extends Controller
{
public function index()
{
$users = User::paginate(10);
return view('users.index', [
'users' => $users,
]);
}
public function show($id)
{
$user = User::find($id);
$microposts = $user->microposts()->orderBy('created_at', 'DESC')->paginate(10);
$data = [
'user' => $user,
'microposts' => $microposts,
];
$data += $this->counts($user);
return view('users.show', $data);
}
public function followings($id)
{
$user = User::find($id);
$followings = $user->followings()->paginate(10);
$data = [
'user' => $user,
'users' => $followings,
];
$data += $this->counts($user);
return view('users.followings', $data);
}
public function followers($id)
{
$user = User::find($id);
$followers = $user->followers()->paginate(10);
$data = [
'user' => $user,
'users' => $followers,
];
$data += $this->counts($user);
return view('users.followers', $data);
}
public function favorites($id)
{
$user = User::find($id);
$microposts = $user->microposts()->orderBy('created_at', 'desc')->paginate(10);
$favorites = $user->favorites()->orderBy('created_at', 'desc')->paginate(10);
foreach ($microposts as $micropost) {
if ($micropost->id === $favorites->user_id) {
$favorite_microposts = $micropost;
}
}
$data = [
'user' => $user,
'microposts' => $microposts,
'favorites' => $favorites,
'favorite_microposts' => $favorite_microposts,
];
$data += $this->counts($user);
return view('users.favorites', $data);
}
}
/microposts/app/Http/routes.php
<?php
Route::get('/', 'WelcomeController@index');
// ユーザー登録
Route::get('signup', 'Auth\AuthController@getRegister')->name('signup.get');
Route::post('signup', 'Auth\AuthController@postRegister')->name('signup.post');
// ログイン
Route::get('login', 'Auth\AuthController@getLogin')->name('login.get');
Route::post('login', 'Auth\AuthController@postLogin')->name('login.post');
Route::get('logout', 'Auth\AuthController@getLogout')->name('logout.get');
// ログイン認証を必要とするルーティンググループ
Route::group(['middleware' => 'auth'], function () {
Route::resource('users', 'UsersController', ['only' => ['index', 'show']]); // ユーザ一覧, ユーザ詳細
Route::group(['prefix' => 'users/{id}'], function () {
Route::post('follow', 'UserFollowController@store')->name('user.follow');
Route::delete('unfollow', 'UserFollowController@destroy')->name('user.unfollow');
Route::get('followings', 'UsersController@followings')->name('users.followings');
Route::get('followers', 'UsersController@followers')->name('users.followers');
});
Route::resource('microposts', 'MicropostsController', ['only' => ['store', 'destroy']]); // 投稿の保存, 投稿の削除
// お気に入り
Route::post('favorite/{id}', 'FavoritesController@store')->name('micropost.favorite');
Route::delete('unfavorite/{id}', 'FavoritesController@destroy')->name('micropost.unfavorite');
Route::get('favorites/{id}', 'UsersController@favorites')->name('micropost.favorites');
});
よろしくお願いします。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
+1
ログイン情報の部分、解決されたようなのと、
質問の回答とは若干異なる内容なので、回答欄に書き込むのはどうかな・・とは思ったんですが。
根本的にバグになり得る部分なので、一応突っ込んでおこうかと思いまして、
コメントだと、うまいこと改行ができないので、回答に書かせてもらいます・・!
先にコメントで書いたように、ユーザー一覧のviewのお話です。
@foreach ($users as $user)
@endforeach
もし、このままにしているのであれば、
今は出力される順序のおかげで、
commons.navbarで利用しているのはコントローラーから渡した $user(ログインユーザーの情報)
になっているようですが、
実際には、
<!-- ここまでは、$userは、コントローラで渡した「ログインユーザーの情報」が入ってる -->
@foreach ($users as $user)
@endforeach
<!-- ここからは、$userには、$usersから最後に取り出した情報が入っている
となり、一覧を出した後は、
最後に取り出したレコードが「たまたまログインユーザーと同じユーザー」でない限り、
ログインユーザー情報は、もう参照できなくなります。
・ログインユーザーの情報を入れている変数名は
$auth_user
など、明確に見分けられるようにする。
・ログインユーザーの情報の取得を1回する以外は参照のみにとどめ、同じ変数は使わない。
というのがおススメ。。というか一般的?かなぁと。
※更新された?gitは見に行ってないので、もしすでに対応済みだった場合は、とんだ余計なお世話を失礼しました・・
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
check解決した方法
0
UsersController の index(){} 内で \Auth::User()
を用いてログイン中のユーザーを取得して view に渡す
ナビバーにユーザープロフィールページへのリンクを実装してから /users (ユーザー一覧ページ) にアクセスすると
Undefined variable: user (View: /home/ubuntu/workspace/microposts/resources/views/commons/navbar.blade.php)
となるのは、viewの継承 (user.index => layouts.app => commons.navbar) を経て最終的に navbar.blade.php にログイン中のユーザーの情報が渡っていない状態でユーザープロフィールページへのリンクを生成するための link_to_route()
メソッドの第3引数に ['id' => $user->id]
を渡していたことが原因でした。
故に UsersController.php の index() {}
内を下記のようにコーディングすると1.と2.を両方とも実現することができました。
public function index()
{
$users = User::paginate(10);
$user = \Auth::User();
return view('users.index', [
'users' => $users,
'user' => $user,
]);
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.35%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
mix-peach
2018/04/12 17:53
おもしろそうなので、gitまでソースを見に行ってみました。ちょっと不思議なのですが、$user には今ログインしている人の情報とかが入っているはずなんです、よね? でも、一覧では foreach($users as $user) で代入していて、詳細ではviewに渡すデータで、 ’user’ に「id指定したuserの情報」を入れていたように見えたんですが、これらは問題なく動くのでしょうか??
KIYZ
2018/04/12 18:12
コメント誠にありがとうございます。UsersControllerのindex(){}内で定義した$userにログインしたユーザーの情報を代入し、それをindex.bladeに渡すことができれば実装できるのではないかと思っています。同ファイルのshow(){}の様にindex($id) {$user = User::find($id);}とすればそれが実現できるのではないかとも思ったのですが、それをするとMissing Argumentエラーが出てしまいます。詳細ページは現状のコードで正常に表示できています。(ページ内の一部の機能は実装途中です。)