Skip to content

Commit

Permalink
[8.x] Accept enums for insert update and where (#39492)
Browse files Browse the repository at this point in the history
* accept enums for insert update and where

* fix style

* Update tests/Integration/Database/QueryingWithEnumsTest.php

Co-authored-by: Dries Vints <[email protected]>

* Update tests/Integration/Database/QueryingWithEnumsTest.php

Co-authored-by: Dries Vints <[email protected]>

Co-authored-by: Taylor Otwell <[email protected]>
Co-authored-by: Dries Vints <[email protected]>
  • Loading branch information
3 people authored Nov 5, 2021
1 parent cb46639 commit 1c834e4
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 5 deletions.
34 changes: 29 additions & 5 deletions src/Illuminate/Database/Query/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Illuminate\Database\Query;

use BackedEnum;
use Closure;
use DateTimeInterface;
use Illuminate\Contracts\Support\Arrayable;
Expand Down Expand Up @@ -3258,14 +3259,33 @@ public function addBinding($value, $type = 'where')
}

if (is_array($value)) {
$this->bindings[$type] = array_values(array_merge($this->bindings[$type], $value));
$this->bindings[$type] = collect($this->bindings[$type])
->merge($value)
->map([$this, 'castBinding'])
->values()
->toArray();
} else {
$this->bindings[$type][] = $value;
$this->bindings[$type][] = $this->castBinding($value);
}

return $this;
}

/**
* Cast the given binding value.
*
* @param mixed $value
* @return mixed
*/
public function castBinding($value)
{
if (function_exists('enum_exists') && $value instanceof BackedEnum) {
return $value->value;
}

return $value;
}

/**
* Merge an array of bindings into our bindings.
*
Expand All @@ -3287,9 +3307,13 @@ public function mergeBindings(self $query)
*/
public function cleanBindings(array $bindings)
{
return array_values(array_filter($bindings, function ($binding) {
return ! $binding instanceof Expression;
}));
return collect($bindings)
->reject(function ($binding) {
return $binding instanceof Expression;
})
->map([$this, 'castBinding'])
->values()
->toArray();
}

/**
Expand Down
42 changes: 42 additions & 0 deletions tests/Integration/Database/EloquentModelEnumCastingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,48 @@ public function testEnumsAcceptNullOnSave()
'integer_status' => null,
], DB::table('enum_casts')->where('id', $model->id)->first());
}

public function testFirstOrNew()
{
DB::table('enum_casts')->insert([
'string_status' => 'pending',
'integer_status' => 1,
]);

$model = EloquentModelEnumCastingTestModel::firstOrNew([
'string_status' => StringStatus::pending,
]);

$model2 = EloquentModelEnumCastingTestModel::firstOrNew([
'string_status' => StringStatus::done,
]);

$this->assertTrue($model->exists);
$this->assertFalse($model2->exists);

$model2->save();

$this->assertEquals(StringStatus::done, $model2->string_status);
}

public function testFirstOrCreate()
{
DB::table('enum_casts')->insert([
'string_status' => 'pending',
'integer_status' => 1,
]);

$model = EloquentModelEnumCastingTestModel::firstOrCreate([
'string_status' => StringStatus::pending,
]);

$model2 = EloquentModelEnumCastingTestModel::firstOrCreate([
'string_status' => StringStatus::done,
]);

$this->assertEquals(StringStatus::pending, $model->string_status);
$this->assertEquals(StringStatus::done, $model2->string_status);
}
}

class EloquentModelEnumCastingTestModel extends Model
Expand Down
60 changes: 60 additions & 0 deletions tests/Integration/Database/QueryingWithEnumsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace Illuminate\Tests\Integration\Database;

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

if (PHP_VERSION_ID >= 80100) {
include_once 'Enums.php';
}

/**
* @requires PHP >= 8.1
*/
class QueryingWithEnumsTest extends DatabaseTestCase
{
protected function setUp(): void
{
parent::setUp();

Schema::create('enum_casts', function (Blueprint $table) {
$table->increments('id');
$table->string('string_status', 100)->nullable();
$table->integer('integer_status')->nullable();
});
}

public function testCanQueryWithEnums()
{
DB::table('enum_casts')->insert([
'string_status' => 'pending',
'integer_status' => 1,
]);

$record = DB::table('enum_casts')->where('string_status', StringStatus::pending)->first();
$record2 = DB::table('enum_casts')->where('integer_status', IntegerStatus::pending)->first();
$record3 = DB::table('enum_casts')->whereIn('integer_status', [IntegerStatus::pending])->first();

$this->assertNotNull($record);
$this->assertNotNull($record2);
$this->assertNotNull($record3);
$this->assertEquals('pending', $record->string_status);
$this->assertEquals(1, $record2->integer_status);
}

public function testCanInsertWithEnums()
{
DB::table('enum_casts')->insert([
'string_status' => StringStatus::pending,
'integer_status' => IntegerStatus::pending,
]);

$record = DB::table('enum_casts')->where('string_status', StringStatus::pending)->first();

$this->assertNotNull($record);
$this->assertEquals('pending', $record->string_status);
$this->assertEquals(1, $record->integer_status);
}
}

0 comments on commit 1c834e4

Please sign in to comment.