Organizzazione PHP Mysql PDO

Rey

Utente Attivo
11 Set 2012
73
0
6
Salve a tutti,
mi sono messo a studiare PDO per tramutare tutto il codice mysql che ho, solo che ho qualche problema di organizzazione del progetto (in rete ho trovato pochi esempi). Attualmente con Mysql lavoro così:

connessione.php che includo in ogni pagina
PHP:
 <?php
// Host
$host = "localhost";
...
etc...

// 0: Errore generico. 1: Debug. 2: Errore generico con invio mail di alert
$dev = 1;
$mittalert = 'From: "Error" <mia@email.com> \r\n';
$destalert = "mia@email.com";
$oggalert = "Errore il: " . date('d-m-Y H:i:s',time());
$msgalert = "Si e' verificato un errore.";

// Mi connetto al server mysql
$myconn = mysql_connect("$host", "$user", "$pass") or die("Errore login db");

// Seleziono il database
mysql_select_db("$nomedb", $myconn) or die("Errore selezione db");
?>
PHP:
include "includes/connessione.php";
$query_code = "SELECT nome FROM " . $prefisso . "utenti WHERE id = '" . $id . "'";
if ($dev == 1) { $result_code = mysql_query($query_code, $myconn) or die("errore: $query_code " . mysql_error()); }
else if ($dev == 2) { $result_code = mysql_query($query_code, $myconn);

if (!$result_code) {
if (!file_exists('alert.txt')) { $alertfile = fopen('alert.txt', 'a+'); fclose($alertfile);
mail($destalert, $oggalert, $msgalert, $mittalert); }
 
$logfile = fopen('log.txt', 'a+'); fwrite($logfile, date('d-m-Y H:i:s',time()) . " - 82 - " . mysql_error()."\n"); fclose($logfile); exit("$errorequery");
} } else { $result_code = mysql_query($query_code, $myconn) or die("$errorequery"); }
Quando il sistema è in produzione $dev è sul 2, se la query non va a buon fine mi arriva un'email e viene creato il file alert.txt in modo che se non me ne accorgo subito e ci sono continui errori evito di ritrovarmi la casella piena. Tramutare il tutto in PDO mi risulta difficile:

connessione.php
PHP:
 <?php
// Host
$host = "localhost";
// Username
$user = "root";
// Password
$pass = "";
// Nome database
$nomedb = "miodb";
// Prefisso tabelle
$prefisso = "db_";

?>
PHP:
include "includes/connessione.php";
try {

// Mi connetto al server mysql
$myconn = new PDO("mysql:host=$host;dbname=$nomedb", $user, $pass);
$myconn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
// Imposto ed eseguo la query
$query = $myconn->prepare("SELECT nome FROM " . $prefisso . "utenti WHERE id = '" . $id . "'");
$query->execute();
    // conteggio dei record coinvolti dalla query
    if($query->rowCount() > 0){
      // creazione di un'array contenente il risultato
      $result = $query->fetchAll();
      // ciclo dei risultati
      foreach($result as $row){
    $nome = $row[0];
    echo $nome . "<br>";
    $myconn = null;
    }
    }else{
      echo "Nessun record corrispondente alla richiesta.";
    }

}
catch(PDOException $e){  
    // otteniamo l'errore  
    echo '<br>Error: ' . $e->getMessage();  
    echo '<br>Line: ' . $e->getLine();  
    echo '<br>File: ' . $e->getFile();  
    }
Alcuni consigliano di non usare try/catch perchè alcuni errori non li rileva e fa andare avanti lo stesso..

PHP:
    $PDO->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );   
    $resultset = $PDO->query("SELECT * FROM inesistente");  
    if(!$resultset){  
        print_r($PDO->errorInfo());  
        die();  
        }
Potrebbe essere questa una soluzione?

Voi come strutturate il codice delle vostre query?
 

marino51

