Skip to content

Commit 86aa9c7

Browse files
authored
make sure $column is string (#2593)
Native Eloquent allows $column to be stringable(). Not possible when using as array key.
1 parent 810d0c9 commit 86aa9c7

File tree

2 files changed

+70
-3
lines changed

2 files changed

+70
-3
lines changed

src/Query/Builder.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,7 @@ public function update(array $values, array $options = [])
625625
*/
626626
public function increment($column, $amount = 1, array $extra = [], array $options = [])
627627
{
628-
$query = ['$inc' => [$column => $amount]];
628+
$query = ['$inc' => [(string) $column => $amount]];
629629

630630
if (! empty($extra)) {
631631
$query['$set'] = $extra;
@@ -797,9 +797,9 @@ public function push($column, $value = null, $unique = false)
797797
}
798798
$query = [$operator => $column];
799799
} elseif ($batch) {
800-
$query = [$operator => [$column => ['$each' => $value]]];
800+
$query = [$operator => [(string) $column => ['$each' => $value]]];
801801
} else {
802-
$query = [$operator => [$column => $value]];
802+
$query = [$operator => [(string) $column => $value]];
803803
}
804804

805805
return $this->performUpdate($query);
@@ -1004,8 +1004,14 @@ protected function compileWheres(): array
10041004
$where['boolean'] = 'or'.(str_ends_with($where['boolean'], 'not') ? ' not' : '');
10051005
}
10061006

1007+
// Column name can be a Stringable object.
1008+
if (isset($where['column']) && $where['column'] instanceof \Stringable) {
1009+
$where['column'] = (string) $where['column'];
1010+
}
1011+
10071012
// We use different methods to compile different wheres.
10081013
$method = "compileWhere{$where['type']}";
1014+
10091015
$result = $this->{$method}($where);
10101016

10111017
if (str_ends_with($where['boolean'], 'not')) {

tests/QueryBuilderTest.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Illuminate\Support\Facades\Date;
1010
use Illuminate\Support\Facades\DB;
1111
use Illuminate\Support\LazyCollection;
12+
use Illuminate\Support\Str;
1213
use Illuminate\Testing\Assert;
1314
use MongoDB\BSON\ObjectId;
1415
use MongoDB\BSON\Regex;
@@ -895,4 +896,64 @@ public function testCursor()
895896
$this->assertEquals($data[$i]['name'], $result['name']);
896897
}
897898
}
899+
900+
public function testStringableColumn()
901+
{
902+
DB::collection('users')->insert([
903+
['name' => 'Jane Doe', 'age' => 36, 'birthday' => new UTCDateTime(new \DateTime('1987-01-01 00:00:00'))],
904+
['name' => 'John Doe', 'age' => 28, 'birthday' => new UTCDateTime(new \DateTime('1995-01-01 00:00:00'))],
905+
]);
906+
907+
$nameColumn = Str::of('name');
908+
$this->assertInstanceOf(\Stringable::class, $nameColumn, 'Ensure we are testing the feature with a Stringable instance');
909+
910+
$user = DB::collection('users')->where($nameColumn, 'John Doe')->first();
911+
$this->assertEquals('John Doe', $user['name']);
912+
913+
// Test this other document to be sure this is not a random success to data order
914+
$user = DB::collection('users')->where($nameColumn, 'Jane Doe')->orderBy('natural')->first();
915+
$this->assertEquals('Jane Doe', $user['name']);
916+
917+
// With an operator
918+
$user = DB::collection('users')->where($nameColumn, '!=', 'Jane Doe')->first();
919+
$this->assertEquals('John Doe', $user['name']);
920+
921+
// whereIn and whereNotIn
922+
$user = DB::collection('users')->whereIn($nameColumn, ['John Doe'])->first();
923+
$this->assertEquals('John Doe', $user['name']);
924+
925+
$user = DB::collection('users')->whereNotIn($nameColumn, ['John Doe'])->first();
926+
$this->assertEquals('Jane Doe', $user['name']);
927+
928+
// whereBetween and whereNotBetween
929+
$ageColumn = Str::of('age');
930+
$user = DB::collection('users')->whereBetween($ageColumn, [30, 40])->first();
931+
$this->assertEquals('Jane Doe', $user['name']);
932+
933+
// whereBetween and whereNotBetween
934+
$ageColumn = Str::of('age');
935+
$user = DB::collection('users')->whereNotBetween($ageColumn, [30, 40])->first();
936+
$this->assertEquals('John Doe', $user['name']);
937+
938+
// whereDate
939+
$birthdayColumn = Str::of('birthday');
940+
$user = DB::collection('users')->whereDate($birthdayColumn, '1995-01-01')->first();
941+
$this->assertEquals('John Doe', $user['name']);
942+
943+
$user = DB::collection('users')->whereDate($birthdayColumn, '<', '1990-01-01')
944+
->orderBy($birthdayColumn, 'desc')->first();
945+
$this->assertEquals('Jane Doe', $user['name']);
946+
947+
$user = DB::collection('users')->whereDate($birthdayColumn, '>', '1990-01-01')
948+
->orderBy($birthdayColumn, 'asc')->first();
949+
$this->assertEquals('John Doe', $user['name']);
950+
951+
$user = DB::collection('users')->whereDate($birthdayColumn, '!=', '1987-01-01')->first();
952+
$this->assertEquals('John Doe', $user['name']);
953+
954+
// increment
955+
DB::collection('users')->where($ageColumn, 28)->increment($ageColumn, 1);
956+
$user = DB::collection('users')->where($ageColumn, 29)->first();
957+
$this->assertEquals('John Doe', $user['name']);
958+
}
898959
}

0 commit comments

Comments
 (0)