Skip to content

Commit

Permalink
[11.x] Accept non-backed enum in database queries (#50674)
Browse files Browse the repository at this point in the history
* Cast non-backed enum in database bindings

* Update enum queries integration tests
  • Loading branch information
gbalduzzi authored Mar 21, 2024
1 parent 075bda5 commit 08772cf
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 1 deletion.
7 changes: 6 additions & 1 deletion src/Illuminate/Database/Query/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
use InvalidArgumentException;
use LogicException;
use RuntimeException;
use UnitEnum;

class Builder implements BuilderContract
{
Expand Down Expand Up @@ -3953,7 +3954,11 @@ public function addBinding($value, $type = 'where')
*/
public function castBinding($value)
{
return $value instanceof BackedEnum ? $value->value : $value;
if ($value instanceof UnitEnum) {
return $value instanceof BackedEnum ? $value->value : $value->name;
}

return $value;
}

/**
Expand Down
10 changes: 10 additions & 0 deletions tests/Database/DatabaseQueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
use RuntimeException;
use stdClass;

include_once 'Enums.php';

class DatabaseQueryBuilderTest extends TestCase
{
protected $called;
Expand Down Expand Up @@ -4474,6 +4476,14 @@ public function testAddBindingWithArrayMergesBindingsInCorrectOrder()
$this->assertEquals(['foo', 'bar', 'baz'], $builder->getBindings());
}

public function testAddBindingWithEnum()
{
$builder = $this->getBuilder();
$builder->addBinding(IntegerStatus::done);
$builder->addBinding([NonBackedStatus::done]);
$this->assertEquals([2, 'done'], $builder->getBindings());
}

public function testMergeBuilders()
{
$builder = $this->getBuilder();
Expand Down
7 changes: 7 additions & 0 deletions tests/Database/Enums.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ enum IntegerStatus: int
case done = 2;
}

enum NonBackedStatus
{
case draft;
case pending;
case done;
}

enum ArrayableStatus: string implements Arrayable
{
case pending = 'pending';
Expand Down
7 changes: 7 additions & 0 deletions tests/Integration/Database/Enums.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ enum IntegerStatus: int
case done = 2;
}

enum NonBackedStatus
{
case draft;
case pending;
case done;
}

enum ArrayableStatus: string implements Arrayable
{
case pending = 'pending';
Expand Down
7 changes: 7 additions & 0 deletions tests/Integration/Database/QueryingWithEnumsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ protected function afterRefreshingDatabase()
$table->increments('id');
$table->string('string_status', 100)->nullable();
$table->integer('integer_status')->nullable();
$table->string('non_backed_status', 100)->nullable();
});
}

Expand All @@ -24,30 +25,36 @@ public function testCanQueryWithEnums()
DB::table('enum_casts')->insert([
'string_status' => 'pending',
'integer_status' => 1,
'non_backed_status' => 'pending',
]);

$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();
$record4 = DB::table('enum_casts')->where('non_backed_status', NonBackedStatus::pending)->first();

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

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

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

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

0 comments on commit 08772cf

Please sign in to comment.