Special characters to mysql from php - php

I know there have been a lot of almost the same questions, but I still didn't find the answer to my problem.
I want to place "les Îles Açores" into the db. But I get:
les Îles Açores
I tried usin:
SET Names 'ut8)
$mysqli->set_charset("utf8");
mysql_real_escape_string()
htmlentities (Here I got htmlentities, but I want to know if there's another way)
Code:
$name_fr = $_POST["name_fr"]; $name_nl = $_POST["name_nl"];
$arr_kollommen = array("NAME_FR","NAME_NL");
$arr_waardes = array($naam_nl,$naam_fr);
$obj_db->insert("landen",$arr_kollommen,$arr_waardes);
Does someone has an idea how to solve my litle problem?
Thank you very much!

Make sure the table uses the correct CHARSET, for example:
CREATE TABLE myTable (
one VARCHAR(255),
two VARCHAR(255)
) DEFAULT CHARSET=utf8;

Make sure you actually write in UTF8 (meaning your IDE / editor you write your code must have encoding set to UTF8).
Is the record corrupted both in the DB and on your page after you fetch it or only in DB?

$name_fr = $_POST["name_fr"];
$name_nl = $_POST["name_nl"];
$arr_kollommen = array("NAME_FR","NAME_NL");
$arr_waardes = array($naam_nl,$naam_fr);
$obj_db->insert("landen",$arr_kollommen,$arr_waardes);
Try using instead of encode to utf_8 decode.
like this:
$name_fr = $_POST["name_fr"];
$name_nl = $_POST["name_nl"];
$naam_fr = utf8_decode($naam_fr);
$naam_nl = utf8_decode($naam_nl);
$arr_kollommen = array("NAME_FR","NAME_NL");
$arr_waardes = array($naam_nl,$naam_fr);
$obj_db->insert("landen",$arr_kollommen,$arr_waardes);

2 possible reasons i can see:
1) Your database doesn't feature UTF-8 fields
2) When you read your data from the server, you are not setting the connection as utf-8. If you have to set it utf-8 when writting you also have to set it utf-8 when reading.
Check using PHPMyAdmin if the data is wrecked... If it is, then it means that your SET names'utf-8' is not working...

Do you pass the "UTF-8" parameter into your htmlentities, and html_entity_decode this way ?
html_entity_decode($text,ENT_QUOTES , "UTF-8");

Related

charset issue with accents retrieving DB2 values with php over odbc

