web-dev-qa-db-fra.com

Ajout de la prise en charge UTF-8 au script JS / PHP

Je travaille sur une page qui utilise JavaScipt pour envoyer des données à un script PHP via AJAX POST. Le problème est que si l'entrée est dans une langue qui n'est pas basé sur le latin, je finis par stocker du charabia dans la table MySQL. L'alphabet latin fonctionne très bien.

La page elle-même est capable de restituer des caractères UTF-8, s'ils se trouvent dans une donnée fournie lors du chargement de la page, c'est la publication avec laquelle je lutte.

اختبار

et enregistrer. Voir la requête Réseau POST dans les outils de développement du navigateur.

La publication s'effectue via la fonction JS suivante

function createEmptyStack(stackTitle) {
    return $.ajax({
        type:'POST',
        url:'ajax.php',
        data: {
            "do": 'createEmptyStack',
            newTitle: stackTitle
        },
        dataType: "json"
    });
}

Voici mon PHP.

header('Content-Type: text/html; charset=utf-8');

$newTitle = trim($_POST['newTitle']);

$db->query("
INSERT INTO t1(project_id, label) 
VALUES (".$_SESSION['project_id'].", '".$newTitle."')");

Lorsque je vérifie l'encodage sur la page comme ceci:

mb_detect_encoding($_POST['newTitle'], "auto");

J'obtiens le résultat: TF-8

J'ai également essayé l'en-tête suivant:

header("Content-type: application/json; charset=utf-8");

Le classement des tables MySQL où les données sont censées aller est défini sur tf8_general_ci

J'ai une autre page qui a un formulaire où les utilisateurs remplissent le même tableau et cela fonctionne parfaitement avec n'importe quelle langue. Lorsque je vérifie sur l'autre page pourquoi il est capable d'insérer des données similaires dans db avec succès, je vois la requête d'insertion ci-dessus:

mysql_query("SET NAMES utf8");

J'ai essayé de mettre la même ligne au-dessus de ma requête que les données semblent toujours du charabia. J'ai également essayé les deux alternatives suivantes:

 mysql_query("SET CHARACTER SET utf8 ");

et

mysql_set_charset('utf8', $db);

...mais en vain. Je suis piétiné. Besoin d'aide pour le comprendre.

Environnement:

PHP 5.6.40 (cgi-fcgi)

MySQL 5.6.45


MISE À JOUR

J'ai effectué plus de tests.

J'ai utilisé une phrase "ceci est un test" en arabe - هذا اختبار

Il semble que le code ajax.php fonctionne correctement. Après l'insertion de db, il retourne des valeurs encodées UTF-8, qui ressemblent à: "\ u0647\u0630\u0627\u0627\u062e\u062a\u0628\u0627\u0631" et l'encodage est défini sur: "UTF-8", cependant le les données insérées dans ma table db apparaissent comme: Ù ‡ Ø ° ا Ø§Ø®ØªØ¨Ø§Ø ±

Alors, pourquoi ne vais-je pas passer à la conversion de ma table db en un classement différent? Deux raisons: il a près de 0,5 million d'enregistrements et il fonctionne réellement correctement lorsque je vais sur une autre page qui fait très similaire INSERT.

Il s'avère que mon autre page utilise ASCII encodage lors de l'insertion des données. Il est donc naturel que j'essaie de converger vers ASCII sur ajax.php. Le problème que je finir avec des données vides. Je suis tellement confus maintenant ...

Merci


FIXED: basé sur quelques indices, j'ai fini par réécrire toutes les fonctions de cette page sur PDO et cela a fonctionné!

11
santa

Le sujet utf8 est un peu compliqué.

Lorsque vous utilisez UTF8 dans MySql, il est important de comprendre que l'UTF8 de MySql ne prend en charge que 3 octets de données, même si la spécification standard autorise jusqu'à 4 octets. En Unicode, vous avez beaucoup de caractères qui utilisent réellement ce 4ème octet, comme emojis comme ceci: ????. Avec utf8mb4 vous pouvez réellement prendre en charge entièrement et les sauvegarder dans la base de données sans aucun problème. Seul UTF8 vous laissera tomber.

Suivez simplement ces règles, et ça devrait aller:

  • Assurez-vous que tous vos fichiers source sont encodés en UTF8.
  • Assurez-vous d'avoir utf8 comme jeu de caractères par défaut dans php.ini :

    default_charset = "utf-8"
    
  • Assurez-vous d'utiliser utf-8 charset dans les en-têtes html:

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    
  • Assurez-vous de définir l'en-tête charset sur UTF8:

    header("Content-type: application/json; charset=utf-8");
    
  • Assurez-vous de définir utf8mb4 pour la connexion MySql dans PDO:

    $dsn='mysql:Host=example.com;dbname=testdb;port=3306;charset=utf8mb4';
    
  • Assurez-vous de créer des bases de données dans utf8mb4 ou de convertir db si vous devez:

    CREATE DATABASE mydatabase CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    
  • Assurez-vous de créer des tables dans utf8mb4 ou de les convertir si vous devez:

    CREATE TABLE my_table ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
    
  • TRÈS IMPORTANT: assurez-vous d'utiliser les fonctions de chaîne mb_ en PHP, car les fonctions de chaîne normales n'assumeront que des données à un octet. Cela signifie qu'au lieu d'utiliser strlen, qui comptera chaque octet, vous devez utiliser mb_strlen. De plus, des erreurs simples comme l'accès à une chaîne en tant que tableau briseront votre code, car $ string [0] n'accédera qu'au premier octet de votre chaîne, même bien que votre premier personnage puisse en avoir 4. Utilisez mb_substr dans ce cas!

Pour le dernier, vous aurez besoin de l'extension mbstring pour php. En outre, sachez que certaines extensions nécessitent que mbstring ait été chargé en premier, donc l'ordre dans lequel vous chargez votre extension peut être important, au cas où vous auriez besoin de l'installer.

Également en remarque: veuillez utiliser PDO et instructions préparées . Vous trouverez de nombreux tutoriels en ligne. L'injection SQL est toujours la plus grande vulnérabilité du Web et les instructions préparées sont la méthode la plus efficace pour empêcher l'injection SQL!

Si vous suivez la liste là-haut, vous n'aurez plus de problèmes.

S'amuser.

Quelques références: https://mathiasbynens.be/notes/mysql-utf8mb4

0
Daidon

J'ai rencontré un problème très similaire il y a environ un an avec un système avec lequel je travaillais et qui exécutait MySQL 5.7. Il me semble que certains de vos paramètres de base de données sont définis sur utf8 alors qu'ils devraient être définis sur utf8mb4. Cela permet à la base de données de gérer correctement les caractères multi-octets.

REMARQUE: le codage utf8mb4 a été ajouté à MySQL dans la version 5.5.

Les requêtes suivantes peuvent être utilisées pour modifier votre encodage. Assurez-vous de modifier les noms de base de données, de table et de colonne, ainsi que le type de données de colonne en fonction de votre situation:

# For each database:
ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
# For each table:
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
# For each column:
ALTER TABLE table_name CHANGE column_name column_name DATATYPE CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Des explications supplémentaires peuvent être trouvées ici.

Documentation pour cela sur votre version MySQL (5.6)

actuelle, documentation MySQL 8

0
drakin8564

Voici ce que j'ai utilisé pour faire fonctionner votre code:

<?php

$db = mysqli_connect("localhost", "root", "", "demo");
$db->set_charset("utf8");

// Check connection
if ($db === false) {
    die("ERROR: Could not connect. " . mysqli_connect_error());
}

$newTitle = trim($_POST['newTitle']);

$db->query("
        INSERT INTO t1(project_id, label) 
        VALUES ('5', '" . $newTitle . "')");

ajoutez cette balise à votre tête html:

<meta charset="utf-8">

J'ai testé avec latin1_bin et utf8_bin et cela a fonctionné dans les deux cas.

PHP version 7.3.9

MySQLi 5.0.12-dev

0
Kalimah