From 757be73cafd0d9afc86143db3241495bd5517d82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leo=20Sj=C3=B6berg?= Date: Tue, 9 May 2017 13:33:12 +0100 Subject: [PATCH] Add a second local key to HasManyThrough (#19114) --- .../Eloquent/Concerns/HasRelationships.php | 7 +- .../Eloquent/Relations/HasManyThrough.php | 21 +- ...eEloquentHasManyThroughIntegrationTest.php | 413 ++++++++++++++++++ .../DatabaseEloquentHasManyThroughTest.php | 326 -------------- 4 files changed, 438 insertions(+), 329 deletions(-) create mode 100644 tests/Database/DatabaseEloquentHasManyThroughIntegrationTest.php delete mode 100644 tests/Database/DatabaseEloquentHasManyThroughTest.php diff --git a/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php b/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php index 8b90f08eabc2..d5599da4378c 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php +++ b/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php @@ -236,9 +236,10 @@ public function hasMany($related, $foreignKey = null, $localKey = null) * @param string|null $firstKey * @param string|null $secondKey * @param string|null $localKey + * @param string|null $secondLocalKey * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough */ - public function hasManyThrough($related, $through, $firstKey = null, $secondKey = null, $localKey = null) + public function hasManyThrough($related, $through, $firstKey = null, $secondKey = null, $localKey = null, $secondLocalKey = null) { $through = new $through; @@ -248,9 +249,11 @@ public function hasManyThrough($related, $through, $firstKey = null, $secondKey $localKey = $localKey ?: $this->getKeyName(); + $secondLocalKey = $secondLocalKey ?: $through->getKeyName(); + $instance = $this->newRelatedInstance($related); - return new HasManyThrough($instance->newQuery(), $this, $through, $firstKey, $secondKey, $localKey); + return new HasManyThrough($instance->newQuery(), $this, $through, $firstKey, $secondKey, $localKey, $secondLocalKey); } /** diff --git a/src/Illuminate/Database/Eloquent/Relations/HasManyThrough.php b/src/Illuminate/Database/Eloquent/Relations/HasManyThrough.php index 3fb7a7cc255e..13f2b70a09fd 100644 --- a/src/Illuminate/Database/Eloquent/Relations/HasManyThrough.php +++ b/src/Illuminate/Database/Eloquent/Relations/HasManyThrough.php @@ -45,6 +45,13 @@ class HasManyThrough extends Relation */ protected $localKey; + /** + * The local key on the intermediary model. + * + * @var string + */ + protected $secondLocalKey; + /** * Create a new has many through relationship instance. * @@ -54,15 +61,17 @@ class HasManyThrough extends Relation * @param string $firstKey * @param string $secondKey * @param string $localKey + * @param string $secondLocalKey * @return void */ - public function __construct(Builder $query, Model $farParent, Model $throughParent, $firstKey, $secondKey, $localKey) + public function __construct(Builder $query, Model $farParent, Model $throughParent, $firstKey, $secondKey, $localKey, $secondLocalKey) { $this->localKey = $localKey; $this->firstKey = $firstKey; $this->secondKey = $secondKey; $this->farParent = $farParent; $this->throughParent = $throughParent; + $this->secondLocalKey = $secondLocalKey; parent::__construct($query, $throughParent); } @@ -102,6 +111,16 @@ protected function performJoin(Builder $query = null) } } + /** + * Get the fully qualified parent key name. + * + * @return string + */ + public function getQualifiedParentKeyName() + { + return $this->parent->getTable().'.'.$this->secondLocalKey; + } + /** * Determine whether "through" parent of the relation uses Soft Deletes. * diff --git a/tests/Database/DatabaseEloquentHasManyThroughIntegrationTest.php b/tests/Database/DatabaseEloquentHasManyThroughIntegrationTest.php new file mode 100644 index 000000000000..6b71e2ebc40c --- /dev/null +++ b/tests/Database/DatabaseEloquentHasManyThroughIntegrationTest.php @@ -0,0 +1,413 @@ +addConnection([ + 'driver' => 'sqlite', + 'database' => ':memory:', + ]); + + $db->bootEloquent(); + $db->setAsGlobal(); + + $this->createSchema(); + } + + /** + * Setup the database schema. + * + * @return void + */ + public function createSchema() + { + $this->schema()->create('users', function ($table) { + $table->increments('id'); + $table->string('email')->unique(); + $table->unsignedInteger('country_id'); + $table->string('country_short'); + $table->timestamps(); + $table->softDeletes(); + }); + + $this->schema()->create('posts', function ($table) { + $table->increments('id'); + $table->integer('user_id'); + $table->string('title'); + $table->text('body'); + $table->string('email'); + $table->timestamps(); + }); + + $this->schema()->create('countries', function ($table) { + $table->increments('id'); + $table->string('name'); + $table->string('shortname'); + $table->timestamps(); + }); + } + + /** + * Tear down the database schema. + * + * @return void + */ + public function tearDown() + { + $this->schema()->drop('users'); + $this->schema()->drop('posts'); + $this->schema()->drop('countries'); + } + + public function testItLoadsAHasManyThroughRelationWithCustomKeys() + { + $this->seedData(); + $posts = HasManyThroughTestCountry::first()->posts; + + $this->assertEquals('A title', $posts[0]->title); + $this->assertCount(2, $posts); + } + + public function testItLoadsADefaultHasManyThroughRelation() + { + $this->migrateDefault(); + $this->seedDefaultData(); + + $posts = HasManyThroughDefaultTestCountry::first()->posts; + $this->assertEquals('A title', $posts[0]->title); + $this->assertCount(2, $posts); + + $this->resetDefault(); + } + + public function testItLoadsARelationWithCustomIntermediateAndLocalKey() + { + $this->seedData(); + $posts = HasManyThroughIntermediateTestCountry::first()->posts; + + $this->assertEquals('A title', $posts[0]->title); + $this->assertCount(2, $posts); + } + + /** + * @expectedException \Illuminate\Database\Eloquent\ModelNotFoundException + */ + public function testFirstOrFailThrowsAnException() + { + HasManyThroughTestCountry::create(['id' => 1, 'name' => 'United States of America', 'shortname' => 'us']) + ->users()->create(['id' => 1, 'email' => 'taylorotwell@gmail.com', 'country_short' => 'us']); + + HasManyThroughTestCountry::first()->posts()->firstOrFail(); + } + + /** + * @expectedException \Illuminate\Database\Eloquent\ModelNotFoundException + */ + public function testFindOrFailThrowsAnException() + { + HasManyThroughTestCountry::create(['id' => 1, 'name' => 'United States of America', 'shortname' => 'us']) + ->users()->create(['id' => 1, 'email' => 'taylorotwell@gmail.com', 'country_short' => 'us']); + + HasManyThroughTestCountry::first()->posts()->findOrFail(1); + } + + public function testFirstRetrievesFirstRecord() + { + $this->seedData(); + $post = HasManyThroughTestCountry::first()->posts()->first(); + + $this->assertNotNull($post); + $this->assertEquals('A title', $post->title); + } + + public function testAllColumnsAreRetrievedByDefault() + { + $this->seedData(); + $post = HasManyThroughTestCountry::first()->posts()->first(); + + $this->assertEquals([ + 'id', + 'user_id', + 'title', + 'body', + 'email', + 'created_at', + 'updated_at', + 'country_id', + ], array_keys($post->getAttributes())); + } + + public function testOnlyProperColumnsAreSelectedIfProvided() + { + $this->seedData(); + $post = HasManyThroughTestCountry::first()->posts()->first(['title', 'body']); + + $this->assertEquals([ + 'title', + 'body', + 'country_id', + ], array_keys($post->getAttributes())); + } + + public function testIntermediateSoftDeletesAreIgnored() + { + $this->seedData(); + HasManyThroughSoftDeletesTestUser::first()->delete(); + + $posts = HasManyThroughSoftDeletesTestCountry::first()->posts; + + $this->assertEquals('A title', $posts[0]->title); + $this->assertCount(2, $posts); + } + + public function testEagerLoadingLoadsRelatedModelsCorrectly() + { + $this->seedData(); + $country = HasManyThroughSoftDeletesTestCountry::with('posts')->first(); + + $this->assertEquals('us', $country->shortname); + $this->assertEquals('A title', $country->posts[0]->title); + $this->assertCount(2, $country->posts); + } + + /** + * Helpers... + */ + protected function seedData() + { + HasManyThroughTestCountry::create(['id' => 1, 'name' => 'United States of America', 'shortname' => 'us']) + ->users()->create(['id' => 1, 'email' => 'taylorotwell@gmail.com', 'country_short' => 'us']) + ->posts()->createMany([ + ['title' => 'A title', 'body' => 'A body', 'email' => 'taylorotwell@gmail.com'], + ['title' => 'Another title', 'body' => 'Another body', 'email' => 'taylorotwell@gmail.com'], + ]); + } + + /** + * Seed data for a default HasManyThrough setup. + */ + protected function seedDefaultData() + { + HasManyThroughDefaultTestCountry::create(['id' => 1, 'name' => 'United States of America']) + ->users()->create(['id' => 1, 'email' => 'taylorotwell@gmail.com']) + ->posts()->createMany([ + ['title' => 'A title', 'body' => 'A body'], + ['title' => 'Another title', 'body' => 'Another body'], + ]); + } + + /** + * Drop the default tables. + */ + protected function resetDefault() + { + $this->schema()->drop('users_default'); + $this->schema()->drop('posts_default'); + $this->schema()->drop('countries_default'); + } + + /** + * Migrate tables for classes with a Laravel "default" HasManyThrough setup. + */ + protected function migrateDefault() + { + $this->schema()->create('users_default', function ($table) { + $table->increments('id'); + $table->string('email')->unique(); + $table->unsignedInteger('has_many_through_default_test_country_id'); + $table->timestamps(); + }); + + $this->schema()->create('posts_default', function ($table) { + $table->increments('id'); + $table->integer('has_many_through_default_test_user_id'); + $table->string('title'); + $table->text('body'); + $table->timestamps(); + }); + + $this->schema()->create('countries_default', function ($table) { + $table->increments('id'); + $table->string('name'); + $table->timestamps(); + }); + } + + /** + * Get a database connection instance. + * + * @return Connection + */ + protected function connection() + { + return Eloquent::getConnectionResolver()->connection(); + } + + /** + * Get a schema builder instance. + * + * @return Schema\Builder + */ + protected function schema() + { + return $this->connection()->getSchemaBuilder(); + } +} + +/** + * Eloquent Models... + */ +class HasManyThroughTestUser extends Eloquent +{ + protected $table = 'users'; + protected $guarded = []; + + public function posts() + { + return $this->hasMany(HasManyThroughTestPost::class, 'user_id'); + } +} + +/** + * Eloquent Models... + */ +class HasManyThroughTestPost extends Eloquent +{ + protected $table = 'posts'; + protected $guarded = []; + + public function owner() + { + return $this->belongsTo(HasManyThroughTestUser::class, 'user_id'); + } +} + +class HasManyThroughTestCountry extends Eloquent +{ + protected $table = 'countries'; + protected $guarded = []; + + public function posts() + { + return $this->hasManyThrough(HasManyThroughTestPost::class, HasManyThroughTestUser::class, 'country_id', 'user_id'); + } + + public function users() + { + return $this->hasMany(HasManyThroughTestUser::class, 'country_id'); + } +} + +/** + * Eloquent Models... + */ +class HasManyThroughDefaultTestUser extends Eloquent +{ + protected $table = 'users_default'; + protected $guarded = []; + + public function posts() + { + return $this->hasMany(HasManyThroughDefaultTestPost::class); + } +} + +/** + * Eloquent Models... + */ +class HasManyThroughDefaultTestPost extends Eloquent +{ + protected $table = 'posts_default'; + protected $guarded = []; + + public function owner() + { + return $this->belongsTo(HasManyThroughDefaultTestUser::class); + } +} + +class HasManyThroughDefaultTestCountry extends Eloquent +{ + protected $table = 'countries_default'; + protected $guarded = []; + + public function posts() + { + return $this->hasManyThrough(HasManyThroughDefaultTestPost::class, HasManyThroughDefaultTestUser::class); + } + + public function users() + { + return $this->hasMany(HasManyThroughDefaultTestUser::class); + } +} + +class HasManyThroughIntermediateTestCountry extends Eloquent +{ + protected $table = 'countries'; + protected $guarded = []; + + public function posts() + { + return $this->hasManyThrough(HasManyThroughTestPost::class, HasManyThroughTestUser::class, 'country_short', 'email', 'shortname', 'email'); + } + + public function users() + { + return $this->hasMany(HasManyThroughTestUser::class, 'country_id'); + } +} + +class HasManyThroughSoftDeletesTestUser extends Eloquent +{ + use SoftDeletes; + + protected $table = 'users'; + protected $guarded = []; + + public function posts() + { + return $this->hasMany(HasManyThroughSoftDeletesTestPost::class, 'user_id'); + } +} + +/** + * Eloquent Models... + */ +class HasManyThroughSoftDeletesTestPost extends Eloquent +{ + protected $table = 'posts'; + protected $guarded = []; + + public function owner() + { + return $this->belongsTo(HasManyThroughSoftDeletesTestUser::class, 'user_id'); + } +} + +class HasManyThroughSoftDeletesTestCountry extends Eloquent +{ + protected $table = 'countries'; + protected $guarded = []; + + public function posts() + { + return $this->hasManyThrough(HasManyThroughSoftDeletesTestPost::class, HasManyThroughTestUser::class, 'country_id', 'user_id'); + } + + public function users() + { + return $this->hasMany(HasManyThroughSoftDeletesTestUser::class, 'country_id'); + } +} diff --git a/tests/Database/DatabaseEloquentHasManyThroughTest.php b/tests/Database/DatabaseEloquentHasManyThroughTest.php deleted file mode 100644 index 6bcbf93c1461..000000000000 --- a/tests/Database/DatabaseEloquentHasManyThroughTest.php +++ /dev/null @@ -1,326 +0,0 @@ -getRelation(); - $model = m::mock('Illuminate\Database\Eloquent\Model'); - $relation->getRelated()->shouldReceive('newCollection')->andReturnUsing(function ($array = []) { - return new Collection($array); - }); - $model->shouldReceive('setRelation')->once()->with('foo', m::type('Illuminate\Database\Eloquent\Collection')); - $models = $relation->initRelation([$model], 'foo'); - - $this->assertEquals([$model], $models); - } - - public function testEagerConstraintsAreProperlyAdded() - { - $relation = $this->getRelation(); - $relation->getQuery()->shouldReceive('whereIn')->once()->with('users.country_id', [1, 2]); - $model1 = new EloquentHasManyThroughModelStub; - $model1->id = 1; - $model2 = new EloquentHasManyThroughModelStub; - $model2->id = 2; - $relation->addEagerConstraints([$model1, $model2]); - } - - public function testEagerConstraintsAreProperlyAddedWithCustomKey() - { - $builder = m::mock('Illuminate\Database\Eloquent\Builder'); - $builder->shouldReceive('join')->once()->with('users', 'users.id', '=', 'posts.user_id'); - $builder->shouldReceive('where')->with('users.country_id', '=', 1); - - $country = m::mock('Illuminate\Database\Eloquent\Model'); - $country->shouldReceive('getKeyName')->andReturn('id'); - $country->shouldReceive('offsetGet')->andReturn(1); - $country->shouldReceive('getForeignKey')->andReturn('country_id'); - - $user = m::mock('Illuminate\Database\Eloquent\Model'); - $user->shouldReceive('getTable')->andReturn('users'); - $user->shouldReceive('getQualifiedKeyName')->andReturn('users.id'); - $post = m::mock('Illuminate\Database\Eloquent\Model'); - $post->shouldReceive('getTable')->andReturn('posts'); - - $builder->shouldReceive('getModel')->andReturn($post); - - $relation = new HasManyThrough($builder, $country, $user, 'country_id', 'user_id', 'not_id'); - $relation->getQuery()->shouldReceive('whereIn')->once()->with('users.country_id', [3, 4]); - $model1 = new EloquentHasManyThroughModelStub; - $model1->id = 1; - $model1->not_id = 3; - $model2 = new EloquentHasManyThroughModelStub; - $model2->id = 2; - $model2->not_id = 4; - $relation->addEagerConstraints([$model1, $model2]); - } - - public function testModelsAreProperlyMatchedToParents() - { - $relation = $this->getRelation(); - - $result1 = new EloquentHasManyThroughModelStub; - $result1->country_id = 1; - $result2 = new EloquentHasManyThroughModelStub; - $result2->country_id = 2; - $result3 = new EloquentHasManyThroughModelStub; - $result3->country_id = 2; - - $model1 = new EloquentHasManyThroughModelStub; - $model1->id = 1; - $model2 = new EloquentHasManyThroughModelStub; - $model2->id = 2; - $model3 = new EloquentHasManyThroughModelStub; - $model3->id = 3; - - $relation->getRelated()->shouldReceive('newCollection')->andReturnUsing(function ($array) { - return new Collection($array); - }); - $models = $relation->match([$model1, $model2, $model3], new Collection([$result1, $result2, $result3]), 'foo'); - - $this->assertEquals(1, $models[0]->foo[0]->country_id); - $this->assertEquals(1, count($models[0]->foo)); - $this->assertEquals(2, $models[1]->foo[0]->country_id); - $this->assertEquals(2, $models[1]->foo[1]->country_id); - $this->assertEquals(2, count($models[1]->foo)); - $this->assertEquals(0, count($models[2]->foo)); - } - - public function testModelsAreProperlyMatchedToParentsWithNonPrimaryKey() - { - $relation = $this->getRelationForNonPrimaryKey(); - - $result1 = new EloquentHasManyThroughModelStub; - $result1->country_id = 1; - $result2 = new EloquentHasManyThroughModelStub; - $result2->country_id = 2; - $result3 = new EloquentHasManyThroughModelStub; - $result3->country_id = 2; - - $model1 = new EloquentHasManyThroughModelStub; - $model1->id = 1; - $model2 = new EloquentHasManyThroughModelStub; - $model2->id = 2; - $model3 = new EloquentHasManyThroughModelStub; - $model3->id = 3; - - $relation->getRelated()->shouldReceive('newCollection')->andReturnUsing(function ($array) { - return new Collection($array); - }); - $models = $relation->match([$model1, $model2, $model3], new Collection([$result1, $result2, $result3]), 'foo'); - - $this->assertEquals(1, $models[0]->foo[0]->country_id); - $this->assertEquals(1, count($models[0]->foo)); - $this->assertEquals(2, $models[1]->foo[0]->country_id); - $this->assertEquals(2, $models[1]->foo[1]->country_id); - $this->assertEquals(2, count($models[1]->foo)); - $this->assertEquals(0, count($models[2]->foo)); - } - - public function testAllColumnsAreSelectedByDefault() - { - $select = ['posts.*', 'users.country_id']; - - $baseBuilder = m::mock('Illuminate\Database\Query\Builder'); - - $relation = $this->getRelation(); - $relation->getRelated()->shouldReceive('newCollection')->once(); - - $builder = $relation->getQuery(); - $builder->shouldReceive('applyScopes')->andReturnSelf(); - $builder->shouldReceive('getQuery')->andReturn($baseBuilder); - $builder->shouldReceive('addSelect')->once()->with($select)->andReturn($builder); - $builder->shouldReceive('getModels')->once()->andReturn([]); - - $relation->get(); - } - - public function testOnlyProperColumnsAreSelectedIfProvided() - { - $select = ['users.country_id']; - - $baseBuilder = m::mock('Illuminate\Database\Query\Builder'); - $baseBuilder->columns = ['foo', 'bar']; - - $relation = $this->getRelation(); - $relation->getRelated()->shouldReceive('newCollection')->once(); - - $builder = $relation->getQuery(); - $builder->shouldReceive('applyScopes')->andReturnSelf(); - $builder->shouldReceive('getQuery')->andReturn($baseBuilder); - $builder->shouldReceive('addSelect')->once()->with($select)->andReturn($builder); - $builder->shouldReceive('getModels')->once()->andReturn([]); - - $relation->get(); - } - - public function testFirstMethod() - { - $relation = m::mock('Illuminate\Database\Eloquent\Relations\HasManyThrough[get]', $this->getRelationArguments()); - $relation->shouldReceive('get')->once()->andReturn(new \Illuminate\Database\Eloquent\Collection(['first', 'second'])); - $relation->shouldReceive('take')->with(1)->once()->andReturn($relation); - - $this->assertEquals('first', $relation->first()); - } - - /** - * @expectedException \Illuminate\Database\Eloquent\ModelNotFoundException - */ - public function testFindOrFailThrowsException() - { - $relation = $this->getMockBuilder('Illuminate\Database\Eloquent\Relations\HasManyThrough')->setMethods(['find'])->setConstructorArgs($this->getRelationArguments())->getMock(); - $relation->expects($this->once())->method('find')->with('foo')->will($this->returnValue(null)); - - try { - $relation->findOrFail('foo'); - } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) { - $this->assertNotEmpty($e->getModel()); - - throw $e; - } - } - - /** - * @expectedException \Illuminate\Database\Eloquent\ModelNotFoundException - */ - public function testFirstOrFailThrowsException() - { - $relation = $this->getMockBuilder('Illuminate\Database\Eloquent\Relations\HasManyThrough')->setMethods(['first'])->setConstructorArgs($this->getRelationArguments())->getMock(); - $relation->expects($this->once())->method('first')->with(['id' => 'foo'])->will($this->returnValue(null)); - - try { - $relation->firstOrFail(['id' => 'foo']); - } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) { - $this->assertNotEmpty($e->getModel()); - - throw $e; - } - } - - public function testFindMethod() - { - $returnValue = new StdClass; - - $relation = m::mock('Illuminate\Database\Eloquent\Relations\HasManyThrough[first]', $this->getRelationArguments()); - $relation->shouldReceive('where')->with('posts.id', '=', 'foo')->once()->andReturn($relation); - $relation->shouldReceive('first')->once()->andReturn($returnValue); - - $related = $relation->getRelated(); - $related->shouldReceive('getQualifiedKeyName')->once()->andReturn('posts.id'); - - $this->assertEquals($returnValue, $relation->find('foo')); - } - - public function testFindManyMethod() - { - $returnValue = new \Illuminate\Database\Eloquent\Collection(['first', 'second']); - - $relation = m::mock('Illuminate\Database\Eloquent\Relations\HasManyThrough[get]', $this->getRelationArguments()); - $relation->shouldReceive('get')->once()->andReturn($returnValue); - $relation->shouldReceive('whereIn')->with('posts.id', ['foo', 'bar'])->once()->andReturn($relation); - - $related = $relation->getRelated(); - $related->shouldReceive('getQualifiedKeyName')->once()->andReturn('posts.id'); - - $this->assertEquals($returnValue, $relation->findMany(['foo', 'bar'])); - } - - public function testIgnoreSoftDeletingParent() - { - list($builder, $country, , $firstKey, $secondKey) = $this->getRelationArguments(); - $user = new EloquentHasManyThroughSoftDeletingModelStub; - - $builder->shouldReceive('whereNull')->with('users.deleted_at')->once()->andReturn($builder); - - $relation = new HasManyThrough($builder, $country, $user, $firstKey, $secondKey, 'id'); - } - - protected function getRelation() - { - list($builder, $country, $user, $firstKey, $secondKey, $overrideKey) = $this->getRelationArguments(); - - return new HasManyThrough($builder, $country, $user, $firstKey, $secondKey, $overrideKey); - } - - protected function getRelationForNonPrimaryKey() - { - list($builder, $country, $user, $firstKey, $secondKey, $overrideKey) = $this->getRelationArgumentsForNonPrimaryKey(); - - return new HasManyThrough($builder, $country, $user, $firstKey, $secondKey, $overrideKey); - } - - protected function getRelationArguments() - { - $builder = m::mock('Illuminate\Database\Eloquent\Builder'); - $builder->shouldReceive('join')->once()->with('users', 'users.id', '=', 'posts.user_id'); - $builder->shouldReceive('where')->with('users.country_id', '=', 1); - - $country = m::mock('Illuminate\Database\Eloquent\Model'); - $country->shouldReceive('getKeyName')->andReturn('id'); - $country->shouldReceive('offsetGet')->andReturn(1); - $country->shouldReceive('getForeignKey')->andReturn('country_id'); - $user = m::mock('Illuminate\Database\Eloquent\Model'); - $user->shouldReceive('getTable')->andReturn('users'); - $user->shouldReceive('getQualifiedKeyName')->andReturn('users.id'); - $post = m::mock('Illuminate\Database\Eloquent\Model'); - $post->shouldReceive('getTable')->andReturn('posts'); - - $builder->shouldReceive('getModel')->andReturn($post); - - $user->shouldReceive('getKey')->andReturn(1); - $user->shouldReceive('getCreatedAtColumn')->andReturn('created_at'); - $user->shouldReceive('getUpdatedAtColumn')->andReturn('updated_at'); - - return [$builder, $country, $user, 'country_id', 'user_id', $country->getKeyName()]; - } - - protected function getRelationArgumentsForNonPrimaryKey() - { - $builder = m::mock('Illuminate\Database\Eloquent\Builder'); - $builder->shouldReceive('join')->once()->with('users', 'users.id', '=', 'posts.user_id'); - $builder->shouldReceive('where')->with('users.country_id', '=', 1); - - $country = m::mock('Illuminate\Database\Eloquent\Model'); - $country->shouldReceive('offsetGet')->andReturn(1); - $country->shouldReceive('getForeignKey')->andReturn('country_id'); - $user = m::mock('Illuminate\Database\Eloquent\Model'); - $user->shouldReceive('getTable')->andReturn('users'); - $user->shouldReceive('getQualifiedKeyName')->andReturn('users.id'); - $post = m::mock('Illuminate\Database\Eloquent\Model'); - $post->shouldReceive('getTable')->andReturn('posts'); - - $builder->shouldReceive('getModel')->andReturn($post); - - $user->shouldReceive('getKey')->andReturn(1); - $user->shouldReceive('getCreatedAtColumn')->andReturn('created_at'); - $user->shouldReceive('getUpdatedAtColumn')->andReturn('updated_at'); - - return [$builder, $country, $user, 'country_id', 'user_id', 'other_id']; - } -} - -class EloquentHasManyThroughModelStub extends \Illuminate\Database\Eloquent\Model -{ - public $country_id = 'foreign.value'; -} - -class EloquentHasManyThroughSoftDeletingModelStub extends \Illuminate\Database\Eloquent\Model -{ - use SoftDeletes; - public $table = 'users'; -}