I'm trying to do a select from a DB2 through PHP and odbc and then save those values on a file. The OS where the code is being executed is Debian. What I do is the following:
$query = "SELECT NAME FROM DATABASE_EXAMPLE.TABLE_EXAMPLE";
$result = odbc_prepare($server, $query);
$success = odbc_execute($result);
$linias = "";
if ($success) {
while ($myRow = odbc_fetch_array($result)) {
$linias .=format_word($myRow['NAME'], 30) . "\r\n";
}
generate_file($linias);
function format_word($paraula, $longitut) {
return str_pad(utf8_encode($paraula), $longitut, " ", STR_PAD_LEFT);
}
function generate_file($linias) {
$nom_fitxer = date('YmdGis');
file_put_contents($nom_fitxer . ".tmp", $linias);
rename($nom_fitxer . '.tmp', $nom_fitxer . '.itf');
}
The problem is that some of the retrieved values contains spanish letters and accents. To make and example, one of the values is "ÁNGULO". If I var_dump the code on my browser I get the word fine, but when it's write into the file it apends weird characters on it (that's why I think there is a problem with the charset). I have tried different workarounds but it just make it worst. The file opened with Notepad++ (with UTF8 encoding enabled) looks like:
Is there a function in PHP that translate between charsets?
Edit
Following erg instructions I do further research:
The DB2 database use IBM284 charset, as I found executing the next command:
select table_schema, table_name, column_name, character_set_name from SYSIBM.COLUMNS
Firefox says the page is encoded as Unicode.
If i do:
var_dump(mb_detect_encoding($paraula));
I get bool(false) as a result.
I have changed my function for formating the word hoping that iconv resolve the conflict:
function format_word($paraula, $longitut) {
$paraula : mb_convert_encoding($paraula, 'UTF-8');
$paraula= iconv("IBM284", "UTF-8", $paraula);
return $paraula;
}
But it doesn't. Seems like the ODBC it's doing some codification bad and that is what mess the data. How can I modify the odbc to codificate to the right charset? I have seen some on Linux changing the locale, but if I execute the command locale on the PC I get:
LC_NAME="es_ES.UTF-8"
LC_ADDRESS="es_ES.UTF-8"
...
I will try to summarize from the comments into an answer:
First note that PHPs utf8_encode will convert from ISO-8859-1 to utf-8. If your database / ODBC-Driver does not return ISO-8859-1 encoded strings, PHPs utf8_encode will fail or return garbage.
The easiest solution should be to let the database / driver convert the values to correct encoding, using its CAST function: https://www.ibm.com/support/knowledgecenter/SSEPEK_11.0.0/sqlref/src/tpc/db2z_castspecification.html
Try to alter your query to let DB2 convert everything to UTF-8 directly and omit the utf8_encode call. This can be done by altering you query to something like:
SELECT CAST(NAME AS VARCHAR(255) CCSID 1208) FROM DATABASE_EXAMPLE.TABLE_EXAMPLE
Thanks to Sergei for the note about CCSID 1208 on IBM PUA. I changed CCSID UNICODE to CCSID 1208.
I do not have DB2 at hand here, so the above query is untested. I'm not sure if this will return utf-8 or utf-16..

Echo from database in collation "latin1_swedish_ci" results in questionmark symbols on webpage

I feel like this should be a simple fix, but the answer eludes me. Ive tried googling, and searching here... to no avail.
i have a long text stored in my database.
The collation is latin1_swedish_ci"
and when I see it in the database, it is stored correctly. For example:
string= Sally was walking one day and saw Tom. Tom said "Hi, Sally!" Sally's response was "Hi, Tom."
every " or ' shows up as a white question mark on a black diamond.
I want to
$result=mysqli_query($db,"SELECT string FROM Table WHERE 1")
while($row = mysqli_fetch_assoc($result)){
echo $row['string'];
}
and have all of the characters show up.
can anyone help?
You may be able to fix yours with this example.
SQL:
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`string` longtext,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
INSERT INTO `test` VALUES ('1', 'Sally was walking one day and saw Tom. Tom said \"Hi, Sally!\" Sally\'s response was \"Hi, Tom.\"');
PHP:
$query = "SELECT id, string FROM test WHERE id = 1";
if ($result = mysqli_query($link, $query)) {
while ($row = mysqli_fetch_assoc($result)) {
echo $row['string'];
}
mysqli_free_result($result);
}
mysqli_close($link);
A single question mark is one kind of symptom; a string of question marks is another; and black diamond with a question mark is yet another problem. Sweep the slate clean... Get rid of all encoding functions and...
Have the data in the client be utf8-encoded, and
Establish that the connection is CHARACTER SET utf8, and
Have the tables/columns be CHARACTER SET utf8, and
On html pages, use <meta charset=UTF-8>.
After doing some more research, I found a post that didn't come up before.
This solution to a similar problem was offered by Emil H:
MySQL performs character set conversions on the fly to something
called the connection charset. You can specify this charset using the
sql statement
SET NAMES utf8 or use a specific API function such as
mysql_set_charset():
mysql_set_charset("utf8", $conn); If this is done correctly there's no
need to use functions such as utf8_encode() and utf8_decode().
You also have to make sure that the browser uses the same encoding.
This is usually done using a simple header:
header('Content-type: text/html;charset=utf-8'); (Note that the
charset is called utf-8 in the browser but utf8 in MySQL.)
In most cases the connection charset and web charset are the only
things that you need to keep track of, so if it still doesn't work
there's probably something else your doing wrong. Try experimenting
with it a bit, it usually takes a while to fully understand.
shareedit edited Mar 25 '09 at 12:17 answered Mar 25 '09 at 11:52
Emil H 28k75778
after reading that, I looked up the php code she/he was talking about and found that there is an sqli equivilant, with different syntax.
(PHP 5 >= 5.0.5, PHP 7)
mysqli::set_charset -- mysqli_set_charset — Sets the default client character set
Description ¶
Object oriented style
bool mysqli::set_charset ( string $charset )
Procedural style
bool mysqli_set_charset ( mysqli $link , string $charset )
Sets the default character set to be used when sending data from and to the database server.
I hope this helps anyone having the problem I had.