Utente Attivo
28 Feb 2013
2.912
162
63
Lombardia
ho costruito questa classe che utilizzo sempre,
chiamo le diverse funzioni con ($sql, array(par1, par2, ....)
vedi un po' se ti interessa e per i dubbi ... posta
PHP:
<?php

class TheBestDB {

  private $db;
  private $OPtransaction = false;

  public function __construct(
    $Database = 'sqlsrv:Server=*****;Database=*****',
    $dbUSER   = '*****',
    $dbPASS   = '*****')
  { 
    $this->MyLog("");
    $this->MyLog("main : ".basename ($_SERVER['PHP_SELF'],".php").".php");

    try { $this->db = new PDO($Database, $dbUSER, $dbPASS); }
    catch (PDOException $e) { $this->handle_sql_errors("PDO : OPEN DB", $e); }
    $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $this->OPtransaction = false;
  } 

  public function __destruct()
  { 
    $this->close(); 
  } 

  public function Query_exec($sql)
  {
    $this->MyLog("SQL : $sql");
    try { return $this->db->exec($sql); }
    catch(PDOException $e){ $this->handle_sql_errors($sql, $e); }
  } 

  public function Query_fetch($sql, $params=array())
  {
    $sth = $this->Bind_Values($sql, $params);
    try { $sth->execute(); return $sth; }
    catch(PDOException $e){ $this->handle_sql_errors($sql, $e); }
  } 

  public function Query_select($sql, $params=array())
  {
    $sth = $this->Bind_Values($sql, $params);
    try { $sth->execute(); return $sth->fetchall(PDO::FETCH_NUM); }
    catch(PDOException $e){ $this->handle_sql_errors($sql, $e); }
  } 

  public function Query_InsUpd($sql, $params=array())
  {
    $sth = $this->Bind_Values($sql, $params);
    try { $sth->execute(); return $sth->rowCount();}
    catch(PDOException $e){ $this->handle_sql_errors($sql, $e); }
  } 

  public function Query_count($sql, $params=array())
  {
    $x = $this->Query_select($sql, $params); return $x[0][0];
  }

  private function Bind_Values($sql, $params)
  {
    $this->MyLog("SQL : ".$sql);
    if (substr_count($sql, "?") != count($params))
      $this->MyErr("ERRORE : incongruenza nei parametri della query -> ".$sql);
    try
    {
      $x = 0;
      $sth = $this->db->prepare($sql); 
      foreach($params as $key => &$param) { $x+=1; $sth->bindParam($x, $param); } 
      return $sth;
    }
    catch(PDOException $e){ $this->handle_sql_errors($sql, $e); }
  } 

  public function begin_transaction()
  {
    try { $this->db->beginTransaction(); }
    catch(PDOException $e){ $this->handle_sql_errors($row, $e); }
    $this->OPtransaction = true;
    return true;
  } 

  public function commit_transaction()
  {
    try { $this->db->commit(); }
    catch(PDOException $e){ $this->handle_sql_errors($row, $e); }
    $this->OPtransaction = false;
  } 

  public function rollback_transaction()
  {
    try { $this->db->rollBack(); }
    catch(PDOException $e){ $this->handle_sql_errors($row, $e); }
    $this->OPtransaction = false;
  } 

  public function close()
  { 
    unset($this->db); 
  }

  public function MyLog($text)
  {
    global $swN;
    return;
    error_log($swN." ".$text, 0);
  }

  public function MyErr($text)
  {
    global $swN;
    error_log($swN." ".$text, 0);

    require_once '../includes/mail_SolidError.php';
    print "ERRORE INATTESO, contatta l'amministratore del sistema";
    die;
  }

  private function handle_sql_errors($sql, $e)
  {
    if ($this->OPtransaction) $this->db->rollBack();

    error_log("SQL cmd    : ".$sql, 0);
    error_log("error code : ".$e->getCode(), 0);
    error_log("error info : ".$e->getMessage(), 0);

    require_once '../includes/mail_SqlFatalError.php';
    print "ERRORE INATTESO, contatta l'amministratore del sistema";
    die;
} } 
?>
 

MarcoGrazia

Utente Attivo
15 Dic 2009
764
15
18
58
Udine
www.stilisticamente.com
" ... Alcuni consigliano di non usare try/catch perchè alcuni errori non li rileva e fa andare avanti lo stesso.. "
mi piacerebbe conoscerli :evil:

In verità il construtto try/catch funziona alla grande ma va letto il manuale però!
Nella sezione property del manuale online per PDOException c'è scritto testualmente:
errorInfo

Corresponds to PDO::errorInfo() or PDOStatement::errorInfo()
code

SQLSTATE error code. Use Exception::getCode() to access it.
Cioè: PDOException corrisponde a errorInfo() nelle due accezioni, cioè PDO e PDO statements, qundi usare uno o l'altro da gli stessi risultati.
L'SQLSTATE si ottiene con con getCode() ma c'è una cosa che non dice qui ma nella pagina di Error Exception che riporto:
Returns the exception code as integer in Exception but possibly as other type in Exception descendants (for example as string in PDOException).
Cioè in PDOException getCode() non ritorna un intero ma qualsiasi altra cosa (compreso un intero! ) è un bug? Può darsi ma si risolve facilmente facendone il casting: echo (int) $errore->getCode();

Altri errori!
PDOException da gli errori di PDO :jolly: sembra ovvio ma qualcuno pensa di no; e no, da solo quelli quindi un buon codice di errore che li intrappoli tutti è questo ad esempio:
PHP:
try {
    $handle = new PDO( ... ); // Insomma codice PDO...
}
catch (PDOException $error) {
  //  Verifica errori PDO
}
catch (Exception $error) {
  //  Verifica altri errori non PDO
}
Attenzione perché è vero che Exception non vede tutti gli errori del PHP, normalmente vede tutti quelli del core del PHP e altri...

Ma non è finita :D
Come diceva il mio professore di costruzioni a scuola: "... siccome noi siamo duri a morire, abbiamo gli occhiali neri e non ci vediamo... " allora vogliamo capire bene!
Così se si guarda bene il manuale del PDO si nota anche che negli esempi almeno un errore viene sempre intrappolato così: execute()
PHP:
if (!$stmt->execute()) {
    echo "\nPDO::errorInfo():\n";
    print_r($dbh->errorInfo());
}
... oppure ...
if (!$stmt->execute()) {
    throw new PDOException('Ho incontrato un errore durante l\'esecuzione della query!');
}
Insomma non finisce certo qui ma è un buon inizio buon lavoro.
In pratica, dato che execute() ritorna un valore quando opera, che può essere true o false ne tracciamo l'esito!
 

MarcoGrazia

Utente Attivo
15 Dic 2009
764
15
18
58
Udine
www.stilisticamente.com
Scusa @Rey ma perché fai così?
PHP:
$query = $myconn->prepare("SELECT nome FROM " . $prefisso . "utenti WHERE id = '" . $id . "'");
Non ti conviene fare questo?
PHP:
$query = $myconn->prepare("SELECT nome FROM $prefissoutenti WHERE id = $id");
Le doppie virgolette in PHP indicano al motore di processare tutto quello che c'è dentro, per questo in PHP per le stringhe ci sono due modi di scrittura, virgolette doppie e singole, non per il gusto di fare ma per processare o meno la stringa :)
Altra cosa: ma tu sei arcisicuro che $prefisso e $id non creino problemi passati in quel modo alla query? Io per sicurezza prima di processarli ne farei un escaping.
Visto che usi PDO usane i vantaggi :D
PHP:
$tabella = $prefisso . 'utenti';
$query = $myconn->prepare("SELECT t.nome FROM $tabella as t WHERE t.id = :id");
$query->bindValue(':id', (int)$id, PDO::PARAM_INT);
if (!$query->execute()) {
    throw new PDOExcepetion('Si è verificato un errore estraendo i dati dalla tabella!');
}
... fetch ...
In questo modo ID è verificato e controllato e può essere solo un valore intero, mentre $tabella contiene il nome dellatabella e a scanso di equivoci creo pure un alias.
 

Rey

Utente Attivo
11 Set 2012
73
0
6
ho costruito questa classe che utilizzo sempre,
chiamo le diverse funzioni con ($sql, array(par1, par2, ....)
vedi un po' se ti interessa e per i dubbi ... posta
Ciao marino, ti ringrazio, ho provato a usarla ma sono un po' a digiuno di classi

PHP:
include "includes/marino.php";
__construct();
$id = 3;
$sql = "SELECT nome FROM utenti WHERE id = :id";
echo Query_select($sql,array(3));
__destruct();
PHP:
Parse error: syntax error, unexpected '__construct' (T_STRING), expecting function (T_FUNCTION) in E:\xxx\test.php
Potresti farmi qualche esempio?

Scusa @Rey ma perché fai così?
PHP:
$query = $myconn->prepare("SELECT nome FROM " . $prefisso . "utenti WHERE id = '" . $id . "'");
[...]
[/PHP]
Ciao Marco, ti ringrazio per tutte le tue precisazioni :) Ho scritto in quella maniera perchè mi è capitato di dover fare degli update su dei nomi e mettendo:
PHP:
$var = "Mario Rossi" 
"....... WHERE nomecognome = $var"
prendeva solo Mario, con i singoli apici avevo rogne, mi pare non venisse sostituito il valore della variabile quindi singoli e doppi! :D Mi chiederai perchè l'ho usato anche li.. Perchè sono un'autodidatta, un po' casinaro :)
 

MarcoGrazia

Utente Attivo
15 Dic 2009
764
15
18
58
Udine
www.stilisticamente.com
Sono un autodidatta pure io; credo che tu debba fare molta attenzione all'escaping delle stringhe.
Non usare mai più costrutti in cui passi stringhe di riferimento direttamente alla query.
Se usi PDO sarà difficile che ti ricapiti di fare quei costrutti. Poi ci si lamenta che certi siti vengono "craccati" da ragazzini di 12 anni :D
 

marino51

Utente Attivo
28 Feb 2013
2.912
162
63
Lombardia
volendo, puoi separare i valori per la connessione al db dalla classe, modificando
PHP:
class TheBestDB {

  private $db;
  private $OPtransaction = false;

  private $dbNAME;
  private $dbUSER;
  private $dbPASS;
  
  function __construct($eDBNAME="", $eDBUSER="", $eDBPASS="")
  {
    $this->dbNAME = $eDBNAME;
    $this->dbUSER = $eDBUSER;
    $this->dbPASS = $eDBPASS;
  
    $this->MyLog("");
    $this->MyLog("main : ".basename ($_SERVER['PHP_SELF'],".php").".php");

    try { $this->db = new PDO($this->dbNAME, $this->dbUSER, $this->dbPASS); }
    catch (PDOException $e) { $this->handle_sql_errors("PDO : OPEN DB", $e); }
    $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
in questo caso, lo script di "configurazione" diventa,
PHP:
require_once '../includes/Class_DB.php';
$db=new TheBestDB('sqlsrv:Server=*****;Database=*****', '**user**', '**pass**');

la select può essere impostata così,
PHP:
$sql = "SELECT * FROM tabella WHERE field1=? and field2=? and field3=?";

// restituisce l'intero set selezionato
$data = $db->Query_select($sql, array($val1, $val2, $val3));

// restituisce l'oggetto che permette la fetch dei singoli record
$stmt = $db->Query_fetch($sql, array($val1, $val2, $val3));
insert, update e delete si eseguono con,
PHP:
// insert, update, delete restituiscono il numero di record interessati
$sql = "insert into tabella (field1, field2, field3) VALUES ( ?, ?, ?)";
$res = $db->Query_InsUpd($sql, array($val1, $val2, $val3));
ci sono altre funzioni che puoi valutare, vengono chiamati anche script di invio mail in caso di errori
sia dalla gestione del db, sia generati all'interno degli script (MyErr)

i dati come vedi non sono passati direttamente nelle query ma con "$sth->bindParam($x, $param)"
 
Ultima modifica:

Rey

Utente Attivo
11 Set 2012
73
0
6
Grazie marino :)

nutro un odio profondo per le classi.. Ho provato a mettere un if in caso non venga trovato nulla ma non va, ho provato in mille modi.
PHP:
$db = new TheBestDB('mysql:host=localhost;dbname=miodb', 'user', 'passwd');
$sql = "SELECT * FROM utenti DESC LIMIT 0,10";
$data = $db->Query_select($sql);  
if($data->fetchColumn() == 0){ echo "Nessun record trovato"; } 
else { foreach($data as $row){ echo print_r($row); } }
La connessione al db va chiusa?
 

marino51

Utente Attivo
28 Feb 2013
2.912
162
63
Lombardia
PHP:
$db = new TheBestDB('mysql:host=localhost;dbname=miodb', 'user', 'passwd'); 
$sql = "SELECT * FROM utenti DESC LIMIT 0,10"; 
$data = $db->Query_select($sql);   
if(!count($data)){ echo "Nessun record trovato"; }  
else { foreach($data as $row){ echo print_r($row); } }
non occorre chiudere la connessione, anzi conviene attivarla ad inizio script
e poi richiamarla all'interno, tutte le volte che serve

usando la classe, trovo la gestione del db molto semplificata,
mi devo curare di, veramente, poche cose
certo se la applichi poi puoi estenderla con le funzionalità che usi di più

per esempio la gestione dei parametri "esterni" alla query è un vantaggio per evitare l'inserimento di codice non desiderato
 
Ultima modifica:

MarcoGrazia

Utente Attivo
15 Dic 2009
764
15
18
58
Udine
www.stilisticamente.com
Ti do anche un altro consiglio, se il tuo hosting te lo permette, e di solito lo fanno solo quelli a pagamento, ma se puoi, crea due profili utente sul database, uno per leggere e uno di amministratore in grado di fare update o creare nuovi inserimenti.
Così quando ti "loggi" usi tutti i poteri che hai dato all'utente admin e utente per tutti gli altri, in questo modo chi passa sul tuo sito non può fare molti danni a meno che non si loggi.
Quindi la funzione di connessione diventa così:
PHP:
function connetti($utente = 'user') {
  return new PDO($dsn, $utente, $password);
}
Ovviamente la password può essere la stessa per ogni utente, oppure diversa, dipende da cosa vuoi fare.
La connessione la fai così:
  • utente $conn = connessione(); ci pensa la funzione che di default ha 'user';
  • admin $conn = connessione('admin'); passi admin come utente.
 

Rey

Utente Attivo
11 Set 2012
73
0
6
Grazie Marco,
sto traducendo tutto il mio codice in modo da tappare ogni falla, ho un calendario scritto da me che viene generato in base alla variabile passata $_GET

PHP:
// Variabili
$anno = $_GET["anno"];


$tabella = $prefisso . 'calendario' . $anno;
$query = "SELECT data FROM $tabella WHERE id_anno = '1'";
Qui pdo mi aiuta poco, sbaglio? Se passo la variabile con i punti interrogativi mi fallisce la query perchè vengono aggiunti gli apici (esempio: test_calendario'2015').

Ho pensato a un controllo del genere:

PHP:
if (strlen($_GET["anno"]) == 4 || is_numeric($_GET["anno"])) {
// eseguo il codice
} else { echo "errore"; }
Può andare? Oppure mi è sfuggito qualcosa di pdo?
 
Ultima modifica:

marino51

Utente Attivo
28 Feb 2013
2.912
162
63
Lombardia
ho ripreso un vecchio script che avevo preparato per conoscere pdo,
non ti impressionare per la lunghezza, ci sono molte print per vedere i risultati,
le righe importanti sono poche,
ma lo script riporta molti esempi di lettura, e modifica del db
se hai la pazienza di creare una tabella con 8 colonne (car, int, car x 5 volte, datetime) mettendoci qualche record,
lo vedi funzionare

in merito alla tua domanda io farei così,
PHP:
$tabella = $prefisso . 'calendario' . $anno;
$query = "SELECT data FROM ? WHERE id_anno = ?";
$sth = $db->query($query, array($tabella, 1));
ti posto il codice
PHP:
<?php

error_reporting(E_ALL);

class TheBestDB
{
  private $db;
  private $OPtransaction = false;

  private $dbNAME;
  private $dbUSER;
  private $dbPASS;
  
  public function __construct($eDBNAME="", $eDBUSER="", $eDBPASS="")
  {
    $this->dbNAME = $eDBNAME;
    $this->dbUSER = $eDBUSER;
    $this->dbPASS = $eDBPASS;
  
    try { $this->db = new PDO($this->dbNAME, $this->dbUSER, $this->dbPASS); }
    catch (PDOException $e) { $this->handle_sql_errors("PDO : OPEN DB", $e); }
    $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

  } 

  public function __destruct()
  { 
    $this->close(); 
  } 

  public function query($sql, $params=array())
  {
    $sth = $this->BindParams($sql, $params); return $sth;
  } 

  private function BindParams($sql, $params)
  {
    if (substr_count($sql, "?") != count($params))
      $this->MyErr("ERRORE : incongruenza nei parametri della query -> ".$sql);

    try { $sth = $this->db->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL));
          $i=0; foreach($params as $key => &$param) { $i+=1; $sth->bindParam($i, $param); } 
          $sth->execute();
          return $sth; }
    catch(PDOException $e){ $this->handle_sql_errors($sql, $e); }
  } 

  public function close()
  { 
    unset($this->db); 
  }

  public function begin_Transaction()
  {
    try { $this->db->beginTransaction(); $this->OPtransaction = true; }
    catch(PDOException $e){ $this->handle_sql_errors($row, $e); }
    return true;
  } 

  public function commit_transaction()
  {
    try { $this->db->commit(); $this->OPtransaction = false; }
    catch(PDOException $e){ $this->handle_sql_errors($row, $e); }
    return true;
  } 

  public function rollback_transaction()
  {
    try { $this->db->rollBack(); $this->OPtransaction = false; }
    catch(PDOException $e){ $this->handle_sql_errors($row, $e); }
    return true;
  } 

  public function MyErr($text)
  {
    global $swN; error_log($swN." ".$text, 0);

    require_once '../includes/mail_SolidError.php';
    print "ERRORE INATTESO, contatta l'amministratore del sistema";
    die;
  }

  private function handle_sql_errors($sql, $e)
  {
    if ($this->OPtransaction) $this->db->rollBack();

    error_log("SQL cmd    : ".$sql, 0);
    error_log("error code : ".$e->getCode(), 0);
    error_log("error info : ".$e->getMessage(), 0);

    require_once '../includes/mail_SqlFatalError.php';
    print "ERRORE INATTESO, contatta l'amministratore del sistema";
    die;
  }
}
$db=new TheBestDB('sqlsrv:Server=CAMBIAMI;Database=CAMBIAMI','USER_CAMBIAMI','PSW_CAMBIAMI');


