/

Rapports SQL personnalisés

Alimentez une grille avec une instruction SELECT arbitraire en lecture seule via query(), pour les rapports qui ne correspondent pas à une seule table.

table() contre query()

->table($name) alimente une grille avec une seule table réelle et modifiable. ->query($sql) est l'alternative pour tout ce qui ne correspond pas à une seule table - jointures, agrégats, colonnes calculées couvrant plusieurs tables :

public function query(string $sql): self

$sql est utilisé tel quel, enveloppé comme une table dérivée par la couche API - exactement le même niveau de confiance que les échappatoires SQL brut de where_raw()/subselect(). Il doit s'agir d'une chaîne simple que vous avez écrite vous-même dans le PHP de votre page, jamais quelque chose construit à partir d'une entrée de requête.

Le mode rapport est en lecture seule

Une grille en mode query n'a ni Ajouter/Modifier/Supprimer, ni actions groupées, ni édition en ligne - elle est en lecture seule par nature, puisqu'il n'y a pas de table unique qu'une écriture pourrait cibler sans ambiguïté. Ceci est appliqué à la fois côté client et côté serveur : l'API rejette purement et simplement les requêtes POST/PUT/DELETE contre une route en mode query, quoi qu'envoie le client. Seuls lister/rechercher/trier/paginer/exporter restent disponibles.

columns() et route() restent requis

Une grille en mode query n'ouvre jamais sa propre connexion à la base de données pour découvrir les colonnes - sa liste de colonnes est uniquement celle indiquée par ->columns(). ->route() est également requis puisqu'il n'y a pas de nom de table dont en déduire un par défaut.

Un exemple basé sur une JOIN

$xcrud = Xcrud::get_instance();
$xcrud->route('order-summary');
$xcrud->query(
    'SELECT o.orderNumber, o.orderDate, o.status, c.customerName, c.country,
            COUNT(od.id) AS itemCount,
            SUM(od.quantityOrdered * od.priceEach) AS orderTotal
     FROM orders o
     JOIN customers c ON c.customerNumber = o.customerNumber
     JOIN orderdetails od ON od.orderNumber = o.orderNumber
     GROUP BY o.orderNumber, o.orderDate, o.status, c.customerName, c.country'
);
$xcrud->columns('orderNumber,orderDate,status,customerName,country,itemCount,orderTotal');
$xcrud->order_by('orderTotal', 'desc');
$xcrud->title('Order Summary Report');

echo $xcrud->render();

Les alias de colonnes propres à $sql et les noms de ->columns() ne sont jamais recoupés entre eux (aucun accès à la base de données n'a lieu au moment du rendu) - une incohérence apparaît sous forme d'erreur lors de la première vraie requête de la grille, et non comme une exception au moment du rendu, contrairement à ce que produirait un nom de colonne inconnu dans order_by()/label()/where(). Vérifiez les deux listes manuellement.

Un ORDER BY final à l'intérieur de $sql sans LIMIT peut être silencieusement abandonné une fois enveloppé comme table dérivée - sans conséquence, puisque le propre tri de la grille/->order_by() applique toujours un ORDER BY externe quoi qu'il arrive, mais ne comptez pas sur un ORDER BY interne pour produire un quelconque effet à lui seul.