Prevent special characters replacement into my DB with PHP - php

When I save François into my DB, it becomes François.
How can I prevent it to keep François ?
During my PDO connection I already use PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8".
Thanks.

you can change charset to utf8 after starting PDO connection.
$pdo_object = new PDO(...);
$pdo_object->exec("SET NAMES 'utf8'; SET CHARSET 'utf8'");

Related

Is PDO ... SET NAMES utf8 dangerous?

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.

How to use UTF-8 with Firebird and PHP Data Objects (PDO)

With mysql I can just do this to solve the problem:
$diveOptions = array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"); // set names utf-8 and works well
$pdo = new PDO('mysql:host=mysql.example.com;dbname=example_db',"username","password",diveOptions);
But I can't do the same with the firebird's pdo connection.
How can I solve this problem of UTF-8?
Already tried charset=utf8 in pdo configuration don t work too..
$str_conn = "firebird:dbname=C:\db\banco.gdb;charset=utf8;host=localhost";
$dbh = new PDO($str_conn, "SYSDBA", "masterkey");
In my db was set to nome like this:
DEFAULT CHARACTER SET NONE COLLATION NONE;

How to properly display non-redable characters stored in a MySQL Database

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)

Mysql php character set setting

At first we was using the default character set by the mysql that was latin1_swedish_ci. Then we had problem with other languages like russian etc. So we have now converted the tables into collation and the field into utf8_unicode_ci. We need some confirmation here should we stick with utf8_unicode_ci for the support all the possible languages or go for something else like utf8_bin?
Next issue for php files where we are using mysqli we have set this.
if (!mysqli_set_charset($link, "utf8")) {
echo("Error loading character set utf8: ". mysqli_error($link));
}
else {
echo("Current character set: ". mysqli_character_set_name($link));
}
Then for places where we use mysql only we did as below
mysql_query("SET NAMES 'utf8'");
mysql_query("SET CHARACTER SET utf8");
mysql_query("SET COLLATION_CONNECTION = 'utf8_unicode_ci'");
The problem now we find this is like quite tedious and we are scared we might be miss. Is it possible to set this character setting in like a config file like we have one for our db connection?
Don't mix mysql_* with mysqli_* functions. You need to stay consistent! You use mysqli_ first and then you use mysql_. That won't work!
This is how I do it:
mysqli_set_charset($Handle, 'utf8'); // <- add this too
mysqli_query($Handle, "SET NAMES 'utf8';");
mysqli_query($Handle, "SET CHARACTER SET 'utf8';");
mysqli_query($Handle, "SET COLLATION_CONNECTION = 'utf8_unicode_ci';");
// might be a bit redundant but it's safe :) ... I think :)
Then make sure you provide proper UTF8 to it.

Set character set using MySQLi

I'm fetching data in Arabic from MySQL tables with MySQLi. So I usually use this in procedural style:
mysql_query("SET NAMES 'utf8'");
mysql_query('SET CHARACTER SET utf8');
Now I am using the OOP style so I am trying to see if there is something I could set rather than the above?
I only found this in PHP manual so I did it, but what about setting names to UTF8?
$mysqli->set_charset("utf8");
It's the same:
$mysqli->query("SET NAMES 'utf8'");
From the manual:
This is the preferred way to change the charset. Using mysqli::query()
to execute SET NAMES .. is not recommended.
$mysqli->set_charset("utf8"); is just enough, let the mysqli db driver do the thing for you.
You should use
$mysqli->set_charset("utf8");
Don't use SET NAMES or SET CHARACTER SET explicitly when using MySQLi., and certainly don't use both like the question asker here originally was. Reasons that this is a bad idea:
Calling SET CHARACTER SET utf8 after SET NAMES utf8 actually just undoes some of the work that SET NAMES did.
The PHP manual explicitly warns us to use mysqli_set_charset, not SET NAMES:
This is the preferred way to change the charset. Using mysqli_query() to set it (such as SET NAMES utf8) is not recommended. See the MySQL character set concepts section for more information.
Under the hood, mysqli_set_charset is just a wrapper for mysql_set_character_set from the MySQL C API (or its mysqlnd equivalent). Looking at the docs for that function, we can see the difference between it and SET NAMES:
This function works like the SET NAMES statement, but also sets the value of mysql->charset, and thus affects the character set used by mysql_real_escape_string()
In other words, $mysqli->set_charset('foo') will do everything SET NAMES foo does and also ensure that mysqli_real_escape_string respects the new encoding. Admittedly, if you're only using encodings like Latin 1 and UTF 8 that strictly extend ASCII (that is, which encode all ASCII strings exactly as they would be encoded in ASCII), then using SET NAMES instead of set_charset won't break anything. However, if you're using more unusual encodings like GBK, then you could end up garbling your strings or even introducing SQL injection vulnerabilities that bypass mysqli_real_escape_string.
It's thus good practice to only use set_charset, not SET NAMES. There's nothing that SET NAMES does that set_charset doesn't, and set_charset avoids the risk of mysqli_real_escape_string behaving incorrectly (or even insecurely).
You can use this. Its realy nice for mysqli Character Set
$dbhost = "localhost";
$dbuser = "root";
$dbpass = "dbpass";
$dbname = "dbname";
$conn = mysqli_connect($dbhost,$dbuser,$dbpass,$dbname);
mysqli_query($conn,"SET CHARACTER SET 'utf8'");
mysqli_query($conn,"SET SESSION collation_connection ='utf8_unicode_ci'");
For procedural style lovers.
// Create connection
$conn = mysqli_connect($servername, $username, $password, $dbname);
/* change character set to utf8 */
mysqli_set_charset($conn,"utf8");
mysqli_query($conn,"SET NAMES 'latin5'");
$conn = connection string

Categories