$sql = "SELECT count(*) FROM TabellaNelDB";				// ----------


print "SELECT CURRENT : Conta le righe selezionate<br />";
  $count1 = current($db->query($sql, array())->fetch());
  print $sql . " " . $count1 . " record(s) counted <br /><br />";


print "SELECT FETCHCOLUMN : Conta le righe selezionate<br />";
  $count2 = $db->query($sql, array())->fetchColumn(); 
  print $sql . " " . $count2 . " record(s) counted <br /><br />";


$sql = "SELECT * FROM TabellaNelDB WHERE Tcol2 IN(?, ?, ?, ?)";		// ----------


print "SELECT WHILE : Ritorna il numero e le righe selezionate<br />";
  $sth = $db->query($sql, array(1, 3, 7, 12)); 

  print $sql . " " . $sth->rowCount() . " record(s) counted <br /><br />";

  $sth->setFetchMode(PDO::FETCH_ASSOC); 
  while($row = $sth->fetch())
    print $row['Tcol1'] . "&emsp;" . $row['Tcol2'] . "&emsp;" . $row['Tcol8'] . "<br />";
  print "<br />";


print "SELECT FOREACH : Ritorna le righe selezionate<br />";
  foreach ($db->query($sql, array(1, 3, 7, 12)) as $row)
    print $row['Tcol1'] . "&emsp;" . $row['Tcol2'] . "&emsp;" . $row['Tcol8'] . "<br />";
  print "<br />";


