php - Laravel 7 尝试删除带有多个图像的帖子时为 foreach() 提供的参数无效
问题描述
我正在运行 Laravel 7 并且有一个任务列表(如果它是博客,则将是帖子),我需要确保在删除任务时,所有后续图像在数据库和光盘中都被删除。当我单击删除按钮时,页面会抛出错误:Invalid argument supplied for foreach()
. 不幸的是,这是一个模糊的错误,可能由多种原因引起。我希望有人可以看看我的代码,看看我是否遗漏了什么。我对 Laravel 比较陌生,所以追查这个问题不仅仅是一个挑战。比你提前帮助我解决这个问题。在我的Task.php
模型中,我有:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\Image;
use Illuminate\Support\Facades\Storage;
class Task extends Model
{
protected $fillable = [
'task_name', 'task_priority', 'task_assigned_to', 'task_assigned_by', 'task_description', 'task_to_be_completed_date', 'task_status',
'task_notes'
];
public function user()
{
return $this->belongsTo(User::class);
}
public function image()
{
// return $this->hasMany('App\Image');
return $this->hasMany(Image::class);
}
public static function boot()
{
parent::boot();
self::deleting(function ($task) {
foreach ($task->images as $image) {
$image->delete();
}
});
}
}
在我的Image.php
模型中,我有
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
use App\Task;
class Image extends Model
{
protected $fillable = [
'task_id',
'name',
];
protected $uploads = '/task-images/';
public function getFileAttribute($image)
{
return $this->uploads . $image;
}
public function task()
{
// return $this->belongsTo('App\Task', 'task_id');
return $this->belongsTo(Task::class);
}
public static function boot()
{
parent::boot();
self::deleting(function ($image) {
Storage::delete(Storage::path($image->name));
});
}
}
在我的TasksController.php
, 中(所有代码,以防此处引起冲突)这是我所拥有的:
<?php
namespace App\Http\Controllers;
use App\Task;
use App\Image;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
class TasksController extends Controller
{
public function index()
{
$tasks = Task::orderBy('created_at', 'desc')->paginate(10);
return view('/tasks')->with('tasks', $tasks);
}
public function create()
{
return view('tasks.create');
}
public function store(Request $request)
{
$this->validate($request, [
'task_name' => 'required',
'task_description' => 'required',
]);
// Create Task
$user = Auth::user();
$task = new Task();
$data = $request->all();
$task->user_id = $user->id;
$task = $user->task()->create($data);
if ($request->hasFile('images')) {
$files = $request->file('images');
foreach ($files as $file) {
$name = time() . '-' . $file->getClientOriginalName();
$name = str_replace(' ', '-', $name);
$file->move('task-images', $name);
$task->image()->create(['name' => $name]);
$images = new Image;
$images->name = $name;
}
}
$task->task_name = $request->input('task_name');
$task->task_description = $request->input('task_description');
$task->task_priority = $request->input('task_priority');
$task->task_assigned_by = $request->input('task_assigned_by');
$task->task_assigned_to = $request->input('task_assigned_to');
$task->task_to_be_completed_date = $request->input('task_to_be_completed_date');
$task->task_notes = $request->input('task_notes');
$task->task_status = $request->task_status;
$task->save();
return redirect('/home')->with('success', 'Task Created');
}
public function edit($id)
{
$task = Task::find($id);
return view('tasks.edit', ['task' => $task]);
}
public function update(Request $request, $id)
{
$this->validate($request, [
'task_name' => 'required',
'task_description' => 'required',
]);
$task = Task::find($id);
$task->task_name = $request->input('task_name');
$task->task_description = $request->input('task_description');
$task->task_priority = $request->input('task_priority');
$task->task_assigned_by = $request->input('task_assigned_by');
$task->task_assigned_to = $request->input('task_assigned_to');
$task->task_to_be_completed_date = $request->input('task_to_be_completed_date');
$task->task_notes = $request->input('task_notes');
$task->task_status = $request->input('task_status');
if ($request->hasFile('images')) {
$files = $request->file('images');
foreach ($files as $file) {
$name = time() . '-' . $file->getClientOriginalName();
$name = str_replace(' ', '-', $name);
$file->move('task-images', $name);
$task->image()->create(['name' => $name]);
}
}
$task->update();
return redirect('/home')->with('success', 'Task Updated');
}
public function show($id)
{
$task = Task::find($id);
return view('tasks.show')->with('task', $task);
}
public function destroy($id)
{
$task = Task::findOrFail($id);
// dd($task);
$task->delete();
return redirect('home')->with('success', 'Task Deleted');
}
}
And in the home page where I am calling the delete function, `home.blade.php`, I have:
@extends('layouts.master')
@section('content')
<div class="custom-container">
<div class="row justify-content-center">
<div class="col-md-12">
@include('layouts.includes.messages')
<div class="card w-100">
<div class="card-header text-white" style="background-color: #605ca8;">
<h3 class="card-title">Tasks</h3>
<div class="card-tools">
<a href="tasks/create" class="btn btn-success">
<i class="fas fa-tasks"></i> Add New Task
</a>
</div>
</div>
<!-- /.card-header -->
</div>
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">Ongoing Tasks</h3>
<div class="card-tools">
<div class="input-group input-group-sm" style="width: 150px;">
<input type="text" name="table_search" class="form-control float-right" placeholder="Search">
<div class="input-group-append">
<button type="submit" class="btn btn-default"><i class="fas fa-search"></i></button>
</div>
</div>
</div>
</div>
<!-- /.card-header -->
<div class="card-body table-responsive p-0">
<table class="table table-hover text-nowrap">
<thead>
<tr>
<th>Task</th>
<th>Priority</th>
<th>Assigned To</th>
<th>Test Environment Date</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
@if($tasks->count() > 0)
@foreach($tasks as $task)
<tr>
<td><a href="/tasks/{{$task->id}}">{{ $task->task_name }}</a></td>
<td>{{ $task->task_priority }}</td>
<td>{{ $task->task_assigned_to }}</td>
<td>{{$task->task_to_be_completed_date }}</td>
<td>{{ $task->task_status }}</td>
<td>
<a href="tasks/{{$task->id}}/edit" class="btn btn-primary btn-sm mr-2">
<i class="fa fa-edit"></i> Edit
</a>
<form action="tasks/{{$task->id}}" method="POST" style="display: inline" class="">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger ml-1 mr-1">
<i class="fa fa-trash"></i> Delete
</button>
</form>
</td>
</tr>
@endforeach
@else
<p class="ml-4 pt-2">No Tasks Found. Please Add one.</p>
@endif
</tbody>
</table>
</div>
<!-- /.card-body -->
</div>
<!-- /.card -->
</div>
</div>
</div>
{{ $tasks->links() }}
</div>
</div>
@endsection
在我的 config 文件夹下的 filesystem.php 中,我有(仅用于存储):
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
// 'root' => public_path('task-images'),
],
如果我遗漏了任何内容或代码,请告诉我,以便我可以编辑我的问题。再次感谢您帮助我解决这个问题。
解决方案
您正在尝试访问images
在您的实例上命名的属性,Task
但没有一个名为的属性images
,也没有一个名为的关系images
,因此null
返回:$task->images == null
。您将您的关系命名为image
not images
,但images
会更正确,因为这种关系可以返回很多;复数。将关系的名称更改为images
:
public function images()
{
return $this->hasMany(Image::class);
}
或以当前名称引用它:$task->image
推荐阅读
- python - 如何在远程机器上执行 python 脚本时发送密码
- html - paginate_by 如何显示省略号 - Django
- linux - 如何将“which”与正则表达式一起使用,或以其他方式在 $PATH 中查找命令
- dictionary - Angular 6:请求的资源上不存在“Access-Control-Allow-Origin”标头
- css - 按钮 CSS 样式在移动设备上不起作用
- c# - 我们需要在 Fluent Api 中定义所有模型吗?
- arrays - 将迭代分布在具有最小值和最大值的特定数组中的列中
- angular - 获取错误 Http 服务:NgFor 仅支持绑定到 Iterables,例如 Arrays。”
- ios - 在不同的测试目标之间有效地共享测试替身
- node.js - 尝试获取特定的单个记录时,GraphiQL 返回空值