I have a table, in mysql, which is in unicode and in phpmyadmin (running on the same machine and server) looks like this...

So unless I am missing something, the data is correct.
However, when I display this information it comes out like this...
Chinese Traditional / ?? (??)
So I must be doing something wrong. I am running PHP5 on Apache 2 on windows but have had the same problem with apache on anything else but have NOT had the problem with IIS on windows XP. I have had the same problem with both PHP 4 and 5.
The code that gets this information is as follows (it is all object oriented which makes it harder to post in a forum like this...)
This is from a CMS which can run multiple sites, each site in multiple languages. It works beautifully on MySQL 4 and not using unicode. Upgrading it is hurting my head and I could really use a helping hand.
I have put the classes that are involved at the top and then the procedural code at the bottom. I know there is a lot but I want to be thorough so that you can see everything that touches this. The page IS output as utf-8 and the browser recognises it as such.
<?php
// The DB class that is being called
class DB
{
var $host_name;
var $user_name;
var $password;
var $db_name;
var $conn_id = "";
var $errno = "";
var $errstr = "";
var $halt_on_error = true;
var $query_pieces = array ();
var $num_rows = "";
var $row = array();
var $row_multiple = array();
var $temp_row = array();
var $insert_id;
function DB ()
{
global $cfg;
$this->host_name = $cfg['dbHostName'];
$this->user_name = $cfg['dbUserName'];
$this->password = $cfg['dbPassword'];
$this->db_name = $cfg['dbName'];
}
function connect ()
{
$this->errno = 0;
$this->errstr = "";
if ($this->conn_id == 0)
{
$this ->conn_id = @mysql_connect ($this->host_name,
$this->user_name,
$this->password);
if (!$this->conn_id)
{
if (mysql_errno())
{
$this->errno = mysql_errno();
$this->errstr = mysql_error();
}
else
{
$this->errno = -1;
$this->errstr = $php_errormsg;
}
$this->error("Cannot connect to the server");
return (false);
}
if (isset($this->db_name) && $this->db_name != "")
{
if (!@mysql_select_db($this->db_name, $this->conn_id))
{
$this->errno = mysql_errno();
$this->errstr = mysql_error();
$this->error("Cannot Select Database");
return (false);
}
}
}
return ($this->conn_id);
}
function disconnect ()
{
if ($this->conn_id !=0)
{
mysql_close ($this->conn_id);
$this->conn_id = 0;
}
return true;
}
function error ($msg)
{
if (!$this ->halt_on_error)
{
return;
}
$msg .="\n";
if ($this->errno)
{
$msg .= sprintf("Error: %s (%d)\n", $this->errstr, $this->errno);
die (nl2br(htmlspecialchars($msg)));
}
}
function issue_query ($query_str)
{
if (!$this->connect ())
{
return false;
}
$this->num_rows = 0;
$this->result_id = mysql_query($query_str, $this->conn_id);
$this->errno = mysql_errno();
$this->errstr = mysql_error();
if ($this->errno)
{
$this->error("Cannot execute query: $query_str");
return false;
}
$this->num_rows = mysql_affected_rows($this->conn_id);
$this->insert_id = mysql_insert_id($this->conn_id);
return $this->result_id;
}
function fetch_row ()
{
$this->row = mysql_fetch_assoc($this->result_id);
$this->errno = mysql_errno();
$this->errstr = mysql_error();
if ($this->errno)
{
$this->error("Error fetching row");
return false;
}
if (is_array($this->row))
{
return $this->row;
}
$this->free_result();
return false;
}
function fetch_multiple_rows ()
{
while ($this->temp_row = mysql_fetch_assoc($this->result_id))
{
$this->row_multiple[] = $this->temp_row;
}
$this->errno = mysql_errno();
$this->errstr = mysql_error();
if ($this->errno)
{
$this->error("Error fetching row");
return false;
}
if (is_array($this->row))
{
return $this->row_multiple;
}
$this->free_result();
return false;
}
function free_result ()
{
if ($this->result_id)
{
mysql_free_result($this->result_id);
}
$this->result_id = 0;
return true;
}
function sql_quote ($str)
{
if (!isset($str))
{
return NULL;
}
$func = function_exists ("mysql_escape_string")
? "mysql_escape_string"
: "addslashes";
return ("'".$func($str)."'");
}
function num_rows()
{
return $this->num_rows;
}
function insertID()
{
return $this->insert_id;
}
}
//The class and parent that stores the data..
class Session
{
function getVar($varName)
{
return $this->$varName;
}
}
class Site extends Session
{
var $siteID;
var $langID;
var $language;
var $langCode;
var $langNameLocal;
var $siteName;
var $siteURL;
var $dbDirect;
var $siteDirect;
var $sitePath;
var $cmsPath;
var $useUTF;
var $charset;
function Site($arguments=false)
{
if ($arguments)
{
foreach ($arguments as $key=>$value)
{
$this->$key = $value;
}
}
}
function getCharset()
{
if ($this->useUTF == "y")
{
return "utf-8";
}
else
{
return $this->charset;
}
}
}
// The code that sets up the classes
unset ($_SESSION['siteInfo']);
unset ($_SESSION['moduleInfo']);
$conn = new DB;
$conn->issue_query("SELECT name, url, dbDirect, siteDirect FROM {$cfg['dbPrefix']}site WHERE siteID = '{$_GET['siteID']}'");
$siteSet = $conn->fetch_row();
$conn->issue_query("SELECT language, langCode, langNameLocal, charset FROM {$cfg['dbPrefix']}language WHERE langID = '{$_GET['langID']}'");
$langSet = $conn->fetch_row();
$conn->issue_query("SELECT useUTF FROM {$cfg['dbPrefix']}site_language WHERE siteID = '{$_GET['siteID']}' AND langID = '{$_GET['langID']}'");
$charsetChoice = $conn->fetch_row();
$_SESSION['siteInfo'] = new Site(array(
'siteID' => $_GET['siteID'],
'langID' => $_GET['langID'],
'language' => $langSet['language'],
'langCode' => $langSet['langCode'],
'langNameLocal' => $langSet['langNameLocal'],
'siteName' => $siteSet['name'],
'siteURL' => $siteSet['url'],
'dbDirect' => $siteSet['dbDirect'],
'siteDirect' => $siteSet['siteDirect'],
'charset' => $langSet['charset'],
'useUTF' => $charsetChoice['useUTF']
));
// and finally how it is displayed and where the ?? comes from:
echo $_SESSION['siteInfo']->getVar('language'); ?> / <?php echo $_SESSION['siteInfo']->getVar('langNameLocal'); ?>
It is not the most optimised code in the world but I will worry about that after I can get it to work.
Is there a single obvious stage that I am missing that would stop retrieved string data in utf-8 when displayed through PHP on a page set as utf-8 becoming gibberish?