Php Laravel 7从数据库和磁盘删除阵列或单个映像-从数据库或磁盘删除post,但不删除关联的映像
在Laravel7中,我有一个任务管理应用程序。我可以上传任务(如果是博客的话,可以上传帖子)和图片。我有一个多图像上传工作的预期。当需要删除任务时,任务会很好地删除,但映像会留在数据库和磁盘中,该磁盘是公用的,并保存在名为“任务映像”的文件夹中。作为拉雷维尔的新手,我正在努力解决这个问题。我试图更改Php Laravel 7从数据库和磁盘删除阵列或单个映像-从数据库或磁盘删除post,但不删除关联的映像,php,laravel,sql-delete,Php,Laravel,Sql Delete,在Laravel7中,我有一个任务管理应用程序。我可以上传任务(如果是博客的话,可以上传帖子)和图片。我有一个多图像上传工作的预期。当需要删除任务时,任务会很好地删除,但映像会留在数据库和磁盘中,该磁盘是公用的,并保存在名为“任务映像”的文件夹中。作为拉雷维尔的新手,我正在努力解决这个问题。我试图更改filesystem.php中的设置(我将随注释掉的代码一起发布),但这并没有像我预期的那样更改位置。最后,我希望能够在删除帖子时删除多个图像,并在单个图像上单击“删除”,然后从数据库和磁盘中删除该
filesystem.php
中的设置(我将随注释掉的代码一起发布),但这并没有像我预期的那样更改位置。最后,我希望能够在删除帖子时删除多个图像,并在单个图像上单击“删除”,然后从数据库和磁盘中删除该图像。我正在为我的所有任务路由使用资源控制器。我不知道该怎么做,而且我发现的教程并没有真正解决我的具体问题。任何帮助都将不胜感激。先谢谢你
这是我的任务控制器,位于TaskController.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);
// $image = '/task-images/' . $task->image;
Storage::delete($task->image);
$task->delete();
return redirect('home')->with('success', 'Task Deleted');
}
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
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);
}
}
在我个人的show模板中,show.blade.php
complete,以防代码冲突
@extends('layouts.master')
@section('content')
<div class="container">
<a href="/home" class="btn bg-purple mb-4">Go Back</a>
<div class="card p-3">
<div class="row">
<div class="col-md-4 col-sm-12">
<h3>Task</h3>
<p>{{ $task->task_name }}</p>
<h3>Assigned On:</h3>
<p>{{ $task->created_at->format('m/d/Y') }}</p>
<h3>Assigned To:</h3>
<p>{{ $task->task_assigned_to }}</p>
</div>
<div class="col-md-4 col-sm-12">
<h3>Task Description</h3>
<p>{{ $task->task_description }}</p>
<h3>Priority</h3>
<p>{{ $task->task_priority }}</p>
<h3>Status</h3>
<p>{{ $task->task_status }}</p>
</div>
<div class="col-md-4 col-sm-12">
<h3>Test Environment Date:</h3>
<p>{{ $task->task_to_be_completed_date }}</p>
<h3>Notes</h3>
<p>{{ $task->task_notes }}</p>
<h3>Action</h3>
<div style="display: inline;">
<a href="/tasks/{{$task->id}}/edit" class="btn btn-sm btn-primary mr-2">
<i class="fa fa-edit"></i> Edit
</a>
</div>
<form style="display: inline;" action="/tasks/{{ $task->id }}" method="POST" class="">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger btn-sm ml-1 mr-1">
<i class="fa fa-trash"></i> Delete
</button>
</form>
</div>
<div class="col-md-12">
<h5>Images</h5>
<hr />
<div class="row">
@if($task->image->count()>0)
@for($i=0; $i < count($images = $task->image()->get()); $i++)
<div class="col-lg-4 col-md-6 col-sm-12">
<a href="#" class="thumbnail" data-toggle="modal" data-target="#lightbox"><img class="w-50 mb-2" src="/task-images/{{ $images[$i]['name'] }}" alt=""></a>
<form style="display: inline;" action="/tasks/{{ $task->name }}" method="POST" class="">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger btn-sm ml-1 mr-1">
<i class="fa fa-trash"></i> Delete
</button>
</form>
</div>
@endfor
@else
<p>No images found</p>
@endif
</div>
<br />
</div>
</div>
</div>
</div>
<!--Modal Start-->
<div id="lightbox" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true">
<div class="modal-dialog">
<button type="button" class="close hidden" data-dismiss="modal" aria-hidden="true">×</button>
<div class="modal-content">
<div class="modal-body">
<img class="w-100" src="" alt="" />
</div>
</div>
</div>
</div>
<!--Modal End-->
@endsection
@section('scripts')
<script>
$(document).ready(function() {
var $lightbox = $('#lightbox');
$('[data-target="#lightbox"]').on('click', function(event) {
var $img = $(this).find('img'),
src = $img.attr('src'),
alt = $img.attr('alt'),
css = {
'maxWidth': $(window).width() - 100,
'maxHeight': $(window).height() - 100
};
$lightbox.find('.close').addClass('hidden');
$lightbox.find('img').attr('src', src);
$lightbox.find('img').attr('alt', alt);
$lightbox.find('img').css(css);
});
$lightbox.on('shown.bs.modal', function (e) {
var $img = $lightbox.find('img');
$lightbox.find('.modal-dialog').css({'width': $img.width()});
$lightbox.find('.close').removeClass('hidden');
});
});
</script>
@endsection
最后是我的图像模型Image.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);
// $image = '/task-images/' . $task->image;
Storage::delete($task->image);
$task->delete();
return redirect('home')->with('success', 'Task Deleted');
}
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
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);
}
}
我在模型中声明了image而不是image,这导致了一个问题。添加三元运算符也有助于代码不会抛出任何错误
在我的TasksController.php中,我使用相同的三元运算符更改了update和create函数,如下所示:
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]);
}
}
我希望这能帮助其他有同样问题的人。感谢@GrumpyCrouton和@lagbox在解决此问题上的帮助,以及@user3563950
如果没有它们,我仍然会绞尽脑汁再过几个星期。在你的
App\Image
类中,实现以下启动功能:
use Illuminate\Support\Facades\Storage;
public static function boot() {
parent::boot();
self::deleting(function($image) {
Storage::delete(Storage::path($image->name));
});
}
还可以在App\Task
类中实现引导方法
use Illuminate\Support\Facades\Storage;
public static function boot() {
parent::boot();
self::deleting(function($task) {
foreach($task->images as $image) {
$image->delete();
}
});
}
现在在您的TaskController
上执行destroy
方法,如下所示
public function destroy($id)
{
$task = Task::findOrFail($id);
$task->delete();
return redirect('home')->with('success', 'Task Deleted');
}
作为奖励,学习在
App\Image
类上使用findOrFail()
来减轻查找实例的痛苦,使用以下命令实现引导功能:
use Illuminate\Support\Facades\Storage;
public static function boot() {
parent::boot();
self::deleting(function($image) {
Storage::delete(Storage::path($image->name));
});
}
还可以在App\Task
类中实现引导方法
use Illuminate\Support\Facades\Storage;
public static function boot() {
parent::boot();
self::deleting(function($task) {
foreach($task->images as $image) {
$image->delete();
}
});
}
现在在您的TaskController
上执行destroy
方法,如下所示
public function destroy($id)
{
$task = Task::findOrFail($id);
$task->delete();
return redirect('home')->with('success', 'Task Deleted');
}
作为奖励,学习使用
findOrFail()
Hi,不确定,可能是->onDelete('cascade')来减轻查找实例的痛苦代码>是否需要?或者可能需要显式删除磁盘文件…我将尝试一下IronMan。很遗憾,这给出了:传递给Illumb\Database\Eloquent\Builder::onDelete()的参数1必须是闭包实例,字符串给定,在第23Hi行的C:\laragon\www\taskapp\vendor\laravel\framework\src\illumb\Support\Traits\ForwardsCalls.php中调用,不确定,可能是->onDelete('cascade')代码>是否需要?或者可能需要显式删除磁盘文件…我将尝试一下IronMan。很遗憾,这给出了:传递给Illumb\Database\Eloquent\Builder::onDelete()的参数1必须是闭包实例,字符串给定,在第23行的C:\laragon\www\taskapp\vendor\laravel\framework\src\Illumb\Support\Traits\ForwardsCalls.php中调用。此解决方案很好,但请记住,如果需要,在大规模删除的情况下不会触发这些事件。感谢用户3563950和Pirvu2k。只是澄清一下,您是分别引用model Image.php和Task.php,还是仅在类本身上引用。对不起,我有个问题,好的。我觉得我越来越近了。我实现了User3563950的建议,但它抛出了以下错误:为foreach()提供的ErrorException无效参数。。。有什么线索吗?再次感谢您。在您的任务
模型中将您的图像
关系重命名为图像
。感谢此解决方案很好,但请记住,如果需要,在大规模删除的情况下不会触发这些事件。感谢用户3563950和Pirvu2k。只是澄清一下,您是分别引用model Image.php和Task.php,还是仅在类本身上引用。对不起,我有个问题,好的。我觉得我越来越近了。我实现了User3563950的建议,但它抛出了以下错误:为foreach()提供的ErrorException无效参数。。。有什么线索吗?再次感谢您。在您的任务
模型中将您的图像
关系重命名为图像
。谢谢