diff --git a/src/Illuminate/Database/Query/Builder.php b/src/Illuminate/Database/Query/Builder.php index 43069c8a2506..cd54e41774ba 100755 --- a/src/Illuminate/Database/Query/Builder.php +++ b/src/Illuminate/Database/Query/Builder.php @@ -1439,13 +1439,14 @@ public function orWhereRowValues($columns, $operator, $values) * @param string $column * @param mixed $value * @param string $boolean + * @param bool $not * @return $this */ - public function whereJsonContains($column, $value, $boolean = 'and') + public function whereJsonContains($column, $value, $boolean = 'and', $not = false) { $type = 'JsonContains'; - $this->wheres[] = compact('type', 'column', 'value', 'boolean'); + $this->wheres[] = compact('type', 'column', 'value', 'boolean', 'not'); if (! $value instanceof Expression) { $this->addBinding(json_encode($value)); @@ -1466,6 +1467,31 @@ public function orWhereJsonContains($column, $value) return $this->whereJsonContains($column, $value, 'or'); } + /** + * Add a "where JSON not contains" clause to the query. + * + * @param string $column + * @param mixed $value + * @param string $boolean + * @return $this + */ + public function whereJsonNotContains($column, $value, $boolean = 'and') + { + return $this->whereJsonContains($column, $value, $boolean, true); + } + + /** + * Add a "or where JSON not contains" clause to the query. + * + * @param string $column + * @param mixed $value + * @return $this + */ + public function orWhereJsonNotContains($column, $value) + { + return $this->whereJsonNotContains($column, $value, 'or'); + } + /** * Handles dynamic "where" clauses to the query. * diff --git a/src/Illuminate/Database/Query/Grammars/Grammar.php b/src/Illuminate/Database/Query/Grammars/Grammar.php index c3d5e5f4c606..8aba3dab35ba 100755 --- a/src/Illuminate/Database/Query/Grammars/Grammar.php +++ b/src/Illuminate/Database/Query/Grammars/Grammar.php @@ -499,7 +499,9 @@ protected function whereRowValues(Builder $query, $where) */ protected function whereJsonContains(Builder $query, $where) { - return $this->compileJsonContains( + $not = $where['not'] ? 'not ' : ''; + + return $not.$this->compileJsonContains( $this->wrap($where['column']), $this->parameter($where['value']) ); } diff --git a/tests/Database/DatabaseQueryBuilderTest.php b/tests/Database/DatabaseQueryBuilderTest.php index 01dcc81527d1..998c82194144 100755 --- a/tests/Database/DatabaseQueryBuilderTest.php +++ b/tests/Database/DatabaseQueryBuilderTest.php @@ -2656,6 +2656,50 @@ public function testWhereJsonContainsSqlServer() $builder->select('*')->from('users')->whereJsonContains('options->languages', ['en'])->toSql(); } + public function testWhereJsonNotContainsMySql() + { + $builder = $this->getMySqlBuilder(); + $builder->select('*')->from('users')->whereJsonNotContains('options->languages', ['en']); + $this->assertEquals('select * from `users` where not json_contains(`options`->\'$."languages"\', ?)', $builder->toSql()); + $this->assertEquals(['["en"]'], $builder->getBindings()); + + $builder = $this->getMySqlBuilder(); + $builder->select('*')->from('users')->where('id', '=', 1)->orWhereJsonNotContains('options->languages', new Raw("'[\"en\"]'")); + $this->assertEquals('select * from `users` where `id` = ? or not json_contains(`options`->\'$."languages"\', \'["en"]\')', $builder->toSql()); + $this->assertEquals([1], $builder->getBindings()); + } + + public function testWhereJsonNotContainsPostgres() + { + $builder = $this->getPostgresBuilder(); + $builder->select('*')->from('users')->whereJsonNotContains('options->languages', ['en']); + $this->assertEquals('select * from "users" where not ("options"->\'languages\')::jsonb @> ?', $builder->toSql()); + $this->assertEquals(['["en"]'], $builder->getBindings()); + + $builder = $this->getPostgresBuilder(); + $builder->select('*')->from('users')->where('id', '=', 1)->orWhereJsonNotContains('options->languages', new Raw("'[\"en\"]'")); + $this->assertEquals('select * from "users" where "id" = ? or not ("options"->\'languages\')::jsonb @> \'["en"]\'', $builder->toSql()); + $this->assertEquals([1], $builder->getBindings()); + } + + /** + * @expectedException \RuntimeException + */ + public function testWhereJsonNotContainsSqlite() + { + $builder = $this->getSQLiteBuilder(); + $builder->select('*')->from('users')->whereJsonNotContains('options->languages', ['en'])->toSql(); + } + + /** + * @expectedException \RuntimeException + */ + public function testWhereJsonNotContainsSqlServer() + { + $builder = $this->getSqlServerBuilder(); + $builder->select('*')->from('users')->whereJsonNotContains('options->languages', ['en'])->toSql(); + } + public function testFromSub() { $builder = $this->getBuilder();