Php larvel each()闭包未执行

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();

我在跟踪一只Laracast。我正在努力通过我的一项考试。我做了一些调试。在RecordActivity.php中,我目前有以下内容:


        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();
            });
        });