2009-10-25 17 views
8

Sto giocando con le istruzioni preparate in PHP/PDO. Le query di base funzionano bene, passando un valore per la clausola WHERE:Quali token possono essere parametrizzati in istruzioni preparate con PDO?

$stmt = $db->prepare('SELECT title FROM episode WHERE id=:id'); 
$stmt->bindParam(':id', $id, PDO::PARAM_INT); 
$id = 5; 
$stmt->execute(); 

Tuttavia ho una situazione in cui ho bisogno di passare le variabili per i nomi dei campi. Questa interrogazione (con rilegatura appropriato) funziona bene:

SELECT :field FROM episode WHERE id=:id 

Questo dà un errore:

SELECT title FROM :field WHERE id=:id 

Questo non dà un errore, ma non restituisce alcuna riga:

SELECT title FROM episode WHERE :field=:id 

Quindi, quali cose dovrebbero funzionare nelle dichiarazioni preparate? Posso 'parametrizzare' nomi di campi, nomi di tabelle e così via?

risposta

10

Non è possibile parametrizzare nomi di tabelle, nomi di colonna o qualsiasi cosa in una clausola IN (grazie a c0r0ner per pointing out the IN clause restriction).

Vedere this question e successivamente this comment in the PHP manual.

+0

Grazie per la risposta. Si scopre che la prima query che ho postato non funziona - se leghi, diciamo, "titolo" a ": campo", seleziona semplicemente la stringa "titolo" e non il valore del campo. Strano che non ci sia un metodo per legare colonne/tabelle, dato che ora devo aggiungere un po 'di sicurezza extra, che PDO avrebbe dovuto gestire per me:/ – DisgruntledGoat

+0

Il pensiero dietro questo è probabilmente che non dovresti lasciare il tuo gli utenti scelgono direttamente quali campi/tabelle sta invocando la tua query. Ma sono d'accordo sul fatto che aggiunge un po 'di lavoro in più alla tua parte. –

+0

Vedo il tuo punto. Tuttavia, lo sto utilizzando in una situazione in cui specifichi solo le tabelle, ma in modo astratto, ad es. 'DisplayTable ('episodio')'. Suppongo che in questo caso non debba davvero preoccuparsi dei parametri/della sicurezza. – DisgruntledGoat

1

@ Josh Leitzel

Quel pensiero è molto restrittiva (ed è, a mio parere solo una scusa per essere troppo pigro per implementare una soluzione robusta), soprattutto per le strutture ad albero dinamiche espresse in un database.

consideri il seguente esempio:

Il mio progetto ha una struttura logica:

Una gerarchia aziendale è espressa in termini di entità. Ogni entità può essere trattata nel caso generale di un membro della gerarchia o come membro di un livello specifico della gerarchia. La gerarchia stessa è definita in una tabella come un singolo ramo di un albero come segue:

entity_structure (
    id 
    name 
    parent_entity_structure_id 
); 

e gli enti stessi sono espressi come:

entities (
    id 
    name 
    entity_structure_id 
    parent_id 
); 

Per facilità d'uso Ho costruito un algoritmo che crea una vista piatta dell'albero. Il seguente esempio concreto illustra cosa intendo:

SELECT * FROM entity_structure; 

id  | name    | entity_structure_parent_id 
----------------------------------------------------------- 
1  | Company   | null (special one that always exists) 
2  | Division   | 1 
3  | Area    | 2 
4  | Store    | 3 

Questo comporterebbe la seguente rappresentazione piana essendo prodotte:

entity_tree (
    entity_id 
    division_id 
    area_id 
    store_id 
) 

entità che sono al livello di divisione avrebbe division_id, area_id e STORE_ID come NULL , Un'area area_id e store_id come NULL, ecc.

La cosa bella di questo è che consente di interrogare tutti i figli di una divisione utilizzando una dichiarazione simile alla seguente:

SELECT * FROM entity_tree WHERE division_id = :division_id; 

Tuttavia, questo presuppone che io conosca il livello di struttura dell'entità che sto interrogando.Sarebbe bello fare:

SELECT * FROM entity_tree WHERE :structure = :entity_id; 

io so che non è difficile capire il livello di struttura di una singola entità, ma presumo sto loop attraverso una collezione di entità che potrebbero non essere tutti allo stesso livello . Come è ora devo creare una query separata per ogni livello della gerarchia, ma se potessi parametrizzare campi ho potuto effettuare le seguenti operazioni:

$children = array(); 
$stmt = $pdo->prepare('SELECT entity_id FROM entity_tree WHERE :structure = :entityId'); 
foreach ($entities AS $entity) { 
    $stmt->execute(array(
     ':structure' = $entity->getEntityStructureId(), 
     ':entityId' = $entity->getId() 
    )); 

    $children[$entity->getId()] = $stmt->fetchAll(PDO::FETCH_COLUMN); 
} 

conseguente codice più pulito e solo una dichiarazione preparata.

L'intero esempio non utilizza alcun input da parte dell'utente.

Solo qualcosa da considerare.

+0

Qual è il punto, però? In questa istanza potresti facilmente utilizzare le variabili regolari poiché non c'è alcun input da parte dell'utente. Non c'è alcuna possibilità di iniezione qui. Inoltre, questo dovrebbe essere stato pubblicato come commento alla mia risposta poiché questa non è una risposta alla domanda dell'OP. (Mi rendo conto che non saresti stato in grado di adattarlo, solo notando questo.) –

1

Non è possibile parametrizzare alcunché all'interno della clausola IN.

+0

Grazie, me ne sono dimenticato. Lo aggiungerò alla mia risposta. –

Problemi correlati