This question already has answers here:
UTF-8 all the way through
(13 answers)
Closed 5 months ago.
I use the PDO library with a MySQL database in PHP, but if I insert any data encoded in UTF-8, like Arabic words, it’s inserted into the database, but as ?????????.
In my own framework, after I create the PDO connection, I send two queries – SET NAMES utf8 and SET CHARACTER SET utf8. It still doesn’t work.
Example:
loadclass('PDO', array(
sprintf(
'mysql:host=%s;port=%s;dbname=%s',
confitem('database', 'host'),
confitem('database', 'port'),
confitem('database', 'name')
),
confitem('database', 'username'),
confitem('database', 'password'),
array('PDO::ATTR_PERSISTENT' => confitem('database', 'pconnect'))
));
$this->query('SET NAMES ' . confitem('database', 'charset'));
$this->query('SET CHARACTER SET ' . confitem('database', 'charset'));
Workaround: Use the json_encode function to convert data before inserting it to the database, and use json_decode to decode it after fetching. This is how I do it now.
Warning: This answer applies to PHP 5.3.5 and lower. Do not use it for PHP version 5.3.6 (released in March 2011) or later.
Compare with Palec's answer here.
Use:
$pdo = new PDO(
'mysql:host=hostname;dbname=defaultDbName',
'username',
'password',
array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")
);
It forces UTF-8 on the PDO connection. It worked for me.
You have to set the correct character set for the connection. Add the charset=utf8 option to the DSN (this is MySQL-specific!)
$pdo = new PDO(
'mysql:host=hostname;dbname=defaultDbName;charset=utf8',
'username',
'password'
);
However, in PHP versions before 5.3.6 (released in March 2011), you must use a workaround as the charset option in the DSN is not supported.
$pdo = new PDO(
'mysql:host=hostname;dbname=defaultDbName',
'username',
'password',
array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")
);
All attempts like:
PDO::MYSQL_ATTR_INIT_COMMAND =>"SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci' "
or
$this->connection = new PDO('mysql:host='.DBHOST.';dbname='.DBNAME.';charset=utf8', DBUSER, DBPASS, self::$opt);
or
$this->connection->exec("set names utf8");
still generated unreadable text mess.
In my case, the cause of the problem was: htmlentities used prior to inserting data into a database.
Cyrillic letters were destroyed completely.
Try setting the default_charset value in php.ini to UTF-8. Or you can set it using the ini_set function.
Also, if the input is coming through form submissions, make sure your web pages are set to UTF-8 using the meta tag.
When interacting with mysql or mariadb, charset 'utf8' is not correct. You need to use utf8mb4. Due to historical issues, utf8 in mysql/mariadb is an alias to utf8mb3 which can only contain a subset of utf8 (3 bytes instead of 4)
So adding 'charset=utf8mb4' to your PDO DSN connection string is the correct thing to do for recent PHP versions, NOT charset=utf8.
For example, the poop emoji in full color: 💩 cannot be stored if the column and PDO are not utf8mb4.
Related
Looking at here: http://www.php.net/manual/en/mysqlinfo.concepts.charset.php
I understand that using
SET NAMES utf8
is not a good idea, but it is not clear:
What is the issue?
How to avoid it?
Which is actually the solution to set the charset for a (or all) PDO connection(s) in a PHP 3.6 or higher?
The code I'm afraid is dangerous:
$this->_conn = new PDO('mysql:host=host.name.blabla;dbname=my_database_name','username', 'password',array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'
));
Thanks!
Are you really still using PHP >= version 3.6 and < 5.3.6 ?
Assuming you have 5.3.6 or later...
Character sets
and PDO_MYSQL DSN
say that you should use
$pdo = new PDO("mysql:host=localhost;dbname=mydb;charset=utf8",
'my_user', 'my_pass');
And implies (not clearly enough) that utf8 should be replaced by utf8mb4 if appropriate.
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8' is not as good, but was the alternative before 5.3.6.
I think "dangerous" is too strong a word, even pre-5.3.6.
A related technique: Using init_command = SET NAMES ... in my.cnf is bad because init_command is not executed when connecting as root.
utf8mb4 is the preferred CHARACTER SET for UTF-8 because it includes Emoji and some Chinese characters that were missing from utf8. That charset is available starting with MySQL version 5.5.3.
This question already has answers here:
Trouble with UTF-8 characters; what I see is not what I stored
(5 answers)
Closed 6 years ago.
I have problem with conversion from latin1 to utf8
I have got 2 databases, first is in latin1 second in utf8
Example:
select * from latin1_db gives
"SPÓŁDZIELNIA PRODUCENTÓW TRZODY ODRODZENIE BOBROWNIKI WĄGROWIEC"
but when i insert to utf8 db it becomes
"SPÓ?DZIELNIA PRODUCENTÓW TRZODY ODRODZENIEBOBROWNIKI W?GROWIEC"
how to make that both string will be same
i was using
$str=utf8_encode($str);
$str=Encoding::fixUTF8($str);
and
iconv
but result was not good.
You have to set the database connection encoding with
SET NAMES utf-8
as an sql query. You don't provide the code with the database request, so i cannot update your code to illustrate what i mean. With PDO it should be
$pdo = new PDO(
'mysql:host=yourdbhost;dbname=yourdbname',
'username',
'password',
array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")
);
Set database connection encoding to UTF-8.
Also have a look at this answer: Convert utf8-characters to iso-88591 and back in PHP.
mb_convert_encoding();
Might be useful for you.
This question already has answers here:
UTF-8 all the way through
(13 answers)
Closed 3 years ago.
I'm trying to insert a Cyrillic value in the MySQL table, but there is a problem with encoding.
Php:
<?php
$servername = "localhost";
$username = "a";
$password = "b";
$dbname = "c";
$conn = new mysqli($servername, $username, $password, $dbname);
mysql_query("SET NAMES 'utf8';");
mysql_query("SET CHARACTER SET 'utf8';");
mysql_query("SET SESSION collation_connection = 'utf8_general_ci';");
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "UPDATE `c`.`mainp` SET `search` = 'test тест' WHERE `mainp`.`id` =1;";
if ($conn->query($sql) === TRUE) {
}
$conn->close();
?>
MySQL:
| id | search |
| 1 | test ав |
Note: PHP file is utf-8, database collation utf8_general_ci
You are mixing APIs here, mysql_* and mysqli_* doesn't mix. You should stick with mysqli_ (as it seems you are anyway), as mysql_* functions are deprecated, and removed entirely in PHP7.
Your actual issue is a charset problem somewhere. Here's a few pointers which can help you get the right charset for your application. This covers most of the general problems one can face when developing a PHP/MySQL application.
ALL attributes throughout your application must be set to UTF-8
Save the document as UTF-8 w/o BOM (If you're using Notepad++, it's Format -> Convert to UTF-8 w/o BOM)
The header in both PHP and HTML should be set to UTF-8
HTML (inside <head></head> tags):
<meta charset="UTF-8">
PHP (at the top of your file, before any output):
header('Content-Type: text/html; charset=utf-8');
Upon connecting to the database, set the charset to UTF-8 for your connection-object, like this (directly after connecting)
mysqli_set_charset($conn, "utf8"); /* Procedural approach */
$conn->set_charset("utf8"); /* Object-oriented approach */
This is for mysqli_*, there are similar ones for mysql_* and PDO (see bottom of this answer).
Also make sure your database and tables are set to UTF-8, you can do that like this:
ALTER DATABASE databasename CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE tablename CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
(Any data already stored won't be converted to the proper charset, so you'll need to do this with a clean database, or update the data after doing this if there are broken characters).
If you're using json_encode(), you might need to apply the JSON_UNESCAPED_UNICODE flag, otherwise it will convert special characters to their hexadecimal equivalent.
Remember that EVERYTHING in your entire pipeline of code needs to be set to UFT-8, otherwise you might experience broken characters in your application.
In addition to this list, there may be functions that has a specific parameter for specifying a charset. The manual will tell you about this (an example is htmlspecialchars()).
There are also special functions for multibyte characters, example: strtolower() won't lower multibyte characters, for that you'll have to use mb_strtolower(), see this live demo.
Note 1: Notice that its someplace noted as utf-8 (with a dash), and someplace as utf8 (without it). It's important that you know when to use which, as they usually aren't interchangeable. For example, HTML and PHP wants utf-8, but MySQL doesn't.
Note 2: In MySQL, "charset" and "collation" is not the same thing, see Difference between Encoding and collation?. Both should be set to utf-8 though; generally collation should be either utf8_general_ci or utf8_unicode_ci, see UTF-8: General? Bin? Unicode?.
Note 3: If you're using emojis, MySQL needs to be specified with an utf8mb4 charset instead of the standard utf8, both in the database and the connection. HTML and PHP will just have UTF-8.
Setting UTF-8 with mysql_ and PDO
PDO: This is done in the DSN of your object. Note the charset attribute,
$pdo = new PDO("mysql:host=localhost;dbname=database;charset=utf8", "user", "pass");
mysql_: This is done very similar to mysqli_*, but it doesn't take the connection-object as the first argument.
mysql_set_charset('utf8');
Solution:
mysql_query("SET NAMES 'utf8';"); > $mysqli->set_charset('utf8');
I have São Tomé and Príncipe stored in a MySQL database.
It displays on my web page as S�o Tom� and Pr�ncipe
Is there anyway to display it properly straight from the database?
My MySQL Type is MyISAM and the collation is utf8_general_ci
My web page charset is <meta charset="utf-8">
Field type is set to varchar(30) and field collations is same as table utf8_general_ci
PHP FUNCTION TESTS
utf8_decode() converted characters to S?o Tom? and Pr?ncipe
htmlspecialchars_decode() converted characters to S�o Tom� and Pr�ncipe
html_entity_decode() converted characters to S�o Tom� and Pr�ncipe
quoted_printable_decode() converted characters to S�o Tom� and Pr�ncipe
htmlentities() returned blank result
GOT IT TO WORK THANKS TO #SAEVEN
Ran this right before my query SELECT
mysqli_query($GLOBALS['db_link'], "SET NAMES 'utf8'");
Could it be that you need to specify your namespace collation at the connection level?
I assume that you've covered the basics, you've got the charset as utf8 in your HTML markup.
Try executing this SQL statement before you do any of your database queries:
'SET NAMES utf8'
e.g., if you are using PDO
// do your regular connection logic whatever it is
$dbc = new PDO( .... );
$dbc->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbc->query( 'SET NAMES utf8' );
// run your queries beneath
....
or can use the shorthand
new PDO(
'mysql:host=mysql.example.com;dbname=awesome_db',
"username",
"password",
array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")
);
Whatever DBAL you use, that query'll work. Just run it on the same connection you use to pull your data, before pulling it (only needs to be done once)
I've a MySQL table that has a UTF-8 charset and upon attempting to insert to it via a PHP form, the database gives the following error:
PDOStatement::execute():
SQLSTATE[HY000]: General error: 1366
Incorrect string value: '\xE8' for
column ...
The character in question is 'è', yet I don't see why this should be a problem considering the database and table are set to UTF-8.
Edit
I've tried directly from the mysql terminal and have the same problem.
Your database might be set to UTF-8, but the database connection also needs to be set to UTF-8. You should do that with a SET NAMES utf8 statement. You can use the driver_options in PDO to have it execute that as soon as you connect:
$handle = new PDO("mysql:host=localhost;dbname=dbname",
'username', 'password',
array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
Have a look at the following two links for more detailed information about making sure your entire site uses UTF-8 appropriately:
UTF-8 all the way through…
UTF8, PHP and MySQL
E8 is greater than the maximum usable character 7F in a one-byte UTF8 character: http://en.wikipedia.org/wiki/UTF-8
It seems your connection is not set to UTF8 but some other 8 bit encoding like ISO Latin. If you set the database to UTF8 you only change the character set the database uses internally, connections may be on a different default value (latin1 for older MySQL versions) so you should try to send an initial SET CHARACTER SET utf-8 after connecting to the database. If you have access to my.cnf you can also set the correct default value there, but keep in mind that changing the default may break any other sites/apps running on the same host.
Before passing the value to Mysql you can use the following code:
$val = mb_check_encoding($val, 'UTF-8') ? $val : utf8_encode($val);
convert the string the to UTF-8, If it's matter of only one field.