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

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

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

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

PHP

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

Q&A

解決済

1回答

832閲覧

Laravel 親子関係で紐づけた子モデルのデータを更新したい

hanasaki

総合スコア3

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

PHP

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

0グッド

0クリップ

投稿2023/03/10 10:56

実現したいこと

  • 親子関係で紐づいた子モデルのステータスを更新したい

前提

Laravel初心者です。現在Todoアプリを制作しています。
大目標(Todo)とそれを達成するための小目標(TodoList)があり、それぞれ親子関係になっています。
子モデルの小目標が達成されたときに完了ボタンを押すことでステータスが未完了(false)→完了(true)になるようにしたいです。

  • Todo(親モデル)
  • TodoList(子モデル)
  • TodoList(子モデル)にstatusカラム(boolean型)が存在し、デフォルトはfalseになっています。

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

完了ボタンを押した際下記のエラーが発生してしまいます。

エラーメッセージ

Attempt to assign property "status" on null

該当のソースコード

Todo.php

php

1<?php 2namespace App\Models; 3use Illuminate\Database\Eloquent\Factories\HasFactory; 4use Illuminate\Database\Eloquent\Model; 5 6class Todo extends Model 7{ 8 // リレーション 9 // ひとつの大目標(todo)はいくつかの小目標(todo_lists)を持つことができる 10 public function todo_lists() 11 { 12 return $this->hasMany('App\Models\TodoList'); 13 } 14 // リレーション 15} 16

TodoList.php

php

1<?php 2namespace App\Models; 3use Illuminate\Database\Eloquent\Factories\HasFactory; 4use Illuminate\Database\Eloquent\Model; 5 6class TodoList extends Model 7{ 8 use HasFactory; 9 10 // リレーション 11 // 小目標(todo_list)は一つの大目標(todo)を持つ 12 public function todo() 13 { 14 return $this->belongsTo('App\Models\Todo'); 15 } 16 // リレーション 17} 18

web.php

php

1<?php 2 3use App\Http\Controllers\ProfileController; 4use Illuminate\Support\Facades\Route; 5use App\Http\Controllers\TodoController; 6use App\Http\Controllers\TodoListController; 7 8// 小目標(todo_list)、大目標(todo)にネスト 9Route::resource('todos', TodoController::class); 10Route::resource('todo.todo_lists',TodoListController::class) 11

TodoListController.php

php

1<?php 2 3namespace App\Http\Controllers; 4use Illuminate\Http\Request; 5use App\Models\Todo; 6use App\Models\TodoList; 7 8 9class TodoListController extends Controller 10{ 11 12 public function update(Request $request, $id) 13 { 14 //該当データ検索 15 $todo_list = TodoList::find($id); 16 //ステータスを未完了(デフォルト)→完了 false:未完了 true:完了 17 $todo_list->status= true; 18 //データの保存 19 $todo_list->save(); 20 // 詳細画面のリダイレクト 21 return redirect()->route('todos.show',$todo_list->todo_id); 22 23 }

TodoController.php

php

1<?php 2namespace App\Http\Controllers; 3use Illuminate\Http\Request; 4use App\Models\Todo; 5use App\Models\User; 6use App\Models\TodoList; 7 8class TodoController extends Controller 9{ 10 public function show($id) 11 { 12 $todo= Todo::find($id); 13 $todo->todo_lists(); 14 return view('todos.show',compact('todo')); 15 } 16 17} 18

todos/show.blade.php

php

1@extends('layouts.app') 2@section('content') 3 4 <div class="container show_box"> 5 <h2 class="show_content_title">❗️やること❗️</h2> 6 <table> 7 //未完了タスクの表示 8 @foreach($todo->todo_lists as $todo_list) 9 @if($todo_list->status==false) 10 <tr> 11 <td>{{$todo_list->list_name}}</td> 12 //ステータスを更新 13 <td> 14 <form action="/todo/{{$todo->id}}/todo_lists/{{$todo_list->id}}" method="post"> 15 @csrf 16 @method('PUT') 17 <input type="hidden" name="status" value="{{$todo_list->status}}"> 18 <div class=green_button><button type="submit"><strong>完了</strong></button></div> 19 </form> 20 </td> 21 </tr> 22 @endif 23 @endforeach 24 </table> 25 26 27 <h2 class="devide_content_title">⭐️終わったこと⭐️</h2> 28 <table> 29 //完了タスクの表示 30 @foreach($todo->todo_lists as $todo_list) 31 @if($todo_list->status==true) 32 <tr> 33 <td>{{$todo_list->list_name}}</td> 34 <td>{{$todo_list->updated_at->format('Y-m-d')}}</td> 35 </tr> 36 @endif 37 @endforeach 38 </table> 39 </div><!--done_box--> 40 </div> 41 42@endsection

試したこと

親モデルのコントローラ(TodoController)のupdateメソッドに記載などしてみましたが
うまくいきませんでした。
原因が分からない為、ご教授頂ければと思います。

補足情報(FW/ツールのバージョンなど)

Laravel9

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

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

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

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

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

guest

回答1

0

ベストアンサー

まずRoute::resource('todo.todo_lists',TodoListController::class)によってどういうルートが定義されてるか確認。
php artisan route:list
多分こんなルート。
todo/{todo}/todo_lists/{todo_list}
この{todo}や{todo_list}はパラメータでURLとして組み立てられた時はtodo/1/todo_lists/2みたいになる。
ここまではルーティングの話。

ルーティングとコントローラーを対応させる時はパラメータとメソッドの引数名を揃える。

php

1public function update(Request $request, $todo, $todo_list) 2{ 3}

質問の原因は引数名ではなく$todo, $todo_listの2つ必要なのに$id一つしかないから。
この$idはTodoのidなのにTodoListで使ってるから正しく動かない。

引数名の一致が必須なのは次の段階のルートモデル結合を使う時。↑の場合は厳密には引数名は関係ないけどLaravelならルートモデル結合を使うのが普通なので最初から引数名を揃えたほうがいい。

php

1public function update(Request $request, Todo $todo, TodoList $todo_list) 2{ 3 $todo_list->status = true; 4 $todo_list->save(); 5}

投稿2023/03/10 11:55

kawax

総合スコア10377

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

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

hanasaki

2023/03/10 12:38

回答頂いた方法で上手くいきました! 分かりやすく解説して下さってありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問