Skip to content

[5.6] Add Collection::loadMissing() - #24166

Merged
taylorotwell merged 2 commits into
laravel:5.6from
staudenmeir:load-missing
May 14, 2018
Merged

[5.6] Add Collection::loadMissing()#24166
taylorotwell merged 2 commits into
laravel:5.6from
staudenmeir:load-missing

Conversation

@staudenmeir

Copy link
Copy Markdown
Contributor

We currently have Model::loadMissing(), which can only handle non-nested relationships and doesn't fully support loading specific columns.

This PR adds Collection::loadMissing():

$posts = Post::with('comments')->get();
$posts->loadMissing('comments.parent');

The shortest way (I know) to achieve the same right now:

(new \Illuminate\Database\Eloquent\Collection($posts->pluck('comments')->collapse()))->load('parent');

Collection::loadMissing() fully supports nested relationships and loading specific columns. There's no support for closures yet (Model::loadMissing() doesn't support closures either).

We can use it to bring the same features to Model::loadMissing().

I added integration tests for both methods.

Fixes #23027 and #24121.

@bepsvpt

bepsvpt commented May 24, 2018

Copy link
Copy Markdown
Contributor

This pull request is breaking change.

Before this pull request, when loading relation with ambiguous column name, we can use dot to specific table name of the ambiguous column.

How to reproduce:

Assume there are User and Role two models and their relation is many-to-many.

User::create();
Role::create();

User::first()->roles()->attach(Role::first());

User::first()->loadMissing('roles:id'); // this will cause `ambiguous column name: id`

// Before this pull request, we can use roles.id to fix this problem.
// However, after this pull request, it will result in `RelationNotFoundException`
User::first()->loadMissing('roles:roles.id'); 

db46f64

db46f64

27b1652

27b1652


users, roles and role_user table migrations

Details
<?php

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

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

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}
<?php

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

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

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('roles');
    }
}
<?php

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

class CreateRoleUserTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('role_user', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('role_id')->unsigned();
            $table->integer('user_id')->unsigned();

            $table->unique(['role_id', 'user_id']);
        });
    }

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

user and role models

Details
<?php

namespace App;

use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
     */
    public function roles()
    {
        return $this->belongsToMany(Role::class);
    }
}
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Role extends Model
{
    //
}

@staudenmeir

Copy link
Copy Markdown
Contributor Author

Sorry about that. Here's the fix: #24329

@bepsvpt

bepsvpt commented May 27, 2018

Copy link
Copy Markdown
Contributor

Thanks a lot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants