character encoding plays a rule at multiple places in your scenario
- which encoding does the client use for sending the parameters to the server
- which encoding does the mysql server use to intepret characters send from the php script to the server
- which encoding does the mysql server use to send results back to the php script
- which encoding does the mysql server use to store the data
- which encoding does the client/browser use to render the data send from the php script to the client/browser
It's simplest to keep the whole chain at utf-8 encoding:
Set the character encoding of the html documents you send to the browser to utf-8, e.g. via default_charset.
Indicate to the mysql server that the connection charset is utf-8, e.g. via setting the charset property in the PDO-MYSQL DSN.
Create the table using utf-8 as default charset and without specifiying another encoding for the field itself.
Self-contained example:
<?php
ini_set('default_charset', 'utf-8');
$fn = isset($_POST['val']) ? 'doDatabase' : 'doForm';
doHtml($fn);
function doHtml($fn) { ?>
<html>
<head><title>...</title></head>
<body>
<?php $fn(); ?>
</body>
</html>
<?php
}
function doForm() { ?>
<form method="POST" action="?">
<div>
<input type="text" name="val" value="®" />
<input type="submit" />
</div>
</form>
<?php
}
function doDatabase() {
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'localonly', 'localonly');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->exec('
CREATE TEMPORARY TABLE soFoo (
id int auto_increment,
val varchar(30),
primary key(id)
) DEFAULT CHARACTER SET utf8
');
$stmt = $pdo->prepare('INSERT INTO soFoo (val) VALUES (?)');
$stmt->execute( array($_POST['val']) );
$stmt = null;
foreach( $pdo->query('SELECT * FROM soFoo', PDO::FETCH_ASSOC) as $row ) {
echo 'row: ', join(', ', $row), "<br />\r\n";
}
}