set charset when saving files with php

I created a simple code for uploading pictures to a folder, with PHP.
On the server side I have
<?php
header('Content-Type: text/plain; charset=utf-8');
//check if file is actually an image etc.
//if is an image, send it to "upload" folder
move_uploaded_file($_FILES["file"]["tmp_name"],"upload/" . $_FILES["file"]["name"]);
//save to the database a string like "upload/myImage.jpg", so I can render it on the site later
$stu = $dbh->prepare("UPDATE multi SET m_place=:name WHERE m_id = :id");
$stu->bindParam(':name', $n, PDO::PARAM_STR);
$n= "upload/".$_FILES["file"]["name"];
$stu->execute();
The problem?
If the name of the image is in english in the folder I see a "myImage01.jpg" and in the database also "upload/myImage01.jpg". But, if the name of the image is in greek in the folder I see "χωΟΞ―Ο‚ τίτλο.jpg" and in the db "upload/χωΟΞ―Ο‚ τίτλο.jpg".Which is wrong. Insted of χωΟΞ―Ο‚ τίτλο I should get "χωρις τιτλο" (thats greek for "no title" btw). So , I guess charset problem?
How do I fix this?
Thanks in advance
It sounds like your database doesn't have the correct collation. Make sure the tables/columns are using utf8_general_ci for their collation.
Also extremely important when handling UTF8 is to use the following two MySQL lines for GET requests...
SET time_zone = '+00:00'
SET CHARACTER SET 'utf8'
...and when you have a POST request use the following two...
SET time_zone = '+00:00'
SET NAMES 'utf8'
These will help ensure that UTF8 characters are maintained correctly.
Finally, I figure out that "PHP filesystem functions can only handle characters that are in system codepage". Thanks to this I solve my problem.
I used the iconv function
So I changed the move_uploaded_file line like so
move_uploaded_file($_FILES["file"]["tmp_name"],"upload/" . iconv('UTF-8', 'Windows1253',$_FILES["file"]["name"]));

How to safelycompare UTF-8 to ISO 8859-1 (latin1) in PHP?

This might be a stupid question, but nothing seems to be working for me:
I'm having to compare values between 2 columns on 2 different databases (which I don't have access to change the values).
The encoding in db1 is UTF-8.
The encoding in db2 is latin1.
So, for example, these are the 2 values I'm comparing and should be the same in the comparison:
**db1_value** = 'Maranhão'
**db2_value** = 'Maranhão';
They display exactly the same way using utf_encode, displaying is not the issue.
I'd like to compare the variable db1_value to the field db2_value in the db, so I'm using something very simple like this:
$query = "SELECT **db2_value** FROM db2 WHERE db2_field LIKE '" . **$db1_value** . "'";
How do I convert 'Maranhão' into '**Maranhão**' before comparing?
I've tried several methods, iconv, utf8_encode, and a few others, but they make no difference to the variable. I'm just wondering if I'm taking the right approach to do this.
Appreciate any constructive comments on this.
Thanks a lot,
You need to convert not from UTF-8 but from HTML-ENTITIES into actual value
Luckily mbstring extension has such conversion available:
$latin1 = mb_convert_encoding($db1_value, "ISO-8859-1", "HTML-ENTITIES");
Here we specify the HTML-ENTITIES as the FROM charset
Then you can compare $latin1 to your $db2_value.

