PHP code example of alex-frolov / query-guard

1. Go to this page and download the library: Download alex-frolov/query-guard library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

alex-frolov / query-guard example snippets


use QueryGuard\Query\QueryEvent;
use QueryGuard\QueryGuard;

QueryGuard::collector()->record(new QueryEvent(
    sql: 'SELECT * FROM users WHERE id = ?',
    params: [42],
    durationMs: 0.4,
    stack: debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS),
));

use QueryGuard\Attribute\AllowQueries;
use QueryGuard\Attribute\IgnoreRule;

#[AllowQueries(50)]
#[IgnoreRule('n-plus-one')]
public function testImportsLargeFile(): void

// before: one query for the timesheets, then one per timesheet for its tags
foreach ($repository->findBy(['user' => $user]) as $timesheet) {
    $names[] = implode(', ', $timesheet->getTags()->map(fn (Tag $t) => $t->getName())->toArray());
}

// after: the association is fetched with the parent, in one query
$timesheets = $repository->createQueryBuilder('t')
    ->addSelect('tags')          // without addSelect the join filters but does not hydrate
    ->leftJoin('t.tags', 'tags')
    ->where('t.user = :user')->setParameter('user', $user)
    ->getQuery()->getResult();

// before: findOneBy in a loop
foreach ($ids as $id) { $orders[] = $repository->find($id); }

// after: one query, indexed for lookup
$orders = $repository->createQueryBuilder('o')
    ->where('o.id IN (:ids)')->setParameter('ids', $ids)
    ->indexBy('o', 'o.id')
    ->getQuery()->getResult();

// before
foreach (Order::all() as $order) { $total += $order->items->sum('price'); }

// after — eager load with the parent query
foreach (Order::with('items')->get() as $order) { $total += $order->items->sum('price'); }

// or, when the collection already exists
$orders->load('items');

#[AllowQueries(120)]
public function testBulkImport(): void

use QueryGuard\Attribute\AllowQueries;
use QueryGuard\Attribute\IgnoreRule;

// a budget sized to the test's real work — its actual count is in the log
#[AllowQueries(120)]
public function testBulkImport(): void

// switch off exactly the rule that misjudges this test; the argument is the rule id
// verbatim from the finding header: [warning] n-plus-one — ...
#[IgnoreRule('n-plus-one')]
public function testLegacyPdfExport(): void

// a whole class may carry the attributes instead of repeating them per test
#[IgnoreRule('select-star')]
final class ReportQueryTest extends TestCase

use PHPUnit\Framework\Attributes\Group;

#[Group('smoke')]
final class AuctionBidLoadSmokeTest extends TestCase
xml
<parameter name="skip-paths" value="vendor/api-platform,vendor/sonata-project"/>
bash
docker run --rm -v "$PWD":/app -w /app -e COMPOSER_CACHE_DIR=/tmp/composer-cache composer:2 composer update
docker run --rm -v "$PWD":/app -w /app php:8.5-cli php vendor/bin/phpunit
docker run --rm -v "$PWD":/app -w /app php:8.5-cli php vendor/bin/phpstan analyse --memory-limit=1G
docker run --rm -v "$PWD":/app -w /app php:8.5-cli php vendor/bin/php-cs-fixer fix
bash
docker run --rm -v "$PWD":/app -w /app composer:2 composer update --working-dir=tools/pest
docker run --rm -v "$PWD/tools/pest":/app -w /app php:8.5-cli php vendor/bin/pest
docker run --rm -v "$PWD/tools/pest":/app -w /app php:8.5-cli php vendor/bin/pest --parallel