• User Attivo

    Estrazione dati con stessa query e ciclo while

    Ciao a tutti.
    Sto facendo un sito multilingua.
    La mia pagina visualizza dei prodotti, ho fatto una tabella per i prodotti, con le immagini e il codice che rimangono uguali per tutte le lingue e per ogni lingua faccio una tabella che verrà scelta con il metodo GET.

    Ora sto componendo la mia pagina e volevo un suggerimento per non fare 2 volte la stessa query.

    Questa è la query che mi estrae articolo e la lingua
    [php]<?
    @include("connessione/connect_prodotti.php");

    $id=$_GET['id'];

    $lingua=$_GET['lang'];

    $query_prodotti = "SELECT * FROM tabella_articoli WHERE id_articolo='$id'";
    $risultato_prodotti = mysql_query($query_prodotti,$con) or die ("impossibile eseguire la query_foto");

    while ($row = mysql_fetch_array($risultato_prodotti)) {

    $foto="$row[foto]";
    $descrizione="$row[descrizione]";
    $dettagli="$row[dettagli]";
    

    }

    $query_lingua = "SELECT * FROM tabella_lingua_$lingua WHERE id_articolo='$id'";
    $risultato_lingua = mysql_query($query_lingua,$con) or die ("impossibile eseguire la query_foto");

    while ($row = mysql_fetch_array($risultato_lingua)) {

    $descrizione="$row[descrizione]";
    //$dettagli="$row[dettagli]";
    

    }

    ?>[/php]Nella pagina dovrei fare un sottomenu con i prodotti e i link per la pagina, praticamente
    [php]<ul>
    <li><a href="prodotti.php?id=1">prodotto 1</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    </ul>
    [/php]Al posto di prodotto 1 dovrebbe esserci il codice per l'elendo dei prodotti
    quindi dovrei fare un altro ciclo while finchè non finiscono i rpodotti che soddisfano le mie condizioni.

    Il mio ciclo while farebbe un'altra query esattamente uguale a quella precedente solo che mi estraggo tutti i nomi dei prodotti....

    La domanda è:
    come posso evitare di fare la stessa query e ciclo while ?
    Esiste una scorciatoia/ottimizzazione ?

    Grazie!

    E' un po' lungo ma vi incollo il codice della pagine così forse è più chiaro

    [php]
    <body>
    <?
    @include("connessione/connect_prodotti.php");

    $id=$_GET['id'];

    $lingua=$_GET['lang'];

    $query_prodotti = "SELECT * FROM tabella_articoli WHERE id_articolo='$id'";
    $risultato_prodotti = mysql_query($query_prodotti,$con) or die ("impossibile eseguire la query_foto");

    while ($row = mysql_fetch_array($risultato_prodotti)) {

    $foto="$row[foto]";
    $descrizione="$row[descrizione]";
    $dettagli="$row[dettagli]";
    

    }

    $query_lingua = "SELECT * FROM tabella_lingua_$lingua WHERE id_articolo='$id'";
    $risultato_lingua = mysql_query($query_lingua,$con) or die ("impossibile eseguire la query_foto");

    while ($row = mysql_fetch_array($risultato_lingua)) {

    $descrizione="$row[descrizione]";
    //$dettagli="$row[dettagli]";
    

    }

    ?>

    <div id="centrale">

    <div id="contenuto_header">
    <div id="logo_teile"><img src="http://www.giorgiotave.it/forum/images/logo.jpg" width="220" height="136" /></div>
    <div id="spazio_l_m"></div>
    <div id="menu"><iframe id="myframe" src="menu2.html" scrolling="no" marginwidth="0" marginheight="0" frameborder="0" vspace="0" hspace="0" style="overflow:visible; width:700px; height:136px display:none"></iframe></div>

    </div>

    <!-- titolo si caricherà con database -->

    <div id="spazio_titolo_sezione"><img src="http://www.giorgiotave.it/forum/images/steelform-3000.png" width="940" height="45" /></div>

    <div id="divide_tit_contenuti"><img src="http://www.giorgiotave.it/forum/images/divide_tit_con.png" width="980" height="15" /></div>

    <div id="principale">
    <div id="colonna_1">

    <div id="menu_prodotti"><dl>
    <dt><a href="/">Modulo 3000</a></dt>
    <dd>

    //****************************************
    // qui dovrei rifare la query che vi ho scritto prima
    //****************************************
    <ul>
    <li><a href="prodotti.php?id=1">prodotto 1</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    </ul>
    </dd>
    <dt><a href="/discuss/">Modulo 2700</a></dt>
    <dd>
    <ul>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    </ul>
    </dd>
    <dt><a href="/dev/">Modulo 2500</a></dt>
    <dd>
    <ul>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    </ul>
    </dd>
    </dl></div>

    <div id="div_pr_col"><img src="http://www.giorgiotave.it/forum/images/dividi_pr_colon.png" width="240" height="20" /></div>

    <div id="link_area">qui ci va il coso per il link area</div>

    <div id="div_pr_col"><img src="http://www.giorgiotave.it/forum/images/dividi_pr_colon.png" width="240" height="20" /></div>

    <div id="credits">qui ci vanno i credits</div>

    </div>

    <div id="colonna2">

    <div id="foto_prodotto"> <a rel="lightbox" href="http://www.giorgiotave.it/forum/images/prodotti/big/<? echo $foto; ?>" title="Teile"><img src="http://www.giorgiotave.it/forum/images/prodotti/small/<? echo $foto; ?>" alt="" width="380" height="380" border="0" /></a></div>

    <div id="dettagli"><? echo $descrizione; ?></div>

    <div id="div_centr_col"><img src="http://www.giorgiotave.it/forum/images/dividi_centr_col.png" width="560" height="20" /></div>

    <div id="eventuale_descr"><img src="http://www.giorgiotave.it/forum/images/prodotti/<? echo $dettagli; ?>" width="540" height="137" /></div></div>

    <div id="colonna3">

    <div id="minibox_new"><strong>minibox news</strong><br />lorem ipsum lorem ipsum lorem ipsum<br /><br /><strong>minibox news</strong><br />lorem ipsum lorem ipsum lorem ipsum </div>
    <div id="div_se_col"><img src="http://www.giorgiotave.it/forum/images/dividi_se_colon.png" width="160" height="20" /></div>
    <div id="evidence">evidence</div>

    </div>

    </div>

    <?

    mysql_close($con);

    ?>

    </div>

    </body>
    </html>
    [/php]


  • User

    Da quel che ho visto non solo puoi evitare di ripetere la stessa query, ma puoi addirittura farne una sola per eseguire tutte le operazioni di cui hai bisogno.

    Eegui una query con join dove peschi tutte le informazioni riguardo i prodotti e la traduzione della lingua in proposito (ti consiglio una variabile di sessione piuttosto che inviare per get il dato della lingua).

    Mentre viene effettuato il ciclo, accumuli tutte le informazioni che ti occorrono in un array, successivamente scorrerai questo array per riprodurre l'elenco 🙂

    es (nell'esempio ho supposto che richiami anche l'id):
    [php]$articolo = array();

    $query_prodotti = "SELECT tabella_articoli.id, tabella_articoli.foto, tabella_articoli.descrizione, tabella_articoli.dettagli, tabella_lingua_$lingua.descrizione AS desc_lingua
    FROM tabella_articoli, tabella_lingua_$lingua
    WHERE tabella_articoli.id_articolo = tabella_lingua_$lingua.id_articolo
    AND tabella_articoli.id_articolo = '$id'";
    $risultato_prodotti = mysql_query($query_prodotti,$con) or die ("impossibile eseguire la query");

    while ($row = mysql_fetch_array($risultato_prodotti))
    {
    $id = $row['id'];

    $articolo[$id]['foto'] = $row['foto'];
    $articolo[$id]['descrizione'] = $row['descrizione'];
    $articolo[$id]['dettagli'] = $row['dettagli'];
    $articolo[$id]['dettagli_lingua'] = $row["desc_lingua"];
    

    }[/php]
    A questo punto hai l'array $articolo che sarà strutturato, all'incirca, così:

    Array(
      id => Array(
                       foto => dato
                       descrizione => dato
                       dettagli => dato
                       dettagli_lingua => dato
                       )
    
      id => Array(
                       foto => dato
                       descrizione => dato
                       dettagli => dato
                       dettagli_lingua => dato
                       )
    
    etc..
    )
    ```Per cui potrai navigarlo in tutta semplicità con un foreach:
    [php]foreach ($articoli as $id => $info){
    
        echo "<li><a href=\"prodotti.php?id=$id\">".$info['descrizione']."</a></li>";     
    
    }[/php](come ho recuperato descrizione puoi recuperare i contenuti delle altre chiavi registrate nel while allo stesso modo).
    
    Fammi sapere come ti va :ciauz:
    
    ps: per le query, cerca sempre di specificare i nomi dei campi che ti occorre recuperare, nel caso di una join tra tabelle con campi simili devi includere "nometabella." davanti al nome che vuoi richiamare.
    
    p-ps: Per quanto riguarda il recupero di array associativi, evita di scriverli come avevi fatto ma includi gli apici per specificare la chiave tra parentesi, in quanto a livello prestazionale c'è un abisso tra l'inclusione o meno di questi apici.

  • User Attivo

    Non entro nel merito della discussione (mi pare che la soluzione di Blancks vada più che bene, al massimo suggerirei un NATURAL JOIN visto che le due tabelle hanno il campo che le "unisce" con lo stesso nome) ma vorrei invitarvi a stare **attenti attenti attenti **all' SQL injection - nel vostro codice inserite direttamente in una query SQL del testo che proviene dall'input utente e questo è pericoloso pericoloso pericoloso!!


  • User Attivo

    Ciao SEO Italy, ti ringrazio per la precisazione, ma quale altra soluzione per evitare SQL Injection ?
    Alla fine è un catalogo, come posso selezionare i prodotti dalle tabelle se passando le variabili in GET ?
    Grazie!

    Posso anche chiedere perchè per la lingua sarebbe preferibile utilizzare una variabile di sessione?


  • User Attivo

    Visto che ormai ho perso la speranza di far utilizzare una libreria per accedere al DB (la libreria da utilizzare è MDB2), la soluzione è usare mysql_real_escape_string così (ad esempio):
    [PHP]$query = "SELECT * FROM tabella_articoli WHERE id_articolo='" . mysql_real_escape_string($id) . "'";[/PHP]
    HTH, ciao! 🙂


  • User Attivo

    Ti ringrazio!
    Quindi come ho visto nel manuale PHP sarebbe sicuro e giusto e più semplice usare una piccola funzione per i GET e i POST ?
    [PHP]
    <?php
    function safe($value){
    return mysql_real_escape_string($value);
    }
    ?>

    Then, when I am using my code, I simply use:

    <?php
    $name = safe($_POST["name"]);
    $password = safe($_POST["password"]);
    ?>[/PHP]


  • User Attivo

    Mah, come vedi la funzione non fa altro che richiamare mysql_real_escape_string quindi ti basta usare quella, cioè
    [PHP]<?php
    $name = mysql_real_escape_string($_POST["name"]);
    $password = mysql_real_escape_string($_POST["password"]);
    ?>[/PHP]


  • User Attivo

    A questo punto avrei un'altra domanda.
    Nella creazione del mio sottomenu dovrei fare una ulteriore query per dividere i prodotti
    [PHP]//****************************************
    // qui dovrei rifare la query
    //****************************************
    <ul>
    <li><a href="prodotti.php?id=1">prodotto 1</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    </ul>
    </dd>
    <dt><a href="/discuss/">Modulo 2700</a></dt>
    <dd>
    <ul>
    //****************************************
    // qui dovrei rifare la query
    //****************************************
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    </ul>
    </dd>
    <dt><a href="/dev/">Modulo 2500</a></dt>
    <dd>
    <ul>
    //****************************************
    // qui dovrei rifare la query
    //****************************************
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    <li><a href="prodotti.php?id=2">prodotto 2</a></li>
    </ul>
    </dd>
    </dl></div>[/PHP]
    la query potrebbe essere un'altra select perchè vorrei che modulo 2500
    avesse tutti i dati contrassegnati da categoria 2500 quindi dovrei fare
    [PHP]"SELECT * FROM tabella_articoli WHERE categoria='2500'";[/PHP]
    poi dovrei farne un'altra che mi visualizzasse
    [PHP]"SELECT * FROM tabella_articoli WHERE categoria='3000'";[/PHP]

    Così facendo dovrei fare più volte la stessa query cambiando un solo paramentro ?


  • User Attivo

    Direi che sarebbe piuttosto inefficiente... La soluzione che ti suggerisco è fare una query e mettere il tutto in un array bidimensionale dove per ogni categoria c'è un array di prodotti (non ti preoccupare, è più facile farlo che dirlo...)

    In sostanza fai così:
    [php]while ($row = mysql_fetch_array($risultato_prodotti)) {
    $prodotti[$row['categoria']][$row['id']] = $row;
    }[/php]quando poi vai a mostrare l'array (cioè a fare i sottomenu) fai così:
    [php]foreach ($prodotti as $categoria => $array_categoria) {
    echo '<dd>';
    echo '<ul>';
    foreach ($array_categoria as $id => $prodotto) {
    echo '<li><a href="prodotti.php?id=' . htmlspecialchars($id) . '">' . htmlspecialchars($prodotto['descrizione']) . '</a></li>';
    }
    echo '</ul>';
    echo '</dd>';
    echo '<dt><a href="/discuss/">Modulo ' . htmlspecialchars($categoria) . '</a></dt>';
    }[/php]Due cose a cui prestare attenzione:

    • come vedi ho usato la funzione htmlspecialchars, leggiti la pagina di manuale corrispondente poichè è fondamentale usarla quando si devono mostrare in una pagina HTML dei dati su cui non si ha il controllo
    • ovviamente la URL della categoria ("/discuss/" o quello che deve essere) la devi variare tu (come ho fatto io è sempre uguale) ad esempio utilizzando un array associativo - però non so cosa vuoi ottenere lì quindi non entro nei dettagli

    HTH, ciao!!


  • User Attivo

    Quindi da quello che ho capito, un ciclo foreach mi analizza le categorie mentre un altro sotto ciclo foreach mi analizza cio' che è all'interno delle categorie giusto ?


  • User Attivo

    Esatto - ovviamente l'importante è creare prima un array bidimensionale, cioè che abbia la forma:

    array (
    categoria1 => array(prodotto1, prodotto2, ...)
    categoria2 => array(prodotto6, prodotto7, ...)
    ...
    )


  • User Attivo

    Ok quindi se ho ben capito (speriamo!) estraggo tutti i dati dalla tabella con un [php]SELECT * FROM tabella_articoli[/php] poi mi creo il mio array bidimensionale con
    [php]while ($row = mysql_fetch_array($risultato_prodotti)) {
    $prodotti[$row['categoria']][$row['id']] = $row;
    } [/php]e li estraggo con il ciclo foreach che mi avete suggerito ?

    Ps.
    Queste ottimizzazioni del codice, suggerimenti e scorciatoie, posso trovarlo in qualche manuale? Mi consigliate qualche lettura ?


  • User Attivo

    A mio modo di vedere la fonte migliore (e meno costosa... :2: per imparare il PHP è il manuale online: http://php.net