Store BLOB-like data in PostgreSQL

I recently switched from MySQL to PostgreSQL. I have one problem left however.
Previously, I would store small images in the BLOB format in MySQL.
PostgreSQL doesn't know such thing as a BLOB.
I tried using BYTEA field type instead. This actually inserts an large (hexadecimal?) string I guess, but now I'm stuck trying to get this string back to displaying an actual image in PHP..
Any ideas? Thanks in advance.
Here is a piece of code I use to save the image in the database:
$data = bin2hex(file_get_contents('php://input'));
if (!empty($data)) {
$sql = "UPDATE asset SET data = X'%s' WHERE uuid = '%s'";
$args = array($data, $asset_uuid);
}
psql (9.1.3) and php 5.3.6 are used
Bytea is a byte array. It's not a bit pattern. See section 4.2.1.5 of PostgreSQL Lexical Structure.
The correct way to enter bytea is '\x...' with hex values. So what you want is SET data = '\x%s'.
You might also want to look into prepared statements with pg_prepare.
Edit: I was able to insert a (text) file into a bytea with this:
$source = file_get_contents( 'hello.php' );
$insert = pg_prepare( $conn, '', 'insert into t (name, data) values($1,$2)' );
pg_execute( $conn, '', array( 'hello.php', $source ) );
3rd Edit: This works fine to insert the file into the database. However, the pgsql driver in PHP is quite impolite. The only way to retrieve the actual data back is using the old bytea escape mechanism, as detailed here: pg_unescape_bytea.
pg_query('SET bytea_output = "escape";');
$result = pg_query( 'select data from t' );
while ( $row = pg_fetch_row( $result ) ) {
echo pg_unescape_bytea( $row[0] );
}
I'm sorry about how annoying this is. The PostgreSQL interface in PHP can do with some major overhaul for binary values.
To insert bytea contents with the pg_* API, the binary value should always be run through the pg_escape_bytea() function, even if it's passed to the pg_execute or pg_query_params functions.
This is because the pg_* layer doesn't "know" that a particular parameter has binary contents, and it does not implement any real support for parameter types anyway. So the text representation must be used. It can either be in the escape form or the hex form, it doesn't matter to the PG server, and it's independant of the value of bytea_output, which is meaningful only for values read from the server.
Example:
$esc=pg_escape_bytea("\000\001\002");
pg_query_params('INSERT INTO some_table(some_col) VALUES($1)', array($esc));
To read bytea contents with the pg_* API, the value must be run through pg_unescape_bytea() after the fetch. Assuming the client library is not older than 9.0 (libq.so.5.3 or higher), it can decode the contents whether it's in hex form or escape form and it will autodetect it. Only with an older library would it be necessary to force bytea_output to escape for it to decode properly, either dynamically with SET or statically for the whole database (ALTER DATABASE SET bytea_output=escape) or in postgresql.conf for the whole instance.
Example:
$p=pg_query("SELECT some_col FROM some_table WHERE...");
$r=pg_fetch_array($p);
$contents = pg_unescape_bytea($r[0]);
Both answers posted here gave me some thoughts, but none were 100% of the answer.
So, I will explain in this answer what I did to get it to work.
When displaying the image, I used this:
header('Content-Type: image/jpeg');
$data = pack("H*", pg_unescape_bytea($data));
echo $data;
I'm running PHP 5.3.8, in PHP 5.4.0 it turns out you can use hex2bin instead of pack.
When adding the image to the database, I used this:
$data = pg_escape_bytea($data); // Escape input for PostgreSQL
$sql = "UPDATE asset SET data = '%s'WHERE uuid = '%s'";
I'm glad it is working now. Thank you both Daniel and Johann!

Categories