Debugging Doctrine Query

User
public function countProductsInFeed(string $feedSlug): int
{
try {
// Debug: Log the feed slug being searched for
error_log("countProductsInFeed – Feed slug: " . $feedSlug);

// Get feed configuration using QueryBuilder
$qb = $this->db->createQueryBuilder();
$config = $qb->select('*')
->from(self::TABLE_CONFIG)
->where('feedSlug = :feedSlug')
->setParameter('feedSlug', $feedSlug, PDO::PARAM_STR)
->execute()
->fetchAssociative();

if (!$config) {
error_log("No config found for feed slug: " . $feedSlug);
return 0;
}

// Get settings
$settings = is_array($config['settings'] ?? null) ? $config['settings'] : json_decode($config['settings'] ?? '{}', true);

// Initialize query builder for product count
$countQb = $this->db->createQueryBuilder();
$countQb->select('COUNT(DISTINCT p.pID) as total')
->from('CommunityStoreProducts', 'p');

// Apply price range filter
if (!empty($settings['price_range']['min']) && !empty($settings['price_range']['max'])) {
$countQb->andWhere('p.pPrice BETWEEN :minPrice AND :maxPrice')
->setParameter('minPrice', (float)$settings['price_range']['min'], PDO::PARAM_STR)
->setParameter('maxPrice', (float)$settings['price_range']['max'], PDO::PARAM_STR);
}

// Apply product groups filter
if (!empty($settings['product_groups']) && is_array($settings['product_groups'])) {
$groupIds = array_filter(array_map('intval', $settings['product_groups']));
if (!empty($groupIds)) {
$countQb->innerJoin('p', 'CommunityStoreProductGroups', 'pg', 'pg.pID = p.pID')
->andWhere($countQb->expr()->in('pg.gID', ':groupIds'))
->setParameter('groupIds', $groupIds, Connection::PARAM_INT_ARRAY);
}
}

// Apply active products filter
if (empty($settings['inactive'])) {
$countQb->andWhere('p.pActive = 1');
}

// Apply stock status filter
if (empty($settings['outofstock'])) {
$countQb->andWhere('(p.pQty > 0 OR p.pQtyUnlim = 1)');
}

// Execute query and get count
$result = $countQb->execute()->fetchAssociative();
$count = (int)($result['total'] ?? 0);

error_log("Product count for feed '{$feedSlug}': {$count}");

return $count;

} catch (Exception $e) {
error_log('Error in countProductsInFeed: ' . $e->getMessage());
return 0;
}
}
how to print query

Assistant
In Doctrine’s **DBAL QueryBuilder** you can easily dump the raw SQL **and** its bound parameters before executing it.

Here’s how you can add it into your method for debugging:

// Before executing
$sql    = $countQb->getSQL();
$params = $countQb->getParameters();

error_log("SQL: " . $sql);
error_log("Params: " . print_r($params, true));

// Now run the query
$result = $countQb->execute()->fetchAssociative();

### Example output in logs:

SQL: SELECT COUNT(DISTINCT p.pID) as total FROM CommunityStoreProducts p 
     INNER JOIN CommunityStoreProductGroups pg ON pg.pID = p.pID 
     WHERE p.pPrice BETWEEN ? AND ? AND pg.gID IN (?) AND p.pActive = 1 AND (p.pQty > 0 OR p.pQtyUnlim = 1)

Params: Array
(
    [minPrice] => 10
    [maxPrice] => 100
    [groupIds] => Array
        (
            [0] => 1
            [1] => 2
        )
)

👉 The `?` placeholders in the SQL correspond to your `$params`.
If you want to **see the full query with values injected**, you’d need to manually interpolate (not recommended for production). For debugging you can do:

$fullSql = strtr($sql, array_map(function($val) {
    return is_array($val) ? '(' . implode(',', $val) . ')' : "'" . $val . "'";
}, $params));

error_log("Full SQL: " . $fullSql);

⚠️ But only use that trick for **debugging**, never in production logs (risk of leaking sensitive data).

Do you want me to adjust your `countProductsInFeed()` method so it logs **both** the raw SQL with placeholders and also the interpolated debug version?

Leave a Comment

Your email address will not be published. Required fields are marked *