5

im trying to safe spanish words with accent in my database but it won't work, i have already tried:

1) changing conllation from tables and rows to utf8_spanish_ci and utf_unicode_ci.

2)adding a header tag with

<meta http-equiv="Content-type" content="text/html; charset=utf-8" />

3)adding

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

in a php tag.

doing this in an xampp server in my laptop will work, but when i upload the database to a login monster server it wont save the accent properly.

edit: this is the connection im using:

    private function Connect()
    {
        //$this->settings = parse_ini_file("settings.ini.php");
        try 
        {
            # Read settings from INI file, set UTF8
            $this->pdo = new PDO('mysql:host=localhost;dbname=xxxxx;charset=utf8', 'xxxxx', 'xxxxxx', array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));

            # We can now log any exceptions on Fatal error. 
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

            # Disable emulation of prepared statements, use REAL prepared statements instead.
            $this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

            # Connection succeeded, set the boolean to true.
            $this->bConnected = true;
        }
        catch (PDOException $e) 
        {
            # Write into log
            echo $this->ExceptionLog($e->getMessage());
            die();
        }
    }

Edit:

i can't save accent, it shows like strange characters like á = á

2one2
  • 381
  • 2
  • 10
  • 23
  • Change the database collation to `utf8_general_ci` and set the meta content-type to `text/html; charset=utf-8` – Philipp Oct 19 '15 at 17:04
  • @Philipp *Collation* has no effect on character set of stored data. *Collation* affect ordering only. Also he's already using the meta content-type you're advising him. – David Ferenczy Rogožan Oct 19 '15 at 17:36
  • 1
    possible duplicate of [UTF-8 all the way through](http://stackoverflow.com/questions/279170/utf-8-all-the-way-through) but I won't mark it as a close vote because it looks like you're doing everything right so far. Worth reading in any case – Phil Oct 23 '15 at 02:16
  • What version of PHP is running on the remote server? – Phil Oct 23 '15 at 02:18
  • So did you solved it? Check also if your data are not broken (see the note in my answer). – David Ferenczy Rogožan Oct 23 '15 at 12:42
  • What do you mean exactly by "don't work"? Do you receive an error message while inserting to the table? Does the text not sort correctly? Are you unable to make a search query on the accents? Does the text show up as replaced blocks? – Lie Ryan Oct 23 '15 at 13:37
  • show please your table schema? and screenshot that proofs that `monster server it wont save the accent properly` like screenshot of simple `INSERT` using phpmyAdmin and `SELECT` that row back right after. – Alex Oct 23 '15 at 14:45
  • i can't save accent, it shows like strange characters like á = á – 2one2 Oct 23 '15 at 21:16
  • @2one2 I was flagging another question as a duplicate of this question now and found out that this question has accepted the down-voted answer. It may be confusing for others, probably would be good to fix it. – David Ferenczy Rogožan May 10 '16 at 14:48

4 Answers4

8

Collation affects text sorting only, it has no effect on actual character set of stored data.

I would recommend this configuration:

  1. Set the character set for the whole DB only, so you don't have to set it for each table separately. Character set is inherited from DB to tables to columns. Use utf8 as the character set.

  2. Set the character set for the DB connection. Execute these queries after you connect to the database:

    SET CHARACTER SET 'utf8'
    SET NAMES 'utf8'
    
  3. Set the character set for the page, using HTTP header and/or HTML meta tag. One of these is enough. Use utf-8 as the charset.

This should be enough.

If you want to have proper sorting of Spanish strings, set collation for the whole database. utf8_spanish_ci should work (ci means Case Insensitive). Without proper collation, accented Spanish characters would be sorted always last.

Note: it's possible that the character set of data you already have in a table is broken, because you character set configuration was wrong previously. You should check it using some DB client first to exclude this case. If it's broken, just re-insert your data with the right character set configuration.

How does character set work in a database

  • objects have a character set attribute, which can be set explicitly or it's inherited (server > database > table > column), so the best option is to set it for the whole database

  • client connection has also a character set attribute and it's telling the database in which encoding you're sending the data

If client connection's and target object's character sets are different, the data you're sending to the database are automatically converted from the connection's character set to the object's character set.

So if you have for example the data in utf8, but client connection set to latin1, the database will break the data, because it'll try to convert utf8 like it's latin1.

David Ferenczy Rogožan
  • 23,966
  • 9
  • 79
  • 68
  • 1
    already did 1 and 3. this is how i have my pdo connection. $this->pdo = new PDO('mysql:host=localhost;dbname=xxxx;charset=utf8', 'xxxxx', 'xxxxx', array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")); still not working – 2one2 Oct 19 '15 at 21:25
  • 1
    Please execute two queries from the item 2 right after you connect to the DB as you would execute any other queries. If it doesn't work we can try to find the reason. – David Ferenczy Rogožan Oct 21 '15 at 01:12
  • im executing both query's, maybe im wrong but i saw in another post that using 'mysql:host=localhost;dbname=xxxxx;charset=utf8' sets the charset and im already using array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8") – 2one2 Oct 23 '15 at 21:18
  • also how do you check if a table data is broken? – 2one2 Oct 23 '15 at 21:22
  • @2one2 -- `SELECT col, HEX(col) FROM tbl WHERE ...` If col has `á`, HEX(col) should have `C3A1` for utf8 (or utf8mb4). – Rick James Oct 26 '15 at 00:39
3

Here is my checklist for storing UTF8 characters. Though, be sure to isolate the cause of failure to be on the part where you store the strings into the database -- meaning the string to store is still as it was when the user inputed it.

First. Make sure the character set of the table being used is utf8 or better yet use utf8mb4 for full unicode support (though it has its drawbacks too). It doesn't matter which charset has been set for the entire database; it is overridden by the table definition, if specified. The DDL code for creating such a table would be like:

CREATE TABLE table_name (
    id INT AUTO_INCREMENT NOT NULL,
    name VARCHAR(190) NOT NULL,
    date_created DATETIME NOT NULL,
    PRIMARY KEY(id)
)
DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci
ENGINE = InnoDB;

Second. Use utf8 charset for the database connection.

// This should be enough
new PDO(
    'mysql:host=localhost;dbname=xxxxx;charset=utf8mb4;',
    'username',
    'password'
);
Czar Pino
  • 6,258
  • 6
  • 35
  • 60
  • I just would advice you to set a character set for the whole DB, so you don't have to set it for each table separately (a potentially forget to set it for some table). – David Ferenczy Rogožan Oct 23 '15 at 10:37
  • Good advice and I agree with you; I, in fact, do that. Though in practice, I'd still favor explicitly setting the charset of a table even when a sensible default is set for the entire db. This forces you to really think about the data you're trying to store in a table (i.e. what charset to use) and also helps to avoid "accidentally" using the wrong charset. – Czar Pino Oct 23 '15 at 14:11
  • I had a problem with diacritic characters despite using `utf8mb4` and setting the `charset=utf8mb4` in the first `PDO()` argument is what helped me. – Amin NAIRI Jun 03 '17 at 20:32
0

For MySql Use these code after invoking the database connection:

$set_utf=$dbh->exec("SET NAMES UTF8"); 
digitai
  • 1,870
  • 2
  • 20
  • 37
0

I had to store a lot of accentuated letters from different languages (including french and spanish), and the only safe way I found at the moment was to store everything in utf8_bin in MySQL, and display pages in charset utf-8 like you do. No further processing needed, neither from MySQL, nor from PHP.

Also, make sure your IDE manages your files in utf8.

Stéphane
  • 500
  • 5
  • 22
  • im not using an ide, im using notepad, is there a way to manage it with notepad? – 2one2 Oct 23 '15 at 21:21
  • 1
    If you're talking about Notepad++ (if not, you should have a look at https://notepad-plus-plus.org/ ), there is specific menu to manage file encoding. I can't give you the menu's name, my np++ is in french, but it's the equivalent of "encoding". – Stéphane Oct 25 '15 at 08:20