print "SELECT FOR : Ritorna le righe selezionate<br />";
  $sth = $db->query($sql, array(1, 3, 7, 12));
  for(; $row = $sth->fetch(); )
    print $row['Tcol1'] . "&emsp;" . $row['Tcol2'] . "&emsp;" . $row['Tcol8'] . "<br />";
  print "<br />";


print "PDO::FETCH_ASSOC : Ritorna ciascuna riga come un'array indicizzata dal nome della colonna<br />";
  $sth = $db->query($sql, array(1, 3, 7, 12));
  $data = $sth->fetch(PDO::FETCH_ASSOC);
  print show_var($data). "<br />";


print "PDO::FETCH_NUM : Ritorna ciascuna riga come un'array indicizzata dal numero della colonna<br />";
  $sth = $db->query($sql, array(1, 3, 7, 12));
  $data = $sth->fetch(PDO::FETCH_NUM);
  print show_var($data). "<br />";


print "PDO::FETCH_BOTH : Ritorna ciascuna riga come un'array indicizzata dal nome e dal numero della colonna<br />";
  $sth = $db->query($sql, array(1, 3, 7, 12));
  $data = $sth->fetch(PDO::FETCH_BOTH);
  print show_var($data). "<br />";


print "PDO::FETCH_LAZY : Ritorna ciascuna riga come un oggetto anonimo con il nome della colonna come proprietà<br />";
  $sth = $db->query($sql, array(1, 3, 7, 12));
  $data = $sth->fetch(PDO::FETCH_LAZY);
  print show_var($data). "<br />";


