Skip to content

Commit 3e22fb6

Browse files
authored
test: ✅ Add regression test for contract-only Expression in where(). (#593)
Locks in the fix from PR #590, which switched src/CacheKey.php to import the Illuminate\Contracts\Database\Query\Expression interface instead of the concrete Illuminate\Database\Query\Expression class. Without the fix, custom Expression classes that implement the contract but do not extend the concrete class (e.g. tpetry/laravel-postgresql-enhanced) fall through CacheKey's instanceof checks and trigger an "Object could not be converted to string" fatal at src/CacheKey.php:280 in getOtherClauses(). The new test fixture (ContractOnlyExpression) implements only the contract, and the integration test passes it as the column argument to where() to exercise the formerly-broken code path.
1 parent 099063c commit 3e22fb6

2 files changed

Lines changed: 55 additions & 0 deletions

File tree

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace GeneaLabs\LaravelModelCaching\Tests\Fixtures;
6+
7+
use Illuminate\Contracts\Database\Query\Expression as ExpressionContract;
8+
use Illuminate\Database\Grammar;
9+
10+
final class ContractOnlyExpression implements ExpressionContract
11+
{
12+
public function __construct(private readonly string $value)
13+
{
14+
}
15+
16+
public function getValue(Grammar $grammar): string
17+
{
18+
return $this->value;
19+
}
20+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace GeneaLabs\LaravelModelCaching\Tests\Integration\CachedBuilder;
4+
5+
use GeneaLabs\LaravelModelCaching\Tests\Fixtures\Book;
6+
use GeneaLabs\LaravelModelCaching\Tests\Fixtures\ContractOnlyExpression;
7+
use GeneaLabs\LaravelModelCaching\Tests\Fixtures\UncachedBook;
8+
use GeneaLabs\LaravelModelCaching\Tests\IntegrationTestCase;
9+
10+
class ContractExpressionTest extends IntegrationTestCase
11+
{
12+
/**
13+
* Regression for PR #590. A custom Expression that implements
14+
* Illuminate\Contracts\Database\Query\Expression but does NOT extend
15+
* the concrete Illuminate\Database\Query\Expression must still be
16+
* recognized by CacheKey's instanceof checks. Otherwise the object
17+
* falls through into string concatenation in getOtherClauses() and
18+
* triggers a fatal "Object of class … could not be converted to string".
19+
*/
20+
public function test_cache_key_handles_contract_only_expression_as_where_column()
21+
{
22+
$expression = new ContractOnlyExpression('id');
23+
24+
$cached = (new Book)
25+
->where($expression, '>', 0)
26+
->get();
27+
28+
$live = (new UncachedBook)
29+
->where($expression, '>', 0)
30+
->get();
31+
32+
$this->assertNotEmpty($cached);
33+
$this->assertEmpty($cached->diffKeys($live));
34+
}
35+
}

0 commit comments

Comments
 (0)