Skip to content

Commit

Permalink
fix(Eloquent/Builder): calling the methods on passthru base object sh…
Browse files Browse the repository at this point in the history
…ould be case-insensitive

Fixes: laravel#48825
  • Loading branch information
luka-papez committed Oct 29, 2023
1 parent 85a5146 commit 6290de8
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 15 deletions.
33 changes: 18 additions & 15 deletions src/Illuminate/Database/Eloquent/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ class Builder implements BuilderContract
/**
* The methods that should be returned from query builder.
*
* Note that the names in the array need to be lowercase so that PHP's case-insensitivity
* regarding method calls can be achieved when forwarding the call to the base object.
*
* @var string[]
*/
protected $passthru = [
Expand All @@ -97,29 +100,29 @@ class Builder implements BuilderContract
'avg',
'count',
'dd',
'ddRawSql',
'doesntExist',
'doesntExistOr',
'ddrawsql',
'doesntexist',
'doesntexistor',
'dump',
'dumpRawSql',
'dumprawsql',
'exists',
'existsOr',
'existsor',
'explain',
'getBindings',
'getConnection',
'getGrammar',
'getbindings',
'getconnection',
'getgrammar',
'implode',
'insert',
'insertGetId',
'insertOrIgnore',
'insertUsing',
'insertgetid',
'insertorignore',
'insertusing',
'max',
'min',
'raw',
'rawValue',
'rawvalue',
'sum',
'toSql',
'toRawSql',
'tosql',
'torawsql',
];

/**
Expand Down Expand Up @@ -1964,7 +1967,7 @@ public function __call($method, $parameters)
return $this->callNamedScope($method, $parameters);
}

if (in_array($method, $this->passthru)) {
if (in_array(strtolower($method), $this->passthru)) {
return $this->toBase()->{$method}(...$parameters);
}

Expand Down
42 changes: 42 additions & 0 deletions tests/Database/DatabaseEloquentBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2246,6 +2246,48 @@ public function testToRawSql()
$this->assertSame('select * from "users" where "email" = \'foo\'', $builder->toRawSql());
}

public function testPassthruMethodsCallsAreNotCaseSensitive()
{
$query = m::mock(BaseBuilder::class);

$mockResponse = 'select 1';
$query
->shouldReceive('toRawSql')
->andReturn($mockResponse)
->times(3);

$builder = new Builder($query);

$this->assertSame('select 1', $builder->TORAWSQL());
$this->assertSame('select 1', $builder->toRawSql());
$this->assertSame('select 1', $builder->toRawSQL());
}

public function testPassthruArrayElementsMustAllBeLowercase()
{
$builder = new class(m::mock(BaseBuilder::class)) extends Builder
{
// expose protected member for test
public function getPassthru(): array
{
return $this->passthru;
}
};

$passthru = $builder->getPassthru();

foreach ($passthru as $method) {
$lowercaseMethod = strtolower($method);

$this->assertSame(
$lowercaseMethod,
$method,
'Eloquent\\Builder relies on lowercase method names in $passthru array to correctly mimic PHP case-insensitivity on method dispatch.'.
'If you are adding a new method to the $passthru array, make sure the name is lowercased.'
);
}
}

protected function mockConnectionForModel($model, $database)
{
$grammarClass = 'Illuminate\Database\Query\Grammars\\'.$database.'Grammar';
Expand Down

0 comments on commit 6290de8

Please sign in to comment.