Visualizzazione dei risultati da 1 a 8 su 8
  1. #1

    [mysql/php] Form di ricerca, la query restituisce in tutti i casi tutti i record

    Ciao a tutti,
    ho un problema con una form per una ricerca di immagini, in cui ogni campo è facoltativo. Se non riempio nessun campo vengono restituiti tutti i risultati, esattamente come desidero. Se compilo uno o più campi invariabilmente la query mi restituisce sempre tutte i record della tabella.

    A livello PHP controllo se ogni campo è stato compilato con isset(), se sì assegno il suo valore a una variabile, altrimenti alla variabile assegno NULL o '' (stringa vuota, ho provato in entrambi i modi ma la query mi restituisce comunque tutti i risultati).

    Veniamo alla query: premetto che, eseguendola da phpmyadmin, la query restituisce i risultati giusti. Ci sarà qualche errore a livello di php che non riesco a trovare!

    La query è:

    Codice PHP:
    $sql "SELECT DISTINCT opere.id, opere.titolo, opere.thumb FROM opere JOIN tags ON opere.id = tags.opera WHERE ( (opere.titolo LIKE '%$titolo%') or  (opere.publisher LIKE '%$autore%')) or    (opere.categoria LIKE '%$categoria%') or (data_pubblicazione BETWEEN '$data_da' and '$data_a'))"
    I vari $titolo, $categoria e $autore... se i campi non sono stati compilati corrispondono a NULL (o a '', come vi spiegavo sopra). Eseguendo le query da phpmyadmin i risultati sono sempre corretti se simulo questi valori, considerando che uso LIKE: '%''%', '%NULL%' , '%%' mi danno sempre ciò che voglio ottenere.

    Se nella query cerco solo sul campo data_pubblicazione ottengo i risultati giusti, se abbino in OR per esempio il campo titolo ottengo di nuovo tutto la roba in tabella.

    Perché? E' un problema di condizioni nella clausola WHERE? Faccio male a settare i campi non compilati come NULL o ''? Strategie alternative che mi suggerite?

    Grazie in anticipo, sto davvero sclerando con questa roba da giorni e mi sfugge proprio dove sta il problema.

    Codice php (scusate ridondanza, poca pulizia, poca eleganza e varie ed eventuali: sono autodidatta, se avete suggerimenti sono sempre graditi):

    Codice PHP:
    //CONTROLLI SULL'INVIO EFFETTIVO DEI PARAMETRI  
    function check_titolo($i) {     
    if (isset(
    $i) and !empty($i)) {return $i;}     
    else {return 
    NULL;}} 

    function 
    check_autore($i) {     
    if (isset(
    $i) and !empty($i)) {return $i;}     
    else {return 
    NULL;}     


    function 
    check_categoria($i) { 
    if (isset(
    $i) and trim($i)) {return $i;}     
    else {return 
    NULL;}     
    return 
    $categoria; } 

    function 
    controlla_data_da($g$m$a) { 
        
    $s checkdate($m,$g,$a);     
    if (
    $s) {         
    $data_da date("$a-$m-$g");     
    }     
    else {         
    $data_da NULL;     
    }         
    return 
    $data_da
    }  

    function 
    controlla_data_a($g$m$a) {     
    $s checkdate($m,$g,$a);     
    if (
    $s) {         
    $data_a date("$a-$m-$g");     
    }     
    else {         
    $data_a NULL
    }     
    return 
    $data_a; } 

     
    //RESTITUISCE I RISULTATI 
    if (isset($_POST['submit'])) { 
        if (     
    (!isset (
    $_POST['titolo']) || !trim ($_POST['titolo'])) and     
    (!isset (
    $_POST['autore']) || !trim ($_POST['autore'])) and 
    (!isset (
    $_POST['categoria']) || !trim ($_POST['categoria'])) and     
    (!isset (
    $_POST['da_giorno']) || $_POST['da_giorno'] == '-1') and     (!isset($_POST['da_mese']) || $_POST['da_mese'] == '-1') and     (!isset($_POST['da_anno']) || $_POST['da_anno'] == '-1') and      (!isset($_POST['a_giorno'])|| $_POST['a_giorno'] == '-1') and
    (!isset(
    $_POST['a_mese']) || $_POST['a_mese'] == '-1') and     
    (!isset(
    $_POST['a_anno']) || $_POST['a_anno'] == '-1') and     
    (!isset(
    $_POST['tag']) || !trim ($_POST['tag'])) and     (!isset($_POST['myCheck']) || empty($_POST['myCheck']))     ) { 
    echo 
    "Nessun criterio selezionato. Torna alla <a href=\"ricercaavanzata.php\">ricerca avanzata</a>.";         
    include(
    "risultatiricercaopere.php");     }     
    else { 
    $titolo check_titolo($_POST['titolo']);         
    $autore check_autore($_POST['autore']);         
    $categoria check_categoria($_POST['categoria']);         
    include(
    "connessionedb.php");                  
    // verifica se le date sono corrette e crea le variabili per la query                  

    $data_da controlla_data_da($_POST['da_giorno'],$_POST['da_mese'],$_POST['da_anno']);         $data_a controlla_data_a($_POST['a_giorno'],$_POST['a_mese'],$_POST['a_anno']);          

    $sql "SELECT DISTINCT opere.id, opere.titolo, opere.thumb FROM opere JOIN tags ON opere.id = tags.opera WHERE (         
    (data_pubblicazione BETWEEN '
    $data_da' and '$data_a') or (opere.titolo LIKE '%$titolo%') or (opere.publisher LIKE '%$autore%') or (opere.categoria LIKE '%$categoria%'))";              
    $res mysql_query($sql,$conn) or die ("Errore" .mysql_error());         

    echo 
    "<table class=\"anteprime\">\n";         
    while(
    $results mysql_fetch_array($res)) {             
    echo 
    "<tr><td><a href='opera.php?id=$results[id]'>[img]".$results[[/img]
    $results[titolo]</a></td></tr>";             
    }         
    echo "
    </table>";         
    echo "
    Criterio/i selezionato/i."."Torna alla <a href=\"ricercaavanzata.php\">ricerca avanzata</a>.";
     } 

    else {     
    include(
    "formcercaopere.php"); 


  2. #2
    Direi che la prima cosa che dovresti fare e' stampare la query per verificare come vengono valorizzati i vari parametri.

    echo $sql;

    tante volte e' sufficiente per scoprire il problema.

    Il silenzio è spesso la cosa migliore. Pensa ... è gratis.

  3. #3
    Grazie del consiglio, l'avevo fatto giorni fa e non dava niente di inaspettato... ma in effetti allora non avevo alcun LIKE nella query!
    Infatti provando ora il risultato che mi dà è:
    codice:
    SELECT DISTINCT opere.id, opere.titolo, opere.thumb 
    FROM opere JOIN tags ON opere.id = tags.opera 
    WHERE (
    (opere.titolo LIKE '%%') or 
    ((data_pubblicazione >= '') and (data_pubblicazione <= '')) or 
    (opere.publisher LIKE '%%') or 
    (opere.categoria LIKE '%varie%')
    )
    In questo caso ciò che vorrei è che non venisse restituito nulla (nessun record nel database al momento ha la categoria "varie", ma purtroppo il NULL/stringa vuota che mando da PHP se il campo non è settato fanno sì che nella query l'espressione '%$titolo%', con titolo NULL/'', si riduca a '%%', che ovviamente restituisce tutto!

    Quindi a questo punto a me sembra che il problema sia nel valore da mandare nella query con php. Come ho detto tutti i campi sono facoltativi e non posso sapere a priori quali sono stati mandati. In secondo luogo voglio che la ricerca avvenga anche per stringhe parziali, quindi non posso abbandonare il LIKE con %% (ergo non posso aggirare il problema scrivendo WHERE titolo LIKE '$titolo').

    Grazie per il consiglio, io credevo che nella query arrivasse qualcosa come LIKE '%NULL%', che comunque non restituiva nulla, invece arriva LIKE '%%', come da query sopra...

    Suggerimenti per continuare a usare il like senza rischiare che tutta la tabella mi venga restituita? Grazie in anticipo!

  4. #4
    Ho, come dire ... la sensazione che possa essere lungo il tempo necessario per darti una mano e purtroppo non ho tutto il tempo che vorrei.

    Mi limito ad alcune osservazioni random:

    Di funzioni per il controllo della data ne basta una. Poi la funzione date():
    $data_da = date("$a-$m-$g");
    Credo sia poco significativa. Prova a stampare $data_da e $data_a per convincerti.
    http://it.php.net/manual/en/function.date.php

    Codice PHP:
    function controlla_data($g$m$a) { 
        
    $s checkdate($m,$g,$a);     
        if (
    $s) { $data "$a-$m-$g";     
                } else { 
    $data '0000-00-00'; }    
        return 
    $data
        }

    // e poi
    $data_da=controlla_data($_POST['da_giorno'],$_POST['da_mese'],$_POST['da_anno']);         
    $data_a controlla_data($_POST['a_giorno'],$_POST['a_mese'],$_POST['a_anno']); 

    Anche il controllo che fai su $_POST e' migliorabile.

    Codice PHP:
    if (isset($_POST['submit'])) { 
        if (     
             (!isset (
    $_POST['titolo']) || !trim ($_POST['titolo'])) 
             and     
             (!isset (
    $_POST['autore']) || !trim ($_POST['autore'])) 
             and ....... 
    farei piuttosto una cosa simile:

    Codice PHP:

    if (isset($_POST['submit']) AND $_POST['submit'] == 'nome_dato_a_submit' ) {

       if(!empty(
    $_POST['titolo'] ) { 
              
    $titolo =  '%'.trim($_POST['titolo']).'%';
              } else { 
    $titolo NULL;  }

          if(!empty(
    $_POST['autore'] ) { 
              
    $autore =  '%'.trim($_POST['autore']).'%';
              } else { 
    $autore NULL;  }

    ...... 
    etc
    poi la query sara':

    WHERE (opere.titolo LIKE '$titolo') or (opere.publisher LIKE '$autore')

    Ovviamente poi non dovranno esserci campi settati a NULL ma solo NOT NULL

    Per la data tieni conto che per fare confronti congruenti devi usare il formato ansi yyyy-mm-dd. 0000-00-00 e' il valore di una data nulla, non valida. Toglierei anche tutti i controlli che fai sui valori della data in arrivo da $_POST, ci pensa la funzione a stabilire se la data e' valida oppure no. Anzi per la data mettici tre select per giorno - mese - anno con default 00-00-0000 cosi' almeno non metteranno cose buffe nel form.

    E' sicuramente ancora migliorabile. Prendilo solo come suggerimento al volo.

    Il silenzio è spesso la cosa migliore. Pensa ... è gratis.

  5. #5
    codice:
    SELECT DISTINCT opere.id, opere.titolo, opere.thumb 
    FROM opere JOIN tags ON opere.id = tags.opera 
    WHERE (
    (opere.titolo LIKE '%%') or 
    ((data_pubblicazione >= '') and (data_pubblicazione <= '')) or 
    (opere.publisher LIKE '%%') or 
    (opere.categoria LIKE '%varie%')
    )
    diventa

    codice:
    SELECT DISTINCT opere.id, opere.titolo, opere.thumb 
    FROM opere JOIN tags ON opere.id = tags.opera 
    WHERE (
    (opere.titolo LIKE '%%' and opere.titolo NOT NULL) or 
    ((data_pubblicazione >= '') and (data_pubblicazione <= '')) or 
    (opere.publisher LIKE '%%'  and opere.publisher NOT NULL) or 
    (opere.categoria LIKE '%varie%')
    )
    In realtà sarebbe meglio fare i controlli lato PHP...se il campo del form che usi nella prima like è vuoto, valorizza a qualcosa di "impossibile" tipo "#@[]£", idem per le altre ...
    Ci sono modi decisamente migliori di quest'ultimo che ti ho detto, ma almeno è un inizio..

  6. #6
    Mi hai davvero aiutato tantissimo, grazie! I suggerimenti per migliorare il codice sono chiari e utilissimi, avevo davvero scritto cose inutili!

    Le due date nella form le costruivo già tramite 3 select ciascuna. Lo scopo del controllo sulla data era nel caso $data_da/$data_a corrispondessero a '' o NULL se il campo non era stato compilato.
    Come dici tu, basta che ora nelle select metta come primo valore selected 00/0000, io avevo messo -1 ma non ha molto senso :P inoltre 00/0000 mi risparmia un controllo sulle date, che posso mandare direttamente in query.

    I risultati della query adesso, come immaginerai, sono quelli giusti. Io mi mangio le mani per essermi persa in un bicchier d'acqua, ma non si finisce mai di imparare

    Originariamente inviato da piero.mac
    Ho, come dire ... la sensazione che possa essere lungo il tempo necessario per darti una mano e purtroppo non ho tutto il tempo che vorrei.
    L'aiuto datomi finora è più che sufficiente, sei stato gentilissimo ed esauriente. Se poi hai davvero voglia di rimettere mano a un codice così disastrato a me farà solo piacere, ma non ti sentire in obbligo.
    Grazie ancora del tuo tempo e della tua gentilezza!

  7. #7
    Originariamente inviato da Dascos
    codice:
    SELECT DISTINCT opere.id, opere.titolo, opere.thumb 
    FROM opere JOIN tags ON opere.id = tags.opera 
    WHERE (
    (opere.titolo LIKE '%%') or 
    ((data_pubblicazione >= '') and (data_pubblicazione <= '')) or 
    (opere.publisher LIKE '%%') or 
    (opere.categoria LIKE '%varie%')
    )
    diventa

    codice:
    SELECT DISTINCT opere.id, opere.titolo, opere.thumb 
    FROM opere JOIN tags ON opere.id = tags.opera 
    WHERE (
    (opere.titolo LIKE '%%' and opere.titolo NOT NULL) or 
    ((data_pubblicazione >= '') and (data_pubblicazione <= '')) or 
    (opere.publisher LIKE '%%'  and opere.publisher NOT NULL) or 
    (opere.categoria LIKE '%varie%')
    )
    In realtà sarebbe meglio fare i controlli lato PHP...se il campo del form che usi nella prima like è vuoto, valorizza a qualcosa di "impossibile" tipo "#@[]£", idem per le altre ...
    Ci sono modi decisamente migliori di quest'ultimo che ti ho detto, ma almeno è un inizio..
    Scusami, ho visto dopo il tuo messaggio.
    Immagino intendessi IS NOT NULL comunque, vero? Grazie comunque dell'aiuto e del consiglio!

  8. #8

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.