print "PDO::FETCH_OBJ : Ritorna ciascuna riga come un oggetto con il nome della colonna come proprietà<br />";
  $sth = $db->query($sql, array(1, 3, 7, 12));
  $data = $sth->fetch(PDO::FETCH_OBJ);
  print show_var($data). "<br />";


print "PDO::FETCH_CLASS : Ritorna ciascuna riga come un oggetto della classe<br />";
  class TabellaNelDB {
    public $Tcol1;
    public $Tcol2;
    public $Tcol3;
    public $Tcol4;
    public $Tcol5;
    public $Tcol6;
    public $Tcol7;
    public $Tcol8;

    function makeString()
    { return $this->Tcol1."&emsp;".$this->Tcol8."<br />"; }
  }
  $sth = $db->query($sql, array(1, 3, 7, 12));
  $data = $sth->fetchALL(PDO::FETCH_CLASS, 'TabellaNelDB');
  foreach( $data as $inst_car )
    print $inst_car->makeString();
  print "<br />";


print "FETCHOBJECT : Ritorna ciascuna riga come un oggetto<br />";
  $sth = $db->query($sql, array(1, 3, 7, 12));
  while($obj = $sth->fetchObject('TabellaNelDB'))
    print $obj->makeString();
  print "<br />";


print "PDO::FETCH_FUNC : Ritorna un'array con i risultati della funzione<br />";
  function TabellaNelDB($Tcol1, $Tcol8)
  { return $Tcol1."&emsp;".$Tcol8; }

  $sth = $db->query($sql, array(1, 3, 7, 12));
  $data = $sth->fetchALL(PDO::FETCH_FUNC, 'TabellaNelDB');
  var_export($data); print "<br /><br />";


