Visualizzazione risultati 1 fino 14 di 14

Discussione: Problema PDO con utf8

  1. #1
    gestioneoltre non è connesso Utente AlterBlog
    Data registrazione
    11-10-2018
    Messaggi
    4

    Predefinito Problema PDO con utf8

    Salve,
    ho un problema con la codifica utf8 dei dati letti da database, probabilmente per un'impostazione sbagliata o una svista, ma non riesco a risolvere. Ho impostato il database in locale sul mio pc nello stesso modo di quello su Altervista e in locale funziona tutto, mentre caricando i file su Altervista ho riscontrato degli errori nella lettura e inserimento dei caratteri speciali. Ho settato la codifica del database a utf8_general_ci, così come la codifica delle tabella e degli attributi di testo, ed eseguendo la query
    Codice:
    show variables like 'char%';
    il database risponde con
    Codice:
    character_set_client     | utf8mb4
    character_set_connection | utf8mb4
    character_set_database   | utf8
    character_set_filesystem | binary
    character_set_results    | utf8mb4
    character_set_server     | latin1
    character_set_system     | utf8
    character_sets_dir       | /usr/share/mysql/charsets/
    I caratteri speciali inseriti a mano nel database vengono visualizzati correttamente, ma quando provo a leggerli hanno una codifica sbagliata. Infatti provando a eseguire questo file php su una tabella con la sola riga 'Sì' ho l'output mostrato a fianco di ogni stampa:
    Codice PHP:
    header('Content-type: text/html; charset=utf-8');
    try {
        
    $dbh = new PDO("mysql:host=localhost;dbname=$db;charset=utf8"$user$pass);
        foreach(
    $dbh->query("SELECT field from table") as $row) {        
            echo(
    $row["field"]);                            //S�
            
    echo json_encode($row["field"]);                //
            
    echo(utf8_encode($row["field"]));               //Sì
            
    echo json_encode(utf8_encode($row["field"]));   //"S\u00ec"
        
    }
    } catch (
    PDOException $e) {
        die(
    "Error!: " $e->getMessage() . "\n");

    Ovvero funziona se uso utf8_encode, altrimenti mi stampa i caratteri sbagliati e json_encode non restituisce niente, quindi sembrerebbe un problema di comunicazione perché il valore che leggo non è in utf8, nonostante abbia impostato la connessione con charset=utf8. Sapete dirmi come mai in locale funziona tutto mentre su Altervista c'è questo problema? Come posso risolvere senza dover usare la funzione utf8_encode ovunque nel sito?
    Grazie

  2. #2
    programmazioned non è connesso Utente attivo
    Data registrazione
    25-03-2008
    Messaggi
    440

    Predefinito

    C'è una discordanza tra character_set_results (la codifica usata nell'invio dal server al client) e character_set_database. Puoi impostare il charset giusto con la query:

    Codice:
    SET character_set_results = utf8
    Il costruttore di PDO permette anche di eseguirla automaticamente al momento della connessione al database:

    Codice PHP:
    $dbh = new PDO("mysql:host=localhost;dbname=$db;charset=utf8"$user$pass, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET character_set_results = utf8')); 
    Ciao!
    Ultima modifica di programmazioned : 20-11-2018 alle ore 00.06.48

  3. #3
    gestioneoltre non è connesso Utente AlterBlog
    Data registrazione
    11-10-2018
    Messaggi
    4

    Predefinito

    Ciao, grazie della risposta, ma purtroppo avevo già provato e non funziona... tra l'altro anche nel database in locale ho le stesse impostazioni che ho postato prima eppure lì funziona tutto.
    Citazione Originalmente inviato da gestioneoltre Visualizza messaggio
    Codice:
    character_set_client     | utf8mb4
    character_set_connection | utf8mb4
    character_set_database   | utf8
    character_set_filesystem | binary
    character_set_results    | utf8mb4
    character_set_server     | latin1
    character_set_system     | utf8
    character_sets_dir       | /usr/share/mysql/charsets/
    Eseguendo la query che mi hai suggerito il character_set_results resta utf8mb4
    Grazie comunque della risposta

  4. #4
    L'avatar di alemoppo
    alemoppo non è connesso Staff AV
    Data registrazione
    24-08-2008
    Residenza
    PU / BO
    Messaggi
    17,766

    Predefinito

    Prova specificandolo da una nuova query:
    Codice PHP:
    $dbh->query('SET character_set_results = utf8;'); 
    O più in generale:
    Codice PHP:
    $dbh->query('SET CHARACTER SET utf8'); 
    (ma anche con la prima, dovrebbe funzionare).

    Ciao!

  5. #5
    darbula non è connesso AlterGuru
    Data registrazione
    24-04-2011
    Messaggi
    2,036

    Predefinito

    Ciao puoi provare creando una nuova tabella in utf-8 tramite l'uso di PDO con php Problema visualizzazione caratteri accentati
    Se i nuovi dati sono in utf-8 il problema sarà altrove (sto cercando di elargire il tuo problema, cioè se inserisci i dati da phpmyadmin sarai limitato a latin1).
    Codice editato previo dimenticanza di una S
    Codice PHP:
    <?php
    //>=php 5.3.6
    try {
        
    header('Content-type: text/plain; charset=utf-8');
        
    $user '';
        
    $pass ='';
        
    $db 'my_gestioneoltre';
        
    $dbh = new PDO("mysql:host=localhost;dbname=$db;charset=utf8"$user$pass);
        
    $dbh->exec("CREATE TABLE IF NOT EXISTS `$db`.`tabella2` (
        `campo` varchar(6) NOT NULL
        ) ENGINE=MyISAM DEFAULT CHARSET=utf8"
    );
        
    $stmt $dbh->prepare("INSERT INTO `$db`.`tabella2` (`campo`) VALUES (:value)");
        
    $stmt->bindParam(':value'$valuePDO::PARAM_STR6);
        
    $value "\xC3\xA0".'bc';
        
    $stmt->execute();
        foreach(
    $dbh->query("SELECT `campo` from `$db`.`tabella2`",PDO::FETCH_ASSOC) as $row) {
            
    print_r($row);
        }
        
    $dbh null;
    } catch (
    PDOException $e) {
        print 
    "Error!: " $e->getMessage() . "\n";
        die();
    }
    ?>
    Ultima modifica di darbula : 20-11-2018 alle ore 15.25.51

  6. #6
    L'avatar di alemoppo
    alemoppo non è connesso Staff AV
    Data registrazione
    24-08-2008
    Residenza
    PU / BO
    Messaggi
    17,766

    Predefinito

    Citazione Originalmente inviato da darbula Visualizza messaggio
    se inserisci i dati da phpmyadmin sarai limitato a latin1
    Non ho capito: phpMyAdmin funziona benissimo con UTF-8:
    i dati di questa pagina vengono visualizzati senza problemi:



    Se ti si visualizzano male, significa che in qualche punto trasformi i dati in altro charset sfalsando il tutto.

    Ciao!

  7. #7
    darbula non è connesso AlterGuru
    Data registrazione
    24-04-2011
    Messaggi
    2,036

    Predefinito

    Citazione Originalmente inviato da alemoppo Visualizza messaggio
    Non ho capito: phpMyAdmin funziona benissimo con UTF-8:
    i dati di questa pagina vengono visualizzati senza problemi:



    Se ti si visualizzano male, significa che in qualche punto trasformi i dati in altro charset sfalsando il tutto.

    Ciao!
    Scusami io malgrado abbia impostato tutto in utf-8 non riesco puoi mostrare il codice?https://darbula.altervista.org/mysql.php il primo risultato è quello inserito a mano da phpmyadmin creando tutto in utf-8.
    Ultima modifica di darbula : 20-11-2018 alle ore 15.30.03

  8. #8
    L'avatar di alemoppo
    alemoppo non è connesso Staff AV
    Data registrazione
    24-08-2008
    Residenza
    PU / BO
    Messaggi
    17,766

    Predefinito

    Citazione Originalmente inviato da darbula Visualizza messaggio
    Dovresti accorgerti che phpmyadmin inserisce i dati in latin1.
    Ho provato velocemente impostando utf8 come comunicazione con la:
    Codice PHP:
    $dbh->query('SET CHARACTER SET utf8'); 
    e funziona tutto correttamente, anche da phpMyAdmin:

    Codice PHP:
    <?php
    //>=php 5.3.6
    try {
        
    $user '';
        
    $pass ='';
        
    $db 'my_alemoppo';
        
    $dbh = new PDO("mysql:host=localhost;dbname=$db;charset=utf8"$user$pass);
        
    $dbh->query('SET CHARACTER SET utf8');
        
    $dbh->exec("CREATE TABLE IF NOT EXISTS `$db`.`tabella2` (
        `campo` varchar(6) NOT NULL
        ) ENGINE=MyISAM DEFAULT CHARSET=utf8"
    );
        
    $stmt $dbh->prepare("INSERT INTO `$db`.`tabella2` (`campo`) VALUES (:value)");
        
    $stmt->bindParam(':value'$valuePDO::PARAM_STR6);
        
    $value "\xC3\xA0".'bc';
        
    $stmt->execute();
        foreach(
    $dbh->query("SELECT `campo` from `$db`.`tabella2`",PDO::FETCH_ASSOC) as $row) {
            
    header('Content-type: text/plain; charset=utf-8');
            
    print_r($row);
        }
        
    $dbh null;
    } catch (
    PDOException $e) {
        print 
    "Error!: " $e->getMessage() . "\n";
        die();
    }
    ?>


    Documentazione
    Se non si imposta character_set_results come indicato da programmazioned, la comunicazione dei dati potrebbe non essere in UTF-8, di fatto, salvando dati con charset differente.

    Ciao!
    Ultima modifica di alemoppo : 20-11-2018 alle ore 15.42.58

  9. #9
    darbula non è connesso AlterGuru
    Data registrazione
    24-04-2011
    Messaggi
    2,036

    Predefinito

    In php non puoi utilizzare questo o altrimenti sei vulnerabile a attacchi SQL http://php.net/manual/en/mysqlinfo.concepts.charset.php
    Comunque credo che con SET CHARACTER SET utf8 il database effettui una conversione al volo da latin1 in utf-8 dato che da phpmyadmin si inseriscono i dati in latin1
    Ultima modifica di darbula : 20-11-2018 alle ore 16.16.53

  10. #10
    L'avatar di alemoppo
    alemoppo non è connesso Staff AV
    Data registrazione
    24-08-2008
    Residenza
    PU / BO
    Messaggi
    17,766

    Predefinito

    In quel modo infatti stiamo impostando il charset della risposta, non dei dati inviati:

    (dal link che ti ho postato sopra):
    The character_set_results system variable indicates the character set in which the server returns query results to the client. This includes result data such as column values, result metadata such as column names, and error messages.
    Se vuoi parlare anche del problema della scrittura, ti invito a creare una nuova discussione senza inquinare questa (puoi comunque risolvere come ti ho indicato e con prepare+bindParam non ci c'è rischio di injection). Comunque PHP sa che siamo in uft8 perché è impostato come connessione al db nel costruttore.

    Se invece vuoi usare mysqli (siamo completamente offtopic), dovrai impostare il charset con mysqli_set_charset() e potrai usare senza problemi le varie escape_string().

    EDIT: ho solo visto adesso la tua modifica:
    Citazione Originalmente inviato da darbula Visualizza messaggio
    Comunque credo che con SET CHARACTER SET utf8 il database effettui una conversione al volo da latin1 in utf-8 dato che da phpmyadmin si inseriscono i dati in latin1
    E dove hai letto questa cosa? Ho appena inserito dei caratteri accentati dall'interfaccia phpMyAdmin e PHP riceve correttamente i dati (anche con il tuo codice, ovviamente con SET CHARACTER SET utf8).
    Come puoi pensare che il database effettui una conversione al volo?
    [ti ri-invito a creare una nuova discussione se hai ancora dubbi per non inquinare questa ulteriormente].

    Ciao!
    Ultima modifica di alemoppo : 20-11-2018 alle ore 16.41.11

  11. #11
    darbula non è connesso AlterGuru
    Data registrazione
    24-04-2011
    Messaggi
    2,036

    Predefinito

    Chiedo scusa volevo essere di aiuto ma inconsciamente mi sono dilungato poiché nel mio codice inserisco anche i dati e non si può utilizzare SET NAMES charset_name o SET CHARACTER SET charset_name (intendo che solo in alcuni contesti è possibile utilizzarlo, ovviamente per la sola lettura va più che bene o se si usa prepare+bindParam).
    Entro sette giorni vado.. Buone cose a tutti :)
    PS. Si avevi ragione se si imposta funziona tutto.
    Ultima modifica di darbula : 21-11-2018 alle ore 00.39.09

  12. #12
    gestioneoltre non è connesso Utente AlterBlog
    Data registrazione
    11-10-2018
    Messaggi
    4

    Predefinito

    Grazie a tutti per le risposte,
    la configurazione dei character_set del database è rimasta quella che ho postato inizialmente e nessuna query suggerita l'ha modificata, quindi resta sempre:
    Citazione Originalmente inviato da gestioneoltre Visualizza messaggio
    Codice:
    character_set_client     | utf8mb4
    character_set_connection | utf8mb4
    character_set_database   | utf8
    character_set_filesystem | binary
    character_set_results    | utf8mb4
    character_set_server     | latin1
    character_set_system     | utf8
    character_sets_dir       | /usr/share/mysql/charsets/
    Ho fatto varie prove seguendo anche i vostri suggerimenti e ho ottenuto i seguenti risultati:
    1) i dati inseriti dall'interfaccia phpMyAdmin sono codificati correttamente in utf8 e vengono visualizzati senza problemi da phpMyAdmin, quindi il problema sta nella comunicazione con il file php

    2) inserendo nel costruttore PDO
    Codice PHP:
    $dbh = new PDO("mysql:host=localhost;dbname=$db;charset=utf8"$user$pass, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET character_set_results = utf8')); 
    oppure
    Codice PHP:
    $dbh = new PDO("mysql:host=localhost;dbname=$db;charset=utf8"$user$pass, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET CHARACTER SET utf8')); 
    oppure togliendo 'charset=utf8'
    Codice PHP:
    $dbh = new PDO("mysql:host=localhost;dbname=$db"$user$pass)); 
    non cambia nulla e i dati continuano a essere letti erroneamente

    3) aggiungendo dopo il costruttore la query
    Codice PHP:
    $dbh->query('SET character_set_results = utf8;'); 
    riesco a leggere i dati correttamente in utf8, ma se faccio un inserimento tramite php i dati vengono codificati male

    4) aggiungendo dopo il costruttore la query
    Codice PHP:
    $dbh->query('SET CHARACTER SET utf8'); 
    riesco a leggere i dati correttamente in utf8, e se faccio un inserimento tramite php i dati vengono codificati correttamente, quindi sembra funzionare tutto

    Grazie mille delle risposte, a questo punto il problema sembrerebbe risolto con la soluzione 4, ma mi sorgono spontanee un paio di domande per capire per bene quale era il problema. Dalle prove che ho fatto mi sembra di capire che il problema dipende dalla non corretta comunicazione tra database e php, però perché eseguendo la query 'SET CHARACTER SET utf8' la comunicazione è corretta mentre 'charset=utf8' nel costruttore PDO (che dovrebbe essere fatto apposta) non funziona? E perché invece in locale mi funziona benissimo anche 'charset=utf8' quando le configurazioni dei due database sono identiche?

  13. #13
    L'avatar di alemoppo
    alemoppo non è connesso Staff AV
    Data registrazione
    24-08-2008
    Residenza
    PU / BO
    Messaggi
    17,766

    Predefinito

    Citazione Originalmente inviato da gestioneoltre Visualizza messaggio
    però perché eseguendo la query 'SET CHARACTER SET utf8' la comunicazione è corretta mentre 'charset=utf8' nel costruttore PDO (che dovrebbe essere fatto apposta) non funziona? E perché invece in locale mi funziona benissimo anche 'charset=utf8' quando le configurazioni dei due database sono identiche?
    È difficile in realtà capire le configurazioni dei database, o meglio ci sono altri parametri nei file di configurazione del server che potrebbero essere differenti.

    In ogni caso mi informo e se saprò qualcosa scriverò qui.
    Può interessarti anche questa discussione.

    Ciao!

  14. #14
    gestioneoltre non è connesso Utente AlterBlog
    Data registrazione
    11-10-2018
    Messaggi
    4

    Predefinito

    Va bene, comunque l'importante è che abbia risolto grazie mille

Regole di scrittura

  • Non puoi creare nuove discussioni
  • Non puoi rispondere ai messaggi
  • Non puoi inserire allegati.
  • Non puoi modificare i tuoi messaggi
  •