Report SQL Personalizzati
Alimenta una griglia con un'istruzione SELECT arbitraria di sola lettura tramite query(), per report che non corrispondono a una singola tabella.
table() vs. query()
->table($name) alimenta una griglia con una singola tabella reale e scrivibile. ->query($sql) è l'alternativa per tutto ciò che non corrisponde a una singola tabella - join, aggregazioni, colonne calcolate che spaziano su più tabelle:
public function query(string $sql): self
$sql viene usato testualmente, incapsulato come tabella derivata dal livello API - esattamente lo stesso livello di fiducia delle vie di fuga SQL grezzo proprie di where_raw()/subselect(). Deve essere una semplice stringa scritta da te nel PHP della tua pagina, mai qualcosa costruito a partire dall'input della richiesta.
La modalità report è di sola lettura
Una griglia in modalità query non ha Add/Edit/Delete, nessuna azione di massa e nessuna modifica in linea - è di sola lettura per natura, dato che non esiste un'unica tabella su cui una scrittura potrebbe puntare in modo inequivocabile. Questo viene imposto sia lato client sia lato server: l'API rifiuta comunque le richieste POST/PUT/DELETE contro una rotta in modalità query, indipendentemente da ciò che invia il client. Restano disponibili solo elenco/ricerca/ordinamento/paginazione/esportazione.
columns() e route() restano obbligatori
Una griglia in modalità query non apre mai una propria connessione al database per scoprire le colonne - il suo elenco di colonne è unicamente quello indicato da ->columns(). ->route() è allo stesso modo obbligatorio, dato che non c'è un nome di tabella da cui derivarne uno predefinito.
Un esempio basato su 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();
Gli alias di colonna propri di $sql e i nomi di ->columns() non vengono mai verificati incrociandoli tra loro (nessun accesso al DB avviene in fase di rendering) - una discrepanza emerge come errore alla prima richiesta reale della griglia, non come eccezione in fase di rendering nel modo in cui lo farebbe un nome di colonna sconosciuto in order_by()/label()/where(). Verifica i due elenchi manualmente.
Un ORDER BY finale dentro $sql senza LIMIT può essere silenziosamente scartato una volta incapsulato come tabella derivata - innocuo, dato che l'ordinamento proprio della griglia/->order_by() applica comunque sempre un ORDER BY esterno, ma non fare affidamento su uno interno che faccia qualcosa da solo.