diff --git a/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php b/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php index 5c93b8f8c111..465e761993a0 100755 --- a/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php +++ b/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php @@ -634,7 +634,7 @@ public function firstOrCreate(array $attributes, array $joining = [], $touch = t public function updateOrCreate(array $attributes, array $values = [], array $joining = [], $touch = true) { if (is_null($instance = $this->where($attributes)->first())) { - return $this->create($values, $joining, $touch); + return $this->create(array_merge($attributes, $values), $joining, $touch); } $instance->fill($values); diff --git a/tests/Database/DatabaseEloquentBelongsToManyTest.php b/tests/Database/DatabaseEloquentBelongsToManyTest.php new file mode 100644 index 000000000000..d2a0ae14f88f --- /dev/null +++ b/tests/Database/DatabaseEloquentBelongsToManyTest.php @@ -0,0 +1,138 @@ +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->id('id'); + }); + + $this->schema()->create('articles', function ($table) { + $table->id('id'); + + $table->string('title'); + $table->string('description'); + }); + + $this->schema()->create('article_user', function ($table) { + $table->foreignId('article_id')->references('id')->on('articles'); + $table->foreignId('user_id')->references('id')->on('users'); + }); + } + + /** + * Tear down the database schema. + * + * @return void + */ + protected function tearDown(): void + { + $this->schema()->drop('users'); + $this->schema()->drop('articles'); + $this->schema()->drop('article_user'); + } + + public function testCreateWithDesiredAttributesUsingUpdateOrCreate() + { + /** @var FakeUpdateOrCreateUser $user */ + $user = FakeUpdateOrCreateUser::create(); + + $user->articles()->updateOrCreate( + ['title' => 'Fixing UpdateOrCreate'], + ['description' => 'Fixed'] + ); + + $article = $user->articles()->first(); + + $this->assertSame($article->description, 'Fixed'); + } + + public function testUpdateWithDesiredAttributesUsingUpdateOrCreate() + { + /** @var FakeUpdateOrCreateUser $user */ + $user = FakeUpdateOrCreateUser::create(); + $user->articles()->create([ + 'title' => $title = 'Fixing UpdateOrCreate', + 'description' => 'Not fixed', + ]); + + $user->articles()->updateOrCreate( + ['title' => $title], + ['description' => 'Fixed'] + ); + + $article = $user->articles()->first(); + + $this->assertSame($article->description, 'Fixed'); + } + + /** + * Get a database connection instance. + * + * @return \Illuminate\Database\ConnectionInterface + */ + protected function connection() + { + return Model::getConnectionResolver()->connection(); + } + + /** + * Get a schema builder instance. + * + * @return \Illuminate\Database\Schema\Builder + */ + protected function schema() + { + return $this->connection()->getSchemaBuilder(); + } +} + +class FakeUpdateOrCreateUser extends Model +{ + protected $table = 'users'; + + protected $fillable = ['email']; + + public $timestamps = false; + + public function articles() + { + return $this->belongsToMany(FakeUpdateOrCreateArticle::class, 'article_user', 'user_id', 'article_id'); + } +} + +class FakeUpdateOrCreateArticle extends Model +{ + protected $table = 'articles'; + + public $timestamps = false; + + protected $fillable = ['title', 'description']; +}