replica410
@replica410 (陽 有村)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

Laravelでのプロフィール画面の作成時のエラー(Undefined variable)

解決したいこと

Undefined variableエラーを解決し、ユーザープロフィール画面を表示させたい

ユーザープロフィール画面を作成しています。最初にログイン処理をし、そこでログインが出来た際にログイン後用トップページが表示され、そこからユーザープロフィール画面に飛んだ際にはログインしたユーザーに沿ったユーザー情報(名前や設定した画像)が表示される仕組みにしたいです。
質問もLaravelの学習自体も不慣れなので、足りない情報や誤った認識や知識があれば修正・追記しますのでご指摘ください。

発生している問題・エラー

未定義の変数というエラー(Undefined variable![スクリーンショット (30).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2535445/f8c5ff5d-9e1a-4bda-7588-6b1e55ad6ddd.png)
![スクリーンショット (31).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2535445/6c1ddf1d-59d2-f055-b5c1-fc80c397da64.png)
![スクリーンショット (32).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2535445/03182856-ccb6-bc54-c615-dcf046cd8b80.png)
)

例)

Undefined variable: users (View: /home/ec2-user/environment/laravel_photo/resources/views/users/show.blade.php)

該当するソースコード

web.php(ルーティング用)
<?php

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Auth::routes();

Route::get('/', function () {
    // return view('welcome');
    return view('top');
});

Route::resource('posts', 'PostController');

Route::resource('likes', 'LikeController')->only([
    'index', 'store', 'destroy'
]);
    
Route::resource('follows', 'FollowController')->only([
    'index', 'store', 'destroy'
]);

Route::get('/folloow', 'FollowController@folloowerIndex');

Route::resource('comments', 'CommentController')->only([
    'store', 'destroy'    
]);
Route::get('/posts/{post}/edit_image', 'PostController@editImage')->name('posts.edit_image');

Route::patch('/posts/{post}/edit_image', 'PostController@updateImage')->name('posts.update_image');

Route::get('/users/edit', 'UserController@edit')->name('users.edit');
Route::patch('/users', 'UserController@update')->name('users.update');
Route::get('/users/edit_image', 'UserController@editImage')->name('users.edit_image');
Route::patch('/users/edit_image', 'UserController@updateImage')->name('users.update_image');

Route::resource('users', 'UserController')->only([
  'show',
]);


UserController.php(コントローラー)
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\User;

class UserController extends Controller
{
    public function show($id)
    {
        $user = User::find($id);
        return view('users.show',[
            'title' => 'プロフィール',
            'user' => $user,
        ]);
    }
    
    public function edit($id)
    {
        $user = User::find($id);
        return view('users.edit',[
            'title' => 'プロフィール編集',
            'user' => $user,
        ]); 
    }
}
top.blade.php(トップページ)
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div>
    <a href="/posts">投稿一覧</a>
    <a href="/likes">いいねした投稿一覧</a>
    <a href="/posts/create">投稿追加フォーム</a>
    <a href="/posts/1"></a>
    <a href="/posts/1/edit">投稿編集</a>
    <a href="/follows">フォロー一覧</a>
    <a href="follower">フォロワー一覧</a>
    </div>
</body>
</html>
logged_in.blade.php(ログイン後のトップページ)
@extends('layouts.default')
 
@section('header')
<header>
    <ul class="header_nav">
        <li>
          <a href="{{ route('posts.index') }}">
            投稿一覧
          </a>
        </li>
        <li>
          <a href="{{ route('likes.index') }}">
            いいねリスト
          </a>
        </li>
        <li>
          <a href="{{ route('users.edit') }}">
          ユーザープロフィール
          </a>
        </li>
        <li>
          <form action="{{ route('logout') }}" method="POST">
            @csrf
            <input type="submit" value="ログアウト">
          </form>
        </li>
    </ul>
    <p>{{ Auth::user()->name }}さん、こんにちは!</p>
</header>
@endsection
show.blade.php(ユーザープロフィール画面で表示させたい画面)
@extends('layouts.logged_in')

@section('content')
<h1>{{ $title }}</h1>

<a href="{{route('users.update')}}">編集</a>
<ul>
    @forelse($users as $user)
    <div>
        名前
        {{ $user->user->name }}
    </div>
    <div>
  @if($user->image !== '')
      <img src="{{ asset('storage/' . $user->image) }}">
  @else
      <img src="{{ asset('images/no_image.png') }}">
  @endif
        <a href="{{ route('users.edit_image', $user) }}">画像を変更</a>
    </div>
    <div>
        <span>プロフィール</span>
        <ul>
            @forelse($profile as $profile)
            <li>{{ $profile }}</li>
            @empty
            <li>プロフィールが設定されていません。</li>
            @endforelse
        </ul>
    </div>
    
    @empty
<li>設定されていません。</li>
</ul>
    
    @endforelse
@endsection

自分で試したこと

テーブル名やカラムの再確認

0

1Answer

Undefined variable: users

usersが未定義の変数」という意味ですが、show.blade.phpにセットしているのはuserで、にもかかわらずusersという名称でアクセスしようとしているのが原因でしょう。

UserController.php
// ...
    public function show($id)
    {
        $user = User::find($id);
        return view('users.show',[
            'title' => 'プロフィール',
            'user' => $user, // <--
        ]);
    }
// ...
show.blade.php
@extends('layouts.logged_in')

@section('content')
<h1>{{ $title }}</h1>

<a href="{{route('users.update')}}">編集</a>
<ul>
    @forelse($users as $user)

    <!-- ... -->

    @empty

    <!-- ... -->

    @endforelse
@endsection

付け加えると、@forelseはコレクション(複数のデータ)を処理するものですが、findメソッドで得られるデータは1レコード分です。

1Like

Comments

  1. @replica410

    Questioner

    ありがとうございます。
    未定義の変数に関してはエラー名が変わったので解消されたと思うのですが、「Invalid argument supplied for foreach()」と出たので、恐らく追加で書いて頂いたforelseでエラーが発生してしまいました。
    書いて頂いた内容を見るに、idを指定して取得しようとしているのでfindはそのままでforelseを別のfor文に変えるという事でしょうか?
  2. まずforelseやfor文を使おうとしているのは何故でしょうか?
  3. @replica410

    Questioner

    自分の考えとしては、プロフィールや画像を設定しているidを呼び出した場合はその情報を、もし設定していないidを呼び出した場合は下部で設定している「設定されていません」の文章を出すために必要かと思いfor文を使いました。
  4. forelseやfor文などのループ処理は複数のデータを1つずつ処理するのに適していますが、そもそも単一のデータに限定されるケースで使うのは向かないです。

    if文などで判定するのが妥当でしょう。
    https://readouble.com/laravel/6.x/ja/blade.html#if-statements

    プログラミングをするにはデータの状態を把握して組み立てていく必要があります。
    慣れないうちは逐一デバッグして、自分のイメージと一致している状態か確認しつつ進めるのが良いと思います。

    https://qiita.com/ucan-lab/items/29614d0f3ded1d3a94fb

Your answer might help someone💌