2
votes

I am trying to load a relationship for a model that is retrieved using route model binding via the load() method, but it doesn't seem to work. Any ideas on what I am doing wrong?

public function update(UpdateOrganisationFormRequest $request, Organisation $organisation)
{
    $organisation->load('contacts');

    dd(
        $organisation->contacts, // returns empty collection
        Organisation::first()->contacts // returns values I generated via factory
    );
}

These answers suggest that this is the correct way to do this:

Eager loading with route model binding

Laravel Route model binding with relaionship

https://laracasts.com/discuss/channels/laravel/laravel-model-binding-with-eager-loading

Here are my relationship definitions:

class Organisation extends Model
{
    public function contacts()
    {
        return $this->hasMany(OrganisationContact::class);
    }
}

class OrganisationContact extends Model
{
    public function organisation()
    {
        return $this->belongsTo(Organisation::class);
    }
}

I have considered Customizing The Resolution Logic but seems a little overkill as I only need some relationships loaded for this update process.

Any help would be appreciated! Thank you.

Update

Thanks to the comments I realised that the route model binding is not returning anything. For some further context... I am running a test where I generate an Organisation model, then hitting the update route for this resource, the code looks like this:

Test class:

/** @test */
public function existing_organisation_can_be_updated()
{
    // Arrange
    $organisation = factory(Organisation::class)->create();

    factory(OrganisationContact::class)->create([
        'organisation_id' => $organisation->id,
    ]);

    /*
        note:
        dd( route('admin.organisation.update', $organisation->id) )
        produces: "http://mydevurl.dev/admin/organisation/1"
    */

    // Act
    $response = $this->put(route('admin.organisation.update', $organisation->id), [
        'name' => 'New name',
    ]);

    // ... assertions and other stuff
}

Resource controller

public function update(UpdateOrganisationFormRequest $request, Organisation $organisation)
{
    // this return null ???
    dd(
        $organisation->id    
    );

    // update logic ...
}

Update 2 - schema

_create_organisations_table.php

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateOrganisationsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('organisations', function (Blueprint $table) {
            $table->increments('id');
            // some other fields
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('organisations');
    }
}

_create_organisation_contacts

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateOrganisationContacts extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('organisation_contacts', function (Blueprint $table) {
            $table->increments('id');
            // some other fields
            $table->timestamps();

            // the relationship
            $table->foreign('organisation_id')->references('id')->on('organisations')->onDelete('cascade');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('organisation_contacts');
    }
}
1
Are you sure that $organisation from parameter and Organisation::first() are the same? - Laerte
Show your schema, please. You may also want to check if that particular organization has any contacts. - aynber
try this Organisation::find($organisation->id)->contacts and see if there are some !! - Maraboc
Ahhh it's because I had the WithoutMiddleware trait being used which pulled out the binding which is managed via the middleware - haakym
You ffigureitout your self ;) nice ! - Maraboc

1 Answers

2
votes

The Organisation model is not retrieved via route model bindings because the WithoutMiddleware trait is being used in the test!

As of Laravel 5.3 route model binding is accomplished via Middleware:

Binding Substitution Middleware

Route model binding is now accomplished using middleware. All applications should add the Illuminate\Routing\Middleware\SubstituteBindings to your web middleware group in your app/Http/Kernel.php file

...

https://laravel.com/docs/5.3/upgrade#upgrade-5.3.0

By using the WithoutMiddleware trait you are stopping the route model binding from being triggered.

Remove the WithoutMiddleware for it to function as expected.

See further discussion here: https://github.com/laravel/framework/issues/15163