print "PDO::FETCH_ORI_NEXT : lettura dal primo record del cursore<br />";
  $sth = $db->query($sql, array(1, 3, 7, 12));
  while ($row = $sth->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_NEXT))
    print $row[0] . "&emsp;" . $row[1] . "&emsp;" . $row[2] . "<br />";
  print "<br />";


print "PDO::FETCH_ORI_LAST : lettura dall'ultimo record del cursore<br />";
  $sth = $db->query($sql, array(1, 3, 7, 12));
  $row = $sth->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_LAST);
  do {
    print $row[0] . "&emsp;" . $row[1] . "&emsp;" . $row[2] . "<br />";
  } while ($row = $sth->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_PRIOR));
  print "<br />";


print "fetchALL::ASSOC : Ritorna un'array (multipla) con i risultati della selezione<br />";
  $sth = $db->query($sql, array(1, 3, 7, 12));
  $data = $sth->fetchALL(PDO::FETCH_ASSOC);
  print show_var($data). "<br />";


print "fetchALL::NUM : Ritorna un'array (multipla) con i risultati della selezione<br />";
  $sth = $db->query($sql, array(1, 3, 7, 12));
  $data = $sth->fetchALL(PDO::FETCH_NUM);
  print show_var($data). "<br />";


print "INSERT restituisce il numero di record interessati<br />";
  $sql ="insert into TabellaNelDB (Tcol1, Tcol8)
	 SELECT 'miocodice','2015/01/01 21:39:39'
	 UNION ALL SELECT 'miocodice','2015/01/01 21:39:40'
	 UNION ALL SELECT 'miocodice','2015/01/01 21:39:41'";
  $sth = $db->query($sql);
  print $sth->rowCount() . " record(s) righe inserite <br /><br />";


