user6188834
user6188834

Reputation:

BadMethodCallException: Method does not exist

I am trying to create a many to many relationship between this profile and an availability table but within my test i keep getting call to a undefined method on availability in the test.

This is the controller function

 /**
 * Creates association between availability and podcast profile
 *
 * @param array $availabilities
 */
private function associateAvailability(array $availabilities)
{
    $this->podcastProfile->availability()->sync(
        array_map(function ($availability) {
            $availabilityModel = Availability::where('availability', '=', $availability)->first();
            return $availabilityModel->id;
        }, $availabilities)
    );
}

This is the method in the podcast profile model

  /**
 * Defines many-to-many relationship between podcasts and availabilities
 */
public function availability(): BelongsToMany
{
    return $this->belongsToMany(
        'App\Models\Availability',
        'podcast_availability',
        'podcast_profile_id',
        'availability_id'
    );
}

This is the test for the method

/**
 * @test
 */
public function it_should_create_availability_relationship()
{
    $this->handlePostRequestToController();
    $this->assertTrue($this->user->podcastProfile->availability()->exists());
    $this->checkAvailability($this->requestData['availability']);
}

this is the check availability method inserted into the test

/**
 * Check database
 *
 * @param $availabilities
 */
private function checkAvailability($availabilities): void
{
    foreach ($availabilities as $availability) {
        $availabilityModel = Availability::where('availability', '=', $availability)
            ->first();

        $this->assertDatabaseHas('podcast_availability', [
            'podcast_profile_id' => $this->user->podcastProfile->id,
            'availability_id' => $availabilityModel->id
        ]);
    }
}

this is the error

1) Tests\Feature\PodcastProfileControllerTest::it_should_create_availability_relationship

BadMethodCallException: Method Illuminate\Database\Eloquent\Collection::availability does not exist.

Upvotes: 1

Views: 2144

Answers (1)

Japs
Japs

Reputation: 1052

If your trying to make a Many to Many relationship base on Laravel Many to Many Relationship.

Here's how you do it. You need to have to 2 models and 3 migrations.

FIRST

Your model should look like this:

Profile Model

protected $guarded = [];

public function availabilities() {
  return $this->belongsToMany(Availability::class);
} 

Note: I use availabilities because it is in a many to many relationship so its a better naming convention.

Availability Model

protected $guarded = [];

public function profiles() {
  return $this->belongsToMany(Profile::class);
}

SECOND

Your migration should be like this:

Profile Migration

Schema::create('profiles', function (Blueprint $table) {
  $table->bigIncrements('id');
  ...
  $table->timestamps();
});

Availability Migration

Schema::create('availabilities', function (Blueprint $table) {
  $table->bigIncrements('id');
  ...
  $table->timestamps();
});

Availability And Profiles Migration

Schema::create('availability_profile', function (Blueprint $table) {
  $table->bigIncrements('id');
  $table->unsignedBigInteger('availability_id');
  $table->unsignedBigInteger('profile_id');
  $table->timestamps();
});

Note: I use the availability_profile naming convention in alphabetical order

INFO

You can generate this migration using artisan command like this php artisan make:migration create_availability_profile_table --create=availability_profile

LAST

In you controller you can assign the profile to availability

Controller

Assuming you have record on your database.

public function generateAvailability() {
  $profile = Profile::firstOrFail(1);
  $role = Role::firstOrFail(1);

  $profile->availabilities()->attach($role->id);

  dd(profile->availabilities);
}

Note: I use dd(dump and die) to check the record

You can also see this reference and this

Upvotes: 1

Related Questions