191 lines
7.5 KiB
PHP
Executable File
191 lines
7.5 KiB
PHP
Executable File
<?php
|
|
//afficherMsg==1 affiche le succes; afficherMsg==1 ou 2 affiche si erreur
|
|
function dynRequete_select($queryType, $tableName, $fields = [], $conditions = [], $orderBy='', $ficAppelant = '', $afficherMsg = 0, $localDebug = 0, $resultName='') {
|
|
|
|
global $admMsg, $admMsgClass, $idPdo, $debugMsg, $debug ; // Déclaration unique des variables globales
|
|
|
|
$startTime = microtime(true); // Pour mesurer le temps d'exécution
|
|
$reqSelect = '';
|
|
|
|
//gestion des requetes imbriquées : nom du tableau de résultat dynamique
|
|
$resultTab = empty($resultName) ? 'tabResult' : $resultName;
|
|
if (!isset($$resultTab)) {
|
|
$$resultTab = []; // Initialise le tableau dynamique
|
|
}
|
|
//blindage tere sur de ne jamais afficher le debug en prod en rajoutant le $debug en plus du local
|
|
// peutre plus besoin du local plus tard ?
|
|
if ($localDebug == 2 && ( isset($debug[1]) && $debug[1] == '1' || isset($debug[2]) && $debug[2] == '1') ) $debugMsg .= monDebug(2, ['queryType' => $queryType, 'tableName' => $tableName ] ,'fonctionRequete_select.php (generique)', $ficAppelant);
|
|
|
|
// ----------------------------------------------------
|
|
// Gestion des champs retournés
|
|
// ----------------------------------------------------
|
|
// Gestion des backticks sauf si le champ est *
|
|
// ----------------------------------------------------
|
|
$escapedFields = array_map(function($field) {
|
|
// Si le champ est '*' on ne fait rien, sinon on échappe les champs avec backticks
|
|
if ($field === '*') {
|
|
return '*';
|
|
}
|
|
|
|
// Si le champ contient un point (pour une jointure), on échappe chaque partie (table/alias + champ)
|
|
$fieldParts = explode('.', $field);
|
|
if (count($fieldParts) === 2) {
|
|
// Exemple: 'cl.idCat' ou 'c.lienImageWeb'
|
|
return "$fieldParts[0].$fieldParts[1]";
|
|
// return "`$fieldParts[0]`.`$fieldParts[1]`";
|
|
} else {
|
|
// Cas où il n'y a pas de jointure, on échappe simplement le champ
|
|
// return "`$field`";
|
|
return "$field";
|
|
}
|
|
}, $fields);
|
|
|
|
$fieldsStr = implode(", ", $escapedFields);
|
|
|
|
// ----------------------------------------------------
|
|
// Construction du debut de la requete
|
|
// ----------------------------------------------------
|
|
if (!(substr($tableName, 0, 1) === '`' && substr($tableName, -1) === '`')) {
|
|
$tableName = "`" . str_replace("`", "", $tableName) . "`";
|
|
}
|
|
if ($queryType == 'SELECT') $reqSelect = "SELECT " .$fieldsStr. " FROM " .$tableName."";
|
|
if ($queryType == 'MAX') $reqSelect = "SELECT MAX(".$fieldsStr.") as max FROM " . $tableName."";
|
|
if ($queryType == 'COUNT') $reqSelect = "SELECT COUNT(".$fieldsStr.") as count FROM " .$tableName."";
|
|
|
|
// ----------------------------------------------------
|
|
// Ajout des conditions WHERE si elles existent
|
|
// ----------------------------------------------------
|
|
$bindParams = [];
|
|
if (!empty($conditions) && is_array($conditions)) {
|
|
$whereClauses = [];
|
|
foreach ($conditions as $key => $value) {
|
|
if ($localDebug == 2 && ( isset($debug[1]) && $debug[1] == '1' || isset($debug[2]) && $debug[2] == '1') ) $debugMsg .= monDebug(2, [''. $key => ''.$value], '');
|
|
$operator = '=';
|
|
if (preg_match('/\s+(=|!=|LIKE|IN)$/i', $key, $m)) {
|
|
$operator = strtoupper($m[1]);
|
|
$key = trim(str_ireplace($m[0], '', $key)); // enlève l'opérateur de la clé
|
|
}
|
|
|
|
// Échapper correctement la clé de la condition si alias de table de type client.id, devient 'client.id'
|
|
$escapedKey = escapeConditionKey($key);
|
|
|
|
// Nom du paramètre PDO qui vaudra :value ( paramName sera la partie droite si client.id ou le champ seul si id)
|
|
$keyParts = explode('.', $key); // Sépare la table de la colonne
|
|
$paramName = (count($keyParts) === 2) ? $keyParts[1] : $keyParts[0];
|
|
|
|
if ($operator === 'IN') {
|
|
if (is_array($value) && !empty($value)) {
|
|
$inParams = [];
|
|
foreach ($value as $i => $val) {
|
|
$p = $paramName . '_' . $i;
|
|
$inParams[] = ':' . $p;
|
|
$bindParams[$p] = $val;
|
|
}
|
|
$whereClauses[] = "$escapedKey IN (" . implode(',', $inParams) . ")";
|
|
}
|
|
|
|
} else {
|
|
// LIKE ou = ou !=
|
|
$whereClauses[] = "$escapedKey $operator :$paramName";
|
|
$bindParams[$paramName] = $value;
|
|
}
|
|
}
|
|
|
|
$reqSelect .= " WHERE " . implode(' AND ', $whereClauses);
|
|
}
|
|
$reqSelect .= " " .$orderBy. " "; // Order
|
|
$reqSelect .= ";"; // Fin de la requête
|
|
|
|
// Debug affichage de la requete brute
|
|
if ($localDebug == 2 && ( isset($debug[1]) && $debug[1] == '1' || isset($debug[2]) && $debug[2] == '1') ) { $debugMsg .= monDebug(2, ['requete Brute' => $reqSelect ], $ficAppelant); }
|
|
|
|
// Requete construite
|
|
$requeteFinale = reconstruireRequete($reqSelect, $bindParams);
|
|
|
|
// Debug affichage de la requete construite
|
|
if ( ($localDebug == 1 || $localDebug == 2) && ( isset($debug[1]) && $debug[1] == '1' || isset($debug[2]) && $debug[2] == '1') ) {
|
|
$debugMsg .= monDebug (2, ['Requête' => $requeteFinale ], $ficAppelant );
|
|
}
|
|
|
|
// ----------------------------------------------------
|
|
// Exécution de la requête
|
|
// ----------------------------------------------------
|
|
try {
|
|
$stmt = $idPdo->prepare($reqSelect);
|
|
|
|
// Execution
|
|
$stmt->execute($bindParams ?? []);
|
|
|
|
// On récupère les résultats
|
|
if ($stmt) {
|
|
$$resultTab= $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
if ($localDebug == 2 && ( isset($debug[1]) && $debug[1] == '1' || isset($debug[2]) && $debug[2] == '1') ) {
|
|
$debugMsg .= '<br>';
|
|
foreach ($$resultTab as $index => $row) {
|
|
$line = [];
|
|
foreach ($row as $key => $value) {
|
|
// sécurité : éviter tableaux / objets
|
|
if (is_array($value) || is_object($value)) {
|
|
$value = json_encode($value);
|
|
}
|
|
$line[] = "[$key] => $value";
|
|
}
|
|
$debugMsg .= '<b>Champ trouvé : </b>'.implode(' | ', $line) . " | ";
|
|
}
|
|
|
|
}
|
|
if ($afficherMsg == 1) { $admMsg .= "Requête exécutée avec succès "; $admMsgClass='ok';}
|
|
|
|
} catch (PDOException $e) {
|
|
if ($afficherMsg != 0) { $admMsg .= "Erreur lors de l'exécution de la requête"; }
|
|
|
|
if ( ($localDebug == 1 || $localDebug == 2) && ( isset($debug[1]) && $debug[1] == '1' || isset($debug[2]) && $debug[2] == '1') ) {
|
|
$erreur = $idPdo->errorInfo();
|
|
$debugMsg .= monDebug(2,[
|
|
'PDO message' => $e->getMessage(),
|
|
'SQLSTATE' => $erreur[0],
|
|
'Driver code' => $erreur[1],
|
|
'Erreur mysql' => $erreur[2],
|
|
'SQL' => $reqSelect
|
|
// 'Params' => $bindParams
|
|
],'fonctionRequete_select.php', $ficAppelant );
|
|
}
|
|
$admMsgClass='ko';
|
|
return []; // Retourner échec
|
|
}
|
|
|
|
|
|
// Temps d'exécution (si nécessaire)
|
|
if ($localDebug == 1 && ( isset($debug[1]) && $debug[1] == '1' || isset($debug[2]) && $debug[2] == '1') ) {
|
|
$endTime = microtime(true);
|
|
$executionTime = $endTime - $startTime;
|
|
$debugMsg .= " | Temps d'exécution : " . number_format($executionTime, 5) . " secondes.";
|
|
}
|
|
|
|
return $$resultTab; // Retourner le résultat
|
|
}
|
|
|
|
|
|
function reconstruireRequete($sql, $params) {
|
|
foreach ($params as $key => $val) {
|
|
$escaped = is_numeric($val) ? $val : "'" . addslashes($val) . "'";
|
|
$sql = str_replace(":$key", $escaped, $sql); // Remplace les `:param`
|
|
}
|
|
return $sql;
|
|
}
|
|
|
|
function escapeConditionKey($key) {
|
|
// Si la clé contient un point (par exemple `cl.idCat`), c'est un alias de table
|
|
if (strpos($key, '.') !== false) {
|
|
$keyParts = explode('.', $key); // Sépare la table de la colonne
|
|
return "$keyParts[0].$keyParts[1]"; // Échappe la table et la colonne
|
|
} else {
|
|
// Si la clé ne contient pas de point, c'est simplement une colonne sans alias
|
|
return "`$key`"; // Échappe uniquement le nom de la colonne
|
|
}
|
|
}
|
|
|
|
?>
|