print "UPDATE restituisce il numero di record interessati<br />";
  $sql ="update TabellaNelDB set Tcol8=? where Tcol8=?";
  $sth = $db->query($sql, array('2015/01/02 21:39:40', '2015/01/01 21:39:40'));
  print $sth->rowCount() . " record(s) righe aggiornate <br /><br />";


print "DELETE restituisce il numero di record interessati<br />";
  $sql ="delete from TabellaNelDB where Tcol8=?";
  $sth = $db->query($sql, array('2015/01/02 21:39:40'));
  print $sth->rowCount() . " record(s) righe cancellate <br /><br />";

  $sql = "SELECT count(*) FROM TabellaNelDB";
  $count1 = current($db->query($sql, array())->fetch());
  print $sql . " " . $count1 . " record(s) counted <br /><br />";

  $sql ="delete from TabellaNelDB where Tcol1=?";
  $sth = $db->query($sql, array('ansab'));
  print $sth->rowCount() . " record(s) righe cancellate <br /><br />";

  $sql = "SELECT count(*) FROM TabellaNelDB";
  $count1 = current($db->query($sql, array())->fetch());
  print $sql . " " . $count1 . " record(s) counted <br /><br />";


unset($count); 
unset($data); 
unset($sql); 
unset($sth); 
unset($db); 
die;


