Skip to content

Commit 7d0a3d3

Browse files
Fix: Handle mixed-type values in compileInsert (#53948)
* Fix: Prevent incorrect handling of single-value inserts by checking if $values itself is a list using `array_is_list` instead of checking if the first element (`reset($values)`) is an array. * Add tests for `compileInsert` with different value structures * Refactor: Improve insert value handling for non-list arrays * formatting * formatting * formatting --------- Co-authored-by: Taylor Otwell <[email protected]>
1 parent 502b489 commit 7d0a3d3

File tree

2 files changed

+82
-2
lines changed

2 files changed

+82
-2
lines changed

src/Illuminate/Database/Query/Grammars/Grammar.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,8 +1168,11 @@ public function compileInsert(Builder $query, array $values)
11681168
return "insert into {$table} default values";
11691169
}
11701170

1171-
if (! is_array(reset($values))) {
1172-
$values = [$values];
1171+
if (! array_is_list($values)) {
1172+
$values = (new Collection(array_keys($values)))
1173+
->some(fn ($key) => ! is_numeric($key))
1174+
? [$values]
1175+
: array_values($values);
11731176
}
11741177

11751178
$columns = $this->columnize(array_keys(reset($values)));

tests/Database/DatabaseQueryGrammarTest.php

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22

33
namespace Illuminate\Tests\Database;
44

5+
use Illuminate\Database\ConnectionInterface;
56
use Illuminate\Database\Query\Builder;
67
use Illuminate\Database\Query\Expression;
78
use Illuminate\Database\Query\Grammars\Grammar;
9+
use Illuminate\Database\Query\Processors\Processor;
810
use Mockery as m;
911
use PHPUnit\Framework\TestCase;
1012
use ReflectionClass;
@@ -41,4 +43,79 @@ public function testWhereRawReturnsStringWhenStringPassed()
4143

4244
$this->assertSame('select * from "users"', $rawQuery);
4345
}
46+
47+
public function testCompileInsertSingleValue()
48+
{
49+
$builder = $this->getBuilder();
50+
$grammar = $builder->getGrammar();
51+
52+
$sql = $grammar->compileInsert($builder, ['name' => 'John Doe', 'email' => '[email protected]']);
53+
$this->assertSame('insert into "users" ("name", "email") values (?, ?)', $sql);
54+
}
55+
56+
public function testCompileInsertMultipleValues()
57+
{
58+
$builder = $this->getBuilder();
59+
$grammar = $builder->getGrammar();
60+
$values = [
61+
['name' => 'John Doe', 'email' => '[email protected]'],
62+
['name' => 'Alice Wong', 'email' => '[email protected]'],
63+
];
64+
65+
$sql = $grammar->compileInsert($builder, $values);
66+
$this->assertSame('insert into "users" ("name", "email") values (?, ?), (?, ?)', $sql);
67+
}
68+
69+
public function testCompileInsertSingleValueWhereFirstKeyIsArray()
70+
{
71+
$builder = $this->getBuilder();
72+
$grammar = $builder->getGrammar();
73+
$value = [
74+
'configuration' => [
75+
'dark_mode' => false,
76+
'language' => 'en',
77+
],
78+
'name' => 'John Doe',
79+
'email' => '[email protected]',
80+
];
81+
82+
$sql = $grammar->compileInsert($builder, $value);
83+
84+
$this->assertSame('insert into "users" ("configuration", "name", "email") values (?, ?, ?)', $sql);
85+
}
86+
87+
public function testCompileInsertSingleValueWhereFirstKeyIsNotArray()
88+
{
89+
$builder = $this->getBuilder();
90+
$grammar = $builder->getGrammar();
91+
92+
$value = [
93+
'name' => 'John Doe',
94+
'configuration' => [
95+
'dark_mode' => false,
96+
'language' => 'en',
97+
],
98+
'email' => '[email protected]',
99+
];
100+
101+
$sql = $grammar->compileInsert($builder, $value);
102+
103+
$this->assertSame('insert into "users" ("name", "configuration", "email") values (?, ?, ?)', $sql);
104+
}
105+
106+
protected function getConnection()
107+
{
108+
return m::mock(ConnectionInterface::class);
109+
}
110+
111+
protected function getBuilder($tableName = 'users')
112+
{
113+
$grammar = new Grammar;
114+
$processor = m::mock(Processor::class);
115+
116+
$builder = new Builder($this->getConnection(), $grammar, $processor);
117+
$builder->from = $tableName;
118+
119+
return $builder;
120+
}
44121
}

0 commit comments

Comments
 (0)