yusuke1209kitamura
@yusuke1209kitamura (murakita)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Call to a member function tasks() on null

#環境
PHP 7.3.11
Laravel Framework 5.8.38

#事象
TODOアプリを作成しております。
「仕事」というフォルダの中に「資料作成」や「会議」のようにタスクがあるような仕様です。

新規タスク作成画面でタスクを作成して、index画面に遷移すると掲題のエラーが出ます。
どこがnullになっているのか確認したところ、
TaskControllerのindexの$current_folderがnullとなっていることがわかりました。
ただ、なぜこの記述でnullになるのかが理解ができず解決にいたりません。
お力添えいただけますと助かります。

$current_folder = Folder::find($id['folder_id']);は試してみましたが、だめでした。

TaskController.php
<?php

namespace App\Http\Controllers;

use App\Folder;
use App\Task;
use Illuminate\Http\Request;
use App\Http\Requests\CreateTask;

class TaskController extends Controller
{

	public function create(int $id){
		return view('tasks/create',['folder_id' => $id]);
	}

	public function store(int $id, CreateTask $request){
		// 現在のフォルダを取得
		$current_folder = Folder::find($id);
		// 空のタスクインスタンスを生成し、リクエストを取得
		$task = new Task();
		$task->title = $request->title;
		$task->due_date = $request->due_date;
		// 現在のフォルダに生成したタスクを保存
		$current_folder->tasks()->save($task);
		return redirect()->route('tasks.index',['id' => '$current_folder->id']);
	}

	public function index($id){
		// すべてのフォルダを取得する
	    $folders = Folder::all();
	    // 選ばれたフォルダを取得する
    //$current_folderがnull
	    $current_folder = Folder::find($id);
	    // 選ばれたフォルダに紐づくタスクを取得する
	    $tasks = $current_folder->tasks()->get();

	    return view('tasks/index', [
	        'folders' => $folders,
	        'current_folder_id' => $current_folder->id,
	        'tasks' => $tasks,
	    ]);
	}


}
Folder.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Folder extends Model
{
	public function tasks(){
		return $this->hasMany('App\Task');
	}
}

Task.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;

class Task extends Model
	{

		public function folder(){
		return $this->belongsTo('App\Folder');
		}

		const STATUS = [
	    1 => [ 'label' => '未着手', 'class' => 'label-danger' ],
	    2 => [ 'label' => '着手中', 'class' => 'label-info' ],
	    3 => [ 'label' => '完了', 'class' => '' ],
	];

	/**
	 * 状態を表すHTMLクラス
	 * @return string
	 */
	public function getStatusLabelAttribute()
	{
	    // 状態値
	    $status = $this->attributes['status'];

	    // 定義されていなければ空文字を返す
	    if (!isset(self::STATUS[$status])) {
	        return '';
	    }

	    return self::STATUS[$status]['label'];
	}

	/**
     * 整形した期限日
     * @return string
     */
	public function getFormattedDueDateAttribute(){
		return Carbon::createFromFormat('Y-m-d',$this->attributes['due_date'])->format('Y/m/d');
	}
}

index.blade.php
@extends('layout')

@section('content')
  <div class="container">
    <div class="row">
      <div class="col col-md-4">
        <nav class="panel panel-default">
          <div class="panel-heading">フォルダ</div>
          <div class="panel-body">
            <a href="{{ route('folders.create') }}" class="btn btn-default btn-block">
              フォルダを追加する
            </a>
          </div>
          <div class="list-group">
            @foreach($folders as $folder)
              <a href="{{ route('tasks.index', ['id' => $folder->id]) }}" class="list-group-item {{ $current_folder_id === $folder->id ? 'active' : ''}}">
                {{ $folder->title }}
              </a>
            @endforeach
          </div>
        </nav>
      </div>

      <div class="column col-md-8">
        <div class="panel panel-default">
          <div class="panel-heading">タスク</div>
          <div class="panel-body">
            <div class="text-right">
              <a href="{{ route('tasks.create',['id' => $current_folder_id ])}}" class="btn btn-default btn-block">
                タスクを追加する
              </a>
            </div>
          </div>
        <table class="table">
          <thead>
          <tr>
            <th>タイトル</th>
            <th>状態</th>
            <th>期限</th>
            <th></th>
          </tr>
          </thead>
          <tbody>
            @foreach($tasks as $task)
              <tr>
                <td>{{ $task->title }}</td>
                <td>
                  <span class="label {{ $task->status_class }}">{{ $task->status_label }}</span>
                </td>
                <td>{{ $task->formatted_due_date }}</td>
                <td><a href="#">編集</a></td>
              </tr>
            @endforeach
          </tbody>
        </table>
      </div>
      </div>
    </div>
  </div>
@endsection
0

5Answer

TaskController::index($id)$idには想定している値が入っていますか?
dd($id)などで確認してください。

それとルーティング設定でidが渡せるようになっていますか?

0Like

ご返答ありがとうございます。

はい、確認したところ、$idには欲しい値("$current_folder->id")が入っております。

以下の通りにルーティングを設定しており、Task/indexの画面を表示するのに、folderのidが欲しいので、問題ない認識です。
Route::get('/folders/{id}/tasks','TaskController@index')->name('tasks.index');

0Like

では単純にfind()でデータが取得できていないようですね。
$idに対応するレコードはDBにありますか?
また、論理削除(ソフトデリート)が設定されていて削除された状態ではないでしょうか?

0Like

ご返答ありがとうございます。

はい、以下のように登録したレコードはすべて入っていることを確認しました。
フォルダー名は気にしないでください笑
1
プライベート
2020-10-30 15:55:16
2020-10-30 15:55:16
2
仕事
2020-10-30 15:55:16
2020-10-30 15:55:16
3
旅行
2020-10-30 15:55:16
2020-10-30 15:55:16
4
サッカー
2020-10-31 11:51:08
2020-10-31 11:51:08
5
彼女
2020-11-01 11:23:40
2020-11-01 11:23:40

また、念のため確認しましたが、ソフトデリートの設定は見当たりません。

0Like

原因はわかりませんが代わりの方法として、
直前で全てのFolderを取得しているのでそこから取り出せないでしょうか?

$folders = Folder::all();
$current_folder = $folders->find($id);

findメソッドは、指定した主キーのモデルを見つけます。

Laravel 5.8 Eloquent:コレクション

0Like

Comments

  1. ご返答ありがとうございます。
    以下の通り、同様のエラーが出ました。
    Call to a member function tasks() on null
  2. $foldersの中身はどうなっていますか?
    これでデータが入っていないようなら、そもそもデータを取得できない状態ではないでしょうか?
    例えば別のデータベースを参照しているなど。

Your answer might help someone💌