diff --git a/README.md b/README.md index 637ba6f..f7b1671 100644 --- a/README.md +++ b/README.md @@ -164,6 +164,29 @@ CacheQuery::forget('latest_articles'); > This functionality does not use cache tags, so it will work on any cache store you set, even the `file` driver! +## Custom Hash Function + +You can set your own function to hash the incoming SQL Query. Just register your function in the `$queryHasher` static property of the `CacheAwareConnectionProxy` class. The function should receive the database Connection, the query string, and the SQL bindings in form of an array. + +This can be done in the `register()` method of your `AppServiceProvider`. + +```php +namespace App\Providers; + +use Illuminate\Support\ServiceProvider; +use Laragear\CacheQuery\CacheAwareConnectionProxy; + +class AppServiceProvider extends ServiceProvider +{ + public function register() + { + CacheAwareConnectionProxy::$queryHasher = function ($connection, $query, $bindings) { + // ... + } + } +} +``` + ## Configuration To further configure the package, publish the configuration file: diff --git a/src/CacheAwareConnectionProxy.php b/src/CacheAwareConnectionProxy.php index 479d721..de73b92 100644 --- a/src/CacheAwareConnectionProxy.php +++ b/src/CacheAwareConnectionProxy.php @@ -2,6 +2,7 @@ namespace Laragear\CacheQuery; +use Closure; use DateInterval; use DateTimeInterface; use Illuminate\Cache\NoLock; @@ -24,6 +25,13 @@ class CacheAwareConnectionProxy extends Connection { + /** + * The Query Hasher closure. + * + * @var (\Closure(\Illuminate\Database\ConnectionInterface, string, array): string)|null + */ + public static ?Closure $queryHasher = null; + /** * Create a new Cache Aware Connection Proxy instance. * @@ -105,7 +113,9 @@ public function selectOne($query, $bindings = [], $useReadPdo = true) */ protected function getQueryHash(string $query, array $bindings): string { - return rtrim(base64_encode(md5($this->connection->getDatabaseName().$query.implode('', $bindings), true)), '='); + return isset(static::$queryHasher) + ? (static::$queryHasher)($this->connection, $query, $bindings) + : rtrim(base64_encode(md5($this->connection->getDatabaseName().$query.implode('', $bindings), true)), '='); } /** diff --git a/tests/CacheAwareConnectionProxyTest.php b/tests/CacheAwareConnectionProxyTest.php index 0f6682b..510e561 100644 --- a/tests/CacheAwareConnectionProxyTest.php +++ b/tests/CacheAwareConnectionProxyTest.php @@ -42,6 +42,8 @@ protected function setUp(): void 'title' => $this->faker->text(20), 'user_id' => (int) floor(max(1, $i / 2)), ])->toArray()); + + CacheAwareConnectionProxy::$queryHasher = null; }); parent::setUp(); @@ -670,6 +672,25 @@ public function test_select_one_uses_cache(): void static::assertSame($results, $retrieved); } + + public function test_sets_custom_query_hasher(): void + { + CacheAwareConnectionProxy::$queryHasher = function ( + ConnectionInterface $connection, + string $query, + array $bindings + ) use (&$args) { + static::assertSame(':memory:', $connection->getDatabaseName()); + static::assertSame('select * from "users" where "users"."id" = ? limit 1', $query); + static::assertSame([0 => 1], $bindings); + + return 'test_hash'; + }; + + User::query()->cache('foo')->whereKey(1)->first(); + + static::assertTrue($this->app->make('cache')->has('cache-query|test_hash')); + } } class User extends Authenticatable