function show_var($x)
{
  $tabella = '<table border=1><tr> <th>key</th> <th>value</th> </tr>'; 
  foreach( $x as $key => $value)
  {
    if (!is_object($value) and $key !== '_SERVER')
    {
      if (is_array ($value))
      { 
        $tabella.='<tr><td>'.$key.'</td><td>'; 
        if ( sizeof($value)>0 )
        {
          $tabella.= show_var($value);
        } 
        else
        { 
          $tabella.='EMPTY'; 
        } 
        $tabella.='</td></tr>'; 
      }
      else
      { 
        $tabella.='<tr><td>'.$key.'</td><td>'.$value.'</td></tr>'; 
      }
    } 
  } 
  $tabella.= '</table>'; 
  return $tabella;
}
?>
 

Rey

Utente Attivo
11 Set 2012
73
0
6
Grazie, do un'occhio al tuo script :)
in merito alla tua domanda io farei così,
PHP:
$tabella = $prefisso . 'calendario' . $anno;
$query = "SELECT data FROM ? WHERE id_anno = ?";
$sth = $db->query($query, array($tabella, 1));
PHP:
Fatal error: Call to undefined method TheBestDB::query()
 

marino51

Utente Attivo
28 Feb 2013
2.912
162
63
Lombardia
si scusa, riferendomi alle funzioni presenti all'interno della classe,
il suggerimento faceva riferimento all'ultimo script che ho postato, quello con tutti gli esempi di "lettura", "scrittura" del db
 

Rey

Utente Attivo
11 Set 2012
73
0
6
Ciao,
ho iniziato stasera a tradurre un po' di codice, il tutto funziona, non ho intoppi :) Volevo qualche parere su questi foreach annidati che mi piacciono tanto :D Voi più esperti che ve ne pare? Codice spazzatura?

Ho due tabelle, una contenente la lista delle tipologie di camere (test_camere) e una con il calendario e le camere in vendita quei giorni (test_anno2015).

Questa è la tabella del calendario contenente la disponibilità
idc1 sta per id camera 1
idp1 sta per permanenza minima della camera 1 (ora non ci interessa..)
idc2 sta per id camera 2
...
etc...

NB: idc1 sono TIPOLOGIE di camera 1, ciò vuol dire che possono essercene più di una in vendita.

db_anno.jpg

PHP:
require_once 'includes/class-db.php';


// Seleziono gli id di tutte le tipologie di camere
$tabella = $prefixdb . 'camere';
$sql = "SELECT id_camere FROM $tabella";
$data = $db->Query_select($sql);  

// Per ogni camera avvio un ciclo
if (!count($data)) { echo "Nessun record trovato"; } else { foreach($data as $row) { 
	$id = $row[0];

// Queste sono le date di arrivo/partenza
$arrivoyy = '2015-04-01';
$partenzayy = '2015-04-03';

$arr = explode("-", $arrivoyy);
$anno = $arr[0];
$mese = $arr[1];
$giorno = $arr[2];

// Sistemo il giorno di partenza sempre per il problema
// del giorno seguente che deve essere prenotabile
$partenzapreyy = date('Y-m-d',strtotime ("-1 day,$partenzayy"));

// Seleziono il numero minore di camere in vendita.
// Se tipo il 01 aprile ci sono 2 idc1 e il 02 aprile ci sono 4 idc1
// verranno prese 2 idc1 disponibili.
$tabella = $prefixdb . 'anno' . $anno;
$sql = "SELECT MIN(idc" . $id . ") FROM $tabella WHERE data between ? AND ?";
$data = $db->Query_select($sql, array($arrivoyy, $partenzapreyy));  
if (!count($data)) { echo "Nessun record trovato"; } else { foreach($data as $row) { 
	$disponibili = $row[0];

	echo "Tipologia camera" . $id . " --> " . $disponibili . "<br>";
}
}

}
}
OUTPUT:

PHP:
Tipologia camera1 --> 2
Tipologia camera2 --> 1
Tipologia camera3 --> 2
Tipologia camera4 --> 1
Tipologia camera5 --> 1