Php larvel each()闭包未执行
我在跟踪一只Laracast。我正在努力通过我的一项考试。我做了一些调试。在RecordActivity.php中,我目前有以下内容:Php larvel each()闭包未执行,php,laravel,eloquent,laravel-6,laravel-events,Php,Laravel,Eloquent,Laravel 6,Laravel Events,我在跟踪一只Laracast。我正在努力通过我的一项考试。我做了一些调试。在RecordActivity.php中,我目前有以下内容: static::deleting(function ($thread) { $thread->replies->each(function($reply) { dd($reply); $reply->delete();
static::deleting(function ($thread) {
$thread->replies->each(function($reply) {
dd($reply);
$reply->delete();
});
});
但是,当我运行在lession中创建的测试时,我觉得每个测试中的闭包都不会触发,因为测试返回错误而不是给出回复。我重新观看了几次视频,并将我的代码与github repo中Jeffery的代码进行了比较
我做错了什么
RecordActivity.php
<?php
namespace App;
trait RecordActivity
{
protected static function bootRecordActivity()
{
if (auth()->guest()) return;
foreach (static::getRecordEvents() as $event) {
static::$event(function ($model) use ($event) {
$model->recordActivity($event);
});
}
static::deleting(function ($model) {
$model->activity()->delete();
});
}
protected function recordActivity($event)
{
$this->activity()->create([
'user_id' => auth()->id(),
'type' => $this->getActivityType($event)
]);
}
protected static function getRecordEvents()
{
return ['created'];
}
public function activity() {
return $this->morphMany('App\Activity', 'subject');
}
protected function getActivityType($event)
{
$type = strtolower((new \ReflectionClass($this))->getShortName());
return "{$event}_{$type}";
}
}
为什么我的测试没有转储$reply模型问题出在您的控制器中:
$thread->replies()->delete();
$thread->delete();
首先删除回复,然后删除线程,因此:
static::deleting(function ($thread) {
$thread->replies->each(function($reply) {
dd($reply);
$reply->delete();
});
});
执行$thread->replies返回空集合,因为您刚刚在控制器中删除了它们
您应该删除$thread->repress->delete;控制器中的行第一件事是在删除线程之前直接删除所有回复。因此,当调用删除侦听器时,该线程没有要循环的回复
在生成器上直接调用delete时,它不使用模型的delete方法。它直接执行删除查询,因此不会触发模型事件。因此,在这种情况下,不会为您的回复触发删除事件:$thread->Replies->delete。这是对数据库的直接删除查询。您必须在应答和调用delete之间旋转,以便为每个应答触发模型事件
简而言之,不要这样做,让您的其他侦听器处理删除记录的操作。您在线程实例上调用delete的代码在哪里?在“thread.php”中,如发布的那样,在引导方法中否,在控制器中或某个地方,您在线程实例上调用delete。。。其中是删除线程编辑问题并添加提示的代码。我现在得到答复了。
<?php
namespace App\Http\Controllers;
use App\Filters\ThreadFilters;
use Illuminate\Http\Request;
use App\Thread;
use App\Channel;
use Auth;
class ThreadsController extends Controller
{
public function __construct() {
$this->middleware('auth')->except(['index', 'show']);
}
/**
* Display a listing of the resource.
*
* @param Channel $channel
* @param \App\Http\Controllers\ThreadFilters $filter
* @return \Illuminate\Http\Response
*/
public function index(Channel $channel, ThreadFilters $filter)
{
$threads = $this->getThread($channel, $filter);
if(request()->wantsJson()) {
return $threads;
}
return view('threads.index', compact('threads'));
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
return view('threads.create');
}
/**
// * Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$this->validate(request(), [
'title' =>'required',
'body' => 'required',
'channel_id' => 'required|exists:channels,id'
]);
$thread = Thread::create([
'user_id' => Auth::user()->id,
'channel_id' => request('channel_id'),
'title' => request('title'),
'body' => request('body')
]);
return redirect($thread->path());
}
/**
* Display the specified resource.
*
* @param int $id
*/
public function show($channelSlug, Thread $thread)
{
return view('threads.show', [
'thread' => $thread,
'replies' => $thread->replies()->paginate(25)
]);
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param int $channel
* @return \Illuminate\Http\Response
*/
public function destroy($channel, Thread $thread)
{
$this->authorize("update", $thread);
$thread->replies()->delete();
$thread->delete();
if(request()->wantsJson()) {
return response([], 204);
}
return redirect(page_url('forum','/threads'));
}
protected function getThread(Channel $channel, ThreadFilters $filter) {
$threads = Thread::latest()->filter($filter);
if($channel->exists) {
$threads->where('channel_id', $channel->id);
}
return $threads->get();
}
}
<?php
namespace App\Http\Controllers;
use App\Filters\ThreadFilters;
use Illuminate\Http\Request;
use App\Thread;
use App\Channel;
use Auth;
class ThreadsController extends Controller
{
public function __construct() {
$this->middleware('auth')->except(['index', 'show']);
}
/**
* Display a listing of the resource.
*
* @param Channel $channel
* @param \App\Http\Controllers\ThreadFilters $filter
* @return \Illuminate\Http\Response
*/
public function index(Channel $channel, ThreadFilters $filter)
{
$threads = $this->getThread($channel, $filter);
if(request()->wantsJson()) {
return $threads;
}
return view('threads.index', compact('threads'));
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
return view('threads.create');
}
/**
// * Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$this->validate(request(), [
'title' =>'required',
'body' => 'required',
'channel_id' => 'required|exists:channels,id'
]);
$thread = Thread::create([
'user_id' => Auth::user()->id,
'channel_id' => request('channel_id'),
'title' => request('title'),
'body' => request('body')
]);
return redirect($thread->path());
}
/**
* Display the specified resource.
*
* @param int $id
*/
public function show($channelSlug, Thread $thread)
{
return view('threads.show', [
'thread' => $thread,
'replies' => $thread->replies()->paginate(25)
]);
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param int $channel
* @return \Illuminate\Http\Response
*/
public function destroy($channel, Thread $thread)
{
$this->authorize("update", $thread);
$thread->replies()->delete();
$thread->delete();
if(request()->wantsJson()) {
return response([], 204);
}
return redirect(page_url('forum','/threads'));
}
protected function getThread(Channel $channel, ThreadFilters $filter) {
$threads = Thread::latest()->filter($filter);
if($channel->exists) {
$threads->where('channel_id', $channel->id);
}
return $threads->get();
}
}
PHPUnit 7.5.18 by Sebastian Bergmann and contributors.
.
................F............ 30 / 30 (100%)
Time: 15.02 seconds, Memory: 30.00 MB
There was 1 failure:
1) Tests\Feature\CreateThreadsTest::test_authorized_users_can_delete_threads
Failed asserting that a row in the table [activities] does not match the attributes {
"subject_id": 1,
"subject_type": "App\\Reply"
}.
Found: [
{
"id": "2",
"user_id": "1",
"subject_type": "App\\Reply",
"subject_id": "1",
"type": "created_reply",
"created_at": "2019-12-23 20:26:03",
"updated_at": "2019-12-23 20:26:03"
}
].
/home/vagrant/Code/intransportal/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/InteractsWithDatabase.php:44
/home/vagrant/Code/intransportal/tests/Feature/CreateThreadsTest.php:75
$thread->replies()->delete();
$thread->delete();
static::deleting(function ($thread) {
$thread->replies->each(function($reply) {
dd($reply);
$reply->delete();
});
});