質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MVC

MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

Q&A

解決済

2回答

1261閲覧

LaravelでTwitterクローン開発 | ユーザー一覧ページの表示とユーザープロフィールページへのリンク生成

KIYZ

総合スコア17

MVC

MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

0グッド

0クリップ

投稿2018/04/11 13:55

編集2018/04/12 10:41

前提・実現したいこと

Cloud9でLaravel 5.1 LTSを用いてTwitterクローンを開発しています。
現在、以下の2点を同時に実現しようとしているところですが、どちらかを実現させるともう片方が実現できないという状態で、対処法が分からない状況です。

  1. DBのUsersテーブル上に存在する全ユーザー一覧のページを表示
  2. ログインしたユーザーが自分のプロフィールページにアクセスするためのリンクをナビバーに設置

発生している問題・エラーメッセージ

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.phpindex() に以下を追記すると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.phpshow(){} の様に、

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'); });

よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mix-peach

2018/04/12 08:53

おもしろそうなので、gitまでソースを見に行ってみました。ちょっと不思議なのですが、$user には今ログインしている人の情報とかが入っているはずなんです、よね? でも、一覧では foreach($users as $user) で代入していて、詳細ではviewに渡すデータで、 ’user’ に「id指定したuserの情報」を入れていたように見えたんですが、これらは問題なく動くのでしょうか??
KIYZ

2018/04/12 09:12

コメント誠にありがとうございます。UsersControllerのindex(){}内で定義した$userにログインしたユーザーの情報を代入し、それをindex.bladeに渡すことができれば実装できるのではないかと思っています。同ファイルのshow(){}の様にindex($id) {$user = User::find($id);}とすればそれが実現できるのではないかとも思ったのですが、それをするとMissing Argumentエラーが出てしまいます。詳細ページは現状のコードで正常に表示できています。(ページ内の一部の機能は実装途中です。)
guest

回答2

0

ログイン情報の部分、解決されたようなのと、
質問の回答とは若干異なる内容なので、回答欄に書き込むのはどうかな・・とは思ったんですが。

根本的にバグになり得る部分なので、一応突っ込んでおこうかと思いまして、
コメントだと、うまいこと改行ができないので、回答に書かせてもらいます・・!


先にコメントで書いたように、ユーザー一覧のviewのお話です。

php

1@foreach ($users as $user) 2@endforeach

もし、このままにしているのであれば、

今は出力される順序のおかげで、
commons.navbarで利用しているのはコントローラーから渡した $user(ログインユーザーの情報)
になっているようですが、

実際には、

php

1<!-- ここまでは、$userは、コントローラで渡した「ログインユーザーの情報」が入ってる --> 2 3@foreach ($users as $user) 4@endforeach 5 6<!-- ここからは、$userには、$usersから最後に取り出した情報が入っている

となり、一覧を出した後は、
最後に取り出したレコードが「たまたまログインユーザーと同じユーザー」でない限り、
ログインユーザー情報は、もう参照できなくなります。

・ログインユーザーの情報を入れている変数名は```
$auth_user

・ログインユーザーの情報の取得を1回する以外は参照のみにとどめ、同じ変数は使わない。 というのがおススメ。。というか一般的?かなぁと。 ※更新された?gitは見に行ってないので、もしすでに対応済みだった場合は、とんだ余計なお世話を失礼しました・・

投稿2018/04/13 01:03

mix-peach

総合スコア1910

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KIYZ

2018/04/13 12:58 編集

自分はプログラミング初心者ですのでこのようなご指摘は大変有り難いです。本当にありがとうございます。 そちらの問題については気づいておりませんでした。 一先ず @foreach ($users as $user) で取り出した $user とログインユーザーを格納するための変数を別にするために UsersController のコードを下記のようにして、 class UsersController extends Controller { public function index() { $users = User::paginate(10); $auth_user = \Auth::user(); return view('users.index', [ 'users' => $users, 'auth_user' => $auth_user, ]); } } navbar.blade.php のプロフィールページへのリンク生成の部分のコードを下記のようにしたのですが、 <li>{!! link_to_route('users.show', 'My profile', ['id' => $auth_user->id]) !!}</li> / にアクセスすると、 Undefined variable: auth_user (View: /home/ubuntu/workspace/microposts/resources/views/commons/navbar.blade.php) となってしまいました。 Laravelの公式ドキュメントのブレードテンプレートのページを読み返して @include('view.name', ['some' => 'data']) のようにして $auth_user を navbar.blade.php に渡すように試みたのですが、色々と検証してみた結果、 index.blade.php までしか渡っていないようでした。 コントローラーで取得したデータを目的のビューに渡す流れは作れていたと思っていたので、 UsersController で $auth_user とする前の状態で期待通りの動作をしていた根拠も分からなくなってしまいました…。 UsersController で取得したログインユーザーの情報は、 index.blade.php => app.blade.php => navbar.blade.php という順番で渡せていたと思っていたのですが、この辺のコーディングにも問題がありそうでしょうか? >ログインユーザーの情報の取得を1回する以外は参照のみにとどめ、同じ変数は使わない。 @foreach ($users as $user) で取り出した $user と UsersController で取得したログインユーザーの情報は別名の変数に格納するようにして、一度 UsersController でログインユーザー情報を取得した後は、そのデータが必要となった時は取得時に格納した変数から取り出すようにする。 という認識で合っていますか?
guest

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.phpindex() {} 内を下記のようにコーディングすると1.と2.を両方とも実現することができました。

public function index() { $users = User::paginate(10); $user = \Auth::User(); return view('users.index', [ 'users' => $users, 'user' => $user, ]); }

投稿2018/04/12 10:35

KIYZ

総合スコア17

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KIYZ

2018/04/13 12:57 編集

問題が解決しましたのでGitHub上のコードは今後変更していきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問