From d101972dcc3ed07cd8bd7575f9792df6b0dad382 Mon Sep 17 00:00:00 2001 From: wivaku Date: Fri, 1 Sep 2023 18:20:43 +0200 Subject: [PATCH] make sure $column is string Native Eloquent allows $column to be stringable(). Not possible when using as array key. --- src/Query/Builder.php | 12 ++++++-- tests/QueryBuilderTest.php | 61 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/src/Query/Builder.php b/src/Query/Builder.php index 6a37e1608..e73ef150a 100644 --- a/src/Query/Builder.php +++ b/src/Query/Builder.php @@ -625,7 +625,7 @@ public function update(array $values, array $options = []) */ public function increment($column, $amount = 1, array $extra = [], array $options = []) { - $query = ['$inc' => [$column => $amount]]; + $query = ['$inc' => [(string) $column => $amount]]; if (! empty($extra)) { $query['$set'] = $extra; @@ -797,9 +797,9 @@ public function push($column, $value = null, $unique = false) } $query = [$operator => $column]; } elseif ($batch) { - $query = [$operator => [$column => ['$each' => $value]]]; + $query = [$operator => [(string) $column => ['$each' => $value]]]; } else { - $query = [$operator => [$column => $value]]; + $query = [$operator => [(string) $column => $value]]; } return $this->performUpdate($query); @@ -1004,8 +1004,14 @@ protected function compileWheres(): array $where['boolean'] = 'or'.(str_ends_with($where['boolean'], 'not') ? ' not' : ''); } + // Column name can be a Stringable object. + if (isset($where['column']) && $where['column'] instanceof \Stringable) { + $where['column'] = (string) $where['column']; + } + // We use different methods to compile different wheres. $method = "compileWhere{$where['type']}"; + $result = $this->{$method}($where); if (str_ends_with($where['boolean'], 'not')) { diff --git a/tests/QueryBuilderTest.php b/tests/QueryBuilderTest.php index 6c4e14f6e..eabdaca1c 100644 --- a/tests/QueryBuilderTest.php +++ b/tests/QueryBuilderTest.php @@ -9,6 +9,7 @@ use Illuminate\Support\Facades\Date; use Illuminate\Support\Facades\DB; use Illuminate\Support\LazyCollection; +use Illuminate\Support\Str; use Illuminate\Testing\Assert; use MongoDB\BSON\ObjectId; use MongoDB\BSON\Regex; @@ -895,4 +896,64 @@ public function testCursor() $this->assertEquals($data[$i]['name'], $result['name']); } } + + public function testStringableColumn() + { + DB::collection('users')->insert([ + ['name' => 'Jane Doe', 'age' => 36, 'birthday' => new UTCDateTime(new \DateTime('1987-01-01 00:00:00'))], + ['name' => 'John Doe', 'age' => 28, 'birthday' => new UTCDateTime(new \DateTime('1995-01-01 00:00:00'))], + ]); + + $nameColumn = Str::of('name'); + $this->assertInstanceOf(\Stringable::class, $nameColumn, 'Ensure we are testing the feature with a Stringable instance'); + + $user = DB::collection('users')->where($nameColumn, 'John Doe')->first(); + $this->assertEquals('John Doe', $user['name']); + + // Test this other document to be sure this is not a random success to data order + $user = DB::collection('users')->where($nameColumn, 'Jane Doe')->orderBy('natural')->first(); + $this->assertEquals('Jane Doe', $user['name']); + + // With an operator + $user = DB::collection('users')->where($nameColumn, '!=', 'Jane Doe')->first(); + $this->assertEquals('John Doe', $user['name']); + + // whereIn and whereNotIn + $user = DB::collection('users')->whereIn($nameColumn, ['John Doe'])->first(); + $this->assertEquals('John Doe', $user['name']); + + $user = DB::collection('users')->whereNotIn($nameColumn, ['John Doe'])->first(); + $this->assertEquals('Jane Doe', $user['name']); + + // whereBetween and whereNotBetween + $ageColumn = Str::of('age'); + $user = DB::collection('users')->whereBetween($ageColumn, [30, 40])->first(); + $this->assertEquals('Jane Doe', $user['name']); + + // whereBetween and whereNotBetween + $ageColumn = Str::of('age'); + $user = DB::collection('users')->whereNotBetween($ageColumn, [30, 40])->first(); + $this->assertEquals('John Doe', $user['name']); + + // whereDate + $birthdayColumn = Str::of('birthday'); + $user = DB::collection('users')->whereDate($birthdayColumn, '1995-01-01')->first(); + $this->assertEquals('John Doe', $user['name']); + + $user = DB::collection('users')->whereDate($birthdayColumn, '<', '1990-01-01') + ->orderBy($birthdayColumn, 'desc')->first(); + $this->assertEquals('Jane Doe', $user['name']); + + $user = DB::collection('users')->whereDate($birthdayColumn, '>', '1990-01-01') + ->orderBy($birthdayColumn, 'asc')->first(); + $this->assertEquals('John Doe', $user['name']); + + $user = DB::collection('users')->whereDate($birthdayColumn, '!=', '1987-01-01')->first(); + $this->assertEquals('John Doe', $user['name']); + + // increment + DB::collection('users')->where($ageColumn, 28)->increment($ageColumn, 1); + $user = DB::collection('users')->where($ageColumn, 29)->first(); + $this->assertEquals('John Doe', $user['name']); + } }