Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

abkrim's avatar
Level 13

Observers not work in testing mode or not work with belongsToMany relations? Mistake?

I have a problem that I can't see my mistake.

Three tables, Subscribers, Campaigns, and the pivot table for the belongsToMany relationship, Campaign_Subscriber

For reasons of my app, the pivot table has some more added

I have created (at the end) a test to see the problem quickly, where you can see that the events of the observer are not reached. I use ray but you can use whatever you don't want to see that none of the events are hit.

Campaign_Subscriber

Schema::create('campaign_subscriber', function (Blueprint $table) {
    $table->unsignedBigInteger('campaign_id');
    $table->foreign('campaign_id', 'campaign_id_fk_4864216')->references('id')->on('campaigns')->onDelete('cascade');
    $table->unsignedBigInteger('subscriber_id');
    $table->foreign('subscriber_id', 'subscriber_id_fk_4864216')->references('id')->on('subscribers')->onDelete('cascade');
    $table->timestamp('subscription_date')->nullable();
    $table->string('activation_code')->nullable()->unique();
    $table->dateTime('expires_at')->nullable();
    $table->dateTime('verified_at')->nullable();
    $table->unsignedTinyInteger('status')->default(array_search('Pendiente', CampaignSubscriber::STATUS_SELECT));
});

##Models

Campaign

public function subscribers(): BelongsToMany
{
    return $this->belongsToMany(Subscriber::class);
}

Subscribers

public function campaigns(): BelongsToMany
    {
        return $this->belongsToMany(Campaign::class);
    }

CampaignSubscriber

public function campaigns()
{
    return $this->belongsTo(Campaign::class);
}

public function subscribers()
{
    return $this->belongsTo(Subscriber::class);
}

Observers

CampaignSubscriberObserver

public function creating(CampaignSubscriber $campaign_subscriber)
{
    ray('Creating CS');
    $campaign_subscriber->subscription_date = Carbon::now()->toDateTimeString();
    $campaign_subscriber->activation_code = Str::random(32);
    $campaign_subscriber->expires_at = Carbon::now()->addSeconds(config('project.expires_hash'));
}

public function created(CampaignSubscriber $campaign_subscriber)
{
    ray('Created CS');
}

EventServiceProvider

public function boot()
{
    CampaignSubscriber::observe(CampaignSubscriberObserver::class);
    Campaign::observe(CampaignObserver::class);
    Subscriber::observe(SubscriberObserver::class);
}

Create a test for verify problem

<?php

namespace Tests\Unit;

use App\Models\Campaign;
use App\Models\CampaignSubscriber;
use App\Models\Subscriber;
use Tests\TestCase;

class RelationshipsTest extends TestCase
{
    /** @test */
    function working_with_belongs_to_many_relations()
    {
        $campaign = Campaign::factory()->create();
        $subscriber = Subscriber::factory()->create();
        $subscriber2 = Subscriber::factory()->create();

        ray($campaign, $subscriber);

        $campaign->subscribers()->attach($subscriber->id);

        $cs = CampaignSubscriber::where([
            ['campaign_id', $campaign->id],
            ['subscriber_id', $subscriber->id]
        ])->first();

        ray($cs);

        $campaign->subscribers()->attach($subscriber2->id);

        $cs = CampaignSubscriber::where([
            ['campaign_id', $campaign->id],
        ])->get();

        ray($cs);
    }
}
0 likes
3 replies
rodrigo.pedra's avatar
Level 56

You need to tell Laravel to use the CampaignSubscriber model when hydrating the pivot records for the many-to-many relation, something like this:

public function subscribers(): BelongsToMany
{
    return $this->belongsToMany(Subscriber::class)->using(CampaignSubscriber::class);
}
public function campaigns(): BelongsToMany
{
    return $this->belongsToMany(Campaign::class)->using(CampaignSubscriber::class);
}

Also note that the CampaignSubscriber class should extend Illuminate\Database\Eloquent\Relations\Pivot and not \Illuminate\Database\Eloquent\Model.

Reference:

https://laravel.com/docs/8.x/eloquent-relationships#defining-custom-intermediate-table-models

1 like
abkrim's avatar
Level 13

@rodrigo.pedra A lot of thanks. Tons on searchs, write code for workaorund the problem.

I don't see on my last read of manual, must be extend with Pivot.... and fail put using() on my model because this.

šŸ‘šŸ‘šŸ‘šŸ‘šŸ‘šŸ‘šŸ‘

1 like

Please or to participate in this conversation.