ZF-1541: Character set option for Db adapters

Description

Need a possibility to set character encoding for Mysqli / Pdo_Mysql adapter (in adapter's constructor) ( sub-classing adapter makes impossible to use Zend_Db::factory() method )

and then query like (for utf8): 'SET NAMES utf8' on every connect()


h3. Possible Solutions as recorded from comments below

When the 'charset' option is available to the Zend_Db::Factory(), do the following in the adapters _connect method: ||Adapter||Proposed Solution|| |Mysqli|use mysqli_set_charset| |Oracle|use the charset option for oci_connect| |Db2|no solution| |Pdo_Ibm_Db2|no solution| |Pdo_Ibm_Ids|no solution| |Pdo_Mssql|no solution,depends on server configuration| |Pdo_Mysql|use PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES "utf8''| |Pdo_Oci|include charset in DSN| |Pdo_Pgsql|use SET NAMES| |Pdo_Sqlite|not needed|

Comments

This is also relevant for OCI adapter and others, but the implementation varies.

mikespook writes:

I used utf8 for my charset with Oracle.

But, there are no item can set the charset in the param of the Zend_Db::factory(). And you konw, MS Windows use GB18030 for the charset in China. So when I send a SQL to the Oracle with charset utf8, I got a error.

I make this patch for we can set charset to the Oracle.


Index: Oci.php
===================================================================
--- Oci.php    (revision 267)
+++ Oci.php    (working copy) 
@@ -67,7 +67,12 @@
             $tns .= '/';
         }
         $tns .= $dsn['dbname'];
-
+   
+        if (isset($dsn['charset']))
+        {
+            $tns .= ';charset=' . $dsn['charset']; 
+        }
+   
         return $this->_pdoType . ':' . $tns;
     }

So, we could use:


<?php
require_once 'Zend/Db.php';
$db = Zend_Db::factory('Pdo_Oci', array(
    'host'     => '127.0.0.1',
    'username' => 'webuser',
    'password' => 'xxxxxxxx',
    'dbname'   => 'test',
    'charset'  => 'utf8'
));

In the Zend_Db_Adapter_Oracle we have

        if (isset($this->_config['dbname'])) {
            $this->_connection = @oci_connect(
                $this->_config['username'],
                $this->_config['password'],
                $this->_config['dbname']);
        } else {
            $this->_connection = oci_connect(
                $this->_config['username'],
                $this->_config['password']);
        }

shouldn't it be something like

        $charset = (isset($this->_config['charset']))
            ? $this->_config['charset']
            : null;

        $dbname = (isset($this->_config['dbname']))
            ? $this->_config['dbname']
            : null;

        $this->_connection = oci_connect(
            $this->_config['username'],
            $this->_config['password'],
            $dbname,
            $charset
        );

Please categorize/fix as needed.

Resetting 'fix version priority' and 'fix version' to be re-evaluated for next release.

Here is a patch for it to work with Zend_Db_Adapter_Oracle

 Index: Zend/Db/Adapter/Oracle.php
===================================================================
--- Zend/Db/Adapter/Oracle.php  (revision 9107)
+++ Zend/Db/Adapter/Oracle.php  (working copy)
@@ -102,17 +102,21 @@
             throw new Zend_Db_Adapter_Oracle_Exception('The OCI8 extension is required for this adapter but the extension is not loaded');
         }
 
-        if (isset($this->_config['dbname'])) {
-            $this->_connection = @oci_connect(
-                $this->_config['username'],
-                $this->_config['password'],
-                $this->_config['dbname']);
-        } else {
-            $this->_connection = oci_connect(
-                $this->_config['username'],
-                $this->_config['password']);
-        }
+        $charset = (isset($this->_config['charset']))
+            ? $this->_config['charset']
+            : null;
 
+        $dbname = (isset($this->_config['dbname']))
+            ? $this->_config['dbname']
+            : null;
+
+        $this->_connection = oci_connect(
+            $this->_config['username'],
+            $this->_config['password'],
+            $dbname,
+            $charset
+        );
+
         // check the connection
         if (!$this->_connection) {
             /**

Here are the patches for Mysqli:

Index: Zend/Db/Adapter/Mysqli.php
===================================================================
--- Mysqli.php  (revision 9527)
+++ Mysqli.php  (working copy)
@@ -301,6 +301,9 @@
             require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
             throw new Zend_Db_Adapter_Mysqli_Exception(mysqli_connect_error());
         }
+        if (array_key_exists('charset', $this->_config)) {
+            $this->_connection->query('SET NAMES \'' . $this->_config['charset'] . '\'');
+        }
     }
 
     /**

and for Pdo_Mysl

Index: Zend/Db/Adapter/Pdo/Abstract.php
===================================================================
--- Abstract.php    (revision 9527)
+++ Abstract.php    (working copy)
@@ -121,7 +121,11 @@
 
             // always use exceptions.
             $this->_connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-
+            
+            // if PDO type is MySQL, and $this->_config['charset'] exists, set names
+            if ( ('mysql' == $this->_pdoType) && array_key_exists('charset', $this->_config) ) {
+                $this->_connection->query('SET NAMES \'' . $this->_config['charset'] . '\'');
+            }
         } catch (PDOException $e) {
             /**
              * @see Zend_Db_Adapter_Exception

Since the PDO database adapters use base (abstract) method for creating a db connection I've added a check ('mysql' == $this->_pdoType) so the 'set names' query is issued only for PDO_Mysql adapter (I don't know how other databases handle this issue).

I really hope this issue will be fixed in the next minor release, it has been long overdue.

If there is something else I can do to help, please let me know.

Please disregard the patch for Pdo_Mysql, haven't really worked with Pdo till now. "SET NAMES" do work for Pdo_Mysql adapter!!! You just have to pass it as a driver option...

The correct way to use it is:

<?php

$db = new Zend_Db_Adapter_Pdo_Mysql(array(
    'host'     => 'your_host_or_ip',
    'username' => 'your_myslq_username0,
    'password' => 'mysql_pass',
    'dbname'   => 'your_db_name',
    'driver_options'  => array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'utf8\'')
));

On Pdo_Mysql I've always just used $db->query('SET NAMES UTF8'); without any problems. I tested it to make sure it works correctly.

Ofcourse it does. But if you send a query you are forcing you app to connect to the database. There are times that you don't want to connect to the database if it isn't really needed, that's what lazy loading is for.

This way, you can use Pdo_Mysql, utf8, and still have lazy loading of the db.

But this issue is still unresolved because in Mysqli you do have to send "SET NAMES 'utf8'" after connecting to the database.

I would love to see this implemented. At the moment managing lazy loading is either something you get creative about, or with a light application simply ignore. Getting it internalised would make life that bit easier.

any way .. could this at least be fixed in the Oracle Adapter since oci_connect supports charset ? :D

All right, this item officially has twice as many votes as the next popular item. If we don't implement it for 1.6 we risk user revolt. :0 Simon, is this something that you'll be able to do. If not, I'll troll for help from the rest of the community.

For mysqli the correct way is to use mysqli::set_charset ( see http://php.net/manual/en/… ).

Here's the patch for it:


Index: library/Zend/Db/Adapter/Mysqli.php
===================================================================
--- library/Zend/Db/Adapter/Mysqli.php  (revision 10900)
+++ library/Zend/Db/Adapter/Mysqli.php  (working copy)
@@ -313,6 +313,16 @@
             require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
             throw new Zend_Db_Adapter_Mysqli_Exception(mysqli_connect_error());
         }
+        
+        if (array_key_exists('charset', $this->_config)) {
+           if(!$this->_connection->set_charset($this->_config['charset'])) {
+                /**
+                * @see Zend_Db_Adapter_Mysqli_Exception
+                */
+                require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
+                throw new Zend_Db_Adapter_Mysqli_Exception('could not set charset');
+            }
+        }
     }
 
     /**

The charset issue is already resolved for Pdo_Oci as far as I see ( SVN trunk ):


    /**
     * Creates a PDO DSN for the adapter from $this->_config settings.
     *
     * @return string
     */
    protected function _dsn()
    {
        // baseline of DSN parts
        $dsn = $this->_config;

        ...

        if (isset($dsn['charset']))
        {
            $tns .= ';charset=' . $dsn['charset'];
        }

        return $this->_pdoType . ':' . $tns;
    }

Here's the resulting patch. It implements charset support for Mysql, Oracle, Pdo_Mysql, Pdo_Oracle and Pdo_Pgsql, as well as unit tests for these.


Index: tests/Zend/Db/Adapter/TestCommon.php
===================================================================
--- tests/Zend/Db/Adapter/TestCommon.php    (revision 10902)
+++ tests/Zend/Db/Adapter/TestCommon.php    (working copy)
@@ -45,6 +45,36 @@
  */
 abstract class Zend_Db_Adapter_TestCommon extends Zend_Db_TestSetup
 {
+   /**
+    * Test set charset option for adapter
+    * CASE: utf8
+    */
+   public function testAdapterCharset()
+   {
+       $params = $this->_util->getParams();
+       
+       $params['charset'] = 'utf8';
+       
+       $db = Zend_Db::factory($this->getDriver(), $params);
+        $db->getConnection();
+   }
+   
+   /**
+    * Test set charset option for adapter
+    * CASE: bad charset
+    */
+   public function testAdapterCharsetBad()
+   {
+       $params = $this->_util->getParams();
+       
+       $params['charset'] = 'blahblahblah';
+       
+       $this->setExpectedException('Zend_Db_Adapter_Exception');
+
+       $db = Zend_Db::factory($this->getDriver(), $params);
+        $db->getConnection();
+   }
+   
     /**
      * Test AUTO_QUOTE_IDENTIFIERS option
      * Case: Zend_Db::AUTO_QUOTE_IDENTIFIERS = true
@@ -55,6 +85,7 @@
         $params = new Zend_Config($this->_util->getParams());
 
         $db = Zend_Db::factory($this->getDriver(), $params);
+        
         $db->getConnection();
     }
 
Index: tests/Zend/Db/Adapter/Pdo/SqliteTest.php
===================================================================
--- tests/Zend/Db/Adapter/Pdo/SqliteTest.php    (revision 10902)
+++ tests/Zend/Db/Adapter/Pdo/SqliteTest.php    (working copy)
@@ -48,6 +48,16 @@
         'INTEGER'            => Zend_Db::BIGINT_TYPE,
         'REAL'               => Zend_Db::FLOAT_TYPE
     );
+    
+    public function testAdapterCharset()
+   {
+        $this->markTestSkipped($this->getDriver() . ' does not support charset');
+    }
+    
+    public function testAdapterCharsetBad()
+   {
+        $this->markTestSkipped($this->getDriver() . ' does not support charset');
+    }
 
     /**
      * Test AUTO_QUOTE_IDENTIFIERS option
Index: tests/Zend/Db/Adapter/OracleTest.php
===================================================================
--- tests/Zend/Db/Adapter/OracleTest.php    (revision 10904)
+++ tests/Zend/Db/Adapter/OracleTest.php    (working copy)
@@ -43,6 +43,41 @@
         'NUMBER'             => Zend_Db::FLOAT_TYPE,
     );
 
+    /**
+     * Test set charset option for adapter
+     * CASE: bad charset
+     */
+    public function testAdapterCharsetBad()
+    {
+        @trigger_error('clearing error buffer', E_USER_NOTICE);
+        
+        $params = $this->_util->getParams();
+        
+        $params['charset'] = 'blahblahblah';
+
+        $db = Zend_Db::factory($this->getDriver(), $params);
+        $db->getConnection();
+        
+        
+        // Since oci_connect throws a warning on a bad charset, we have no choice but to 
+        // use error_get_last()  to detect this warning. 
+        // 
+        // Due to the fact that error_get_last() cannot be reset, we also have to use
+        // @trigger_error() to "force" the reset of the last error message\
+        // 
+        // This is also the reason that this piece of code was not included in Zend_Db_Adapter_Oracle
+        // in order to throw an Exception when seting a bad charset
+        $last_error = error_get_last();
+        
+        if( is_array($last_error) && 
+            $last_error['type'] == 2 && 
+            strpos($last_error['message'], 'Invalid character set name') !== false ) {
+            
+        } else {
+            $this->fail( 'Invalid character set name' );
+        }
+    }
+    
     public function testAdapterDescribeTablePrimaryAuto()
     {
         $this->markTestSkipped('Oracle does not support auto-increment');
Index: library/Zend/Db/Adapter/Oracle.php
===================================================================
--- library/Zend/Db/Adapter/Oracle.php  (revision 10902)
+++ library/Zend/Db/Adapter/Oracle.php  (working copy)
@@ -114,17 +114,21 @@
             throw new Zend_Db_Adapter_Oracle_Exception('The OCI8 extension is required for this adapter but the extension is not loaded');
         }
 
-        if (isset($this->_config['dbname'])) {
-            $this->_connection = @oci_connect(
-                $this->_config['username'],
-                $this->_config['password'],
-                $this->_config['dbname']);
-        } else {
-            $this->_connection = oci_connect(
-                $this->_config['username'],
-                $this->_config['password']);
-        }
+        $charset = (isset($this->_config['charset']))
+            ? $this->_config['charset']
+            : null;
+ 
+        $dbname = (isset($this->_config['dbname']))
+            ? $this->_config['dbname']
+            : null;
 
+        $this->_connection = oci_connect(
+            $this->_config['username'],
+            $this->_config['password'],
+            $dbname,
+            $charset
+        );
+        
         // check the connection
         if (!$this->_connection) {
             /**
Index: library/Zend/Db/Adapter/Pdo/Abstract.php
===================================================================
--- library/Zend/Db/Adapter/Pdo/Abstract.php    (revision 10902)
+++ library/Zend/Db/Adapter/Pdo/Abstract.php    (working copy)
@@ -72,6 +72,7 @@
         unset($dsn['username']);
         unset($dsn['password']);
         unset($dsn['options']);
+        unset($dsn['charset']);
         unset($dsn['driver_options']);
 
         // use all remaining parts in the DSN
@@ -82,6 +83,12 @@
         return $this->_pdoType . ':' . implode(';', $dsn);
     }
 
+    protected function _setCharset( )
+    {
+        if ( array_key_exists('charset', $this->_config) ) {
+            $this->_connection->query('SET NAMES \'' . $this->_config['charset'] . '\'');
+        }
+    }
     /**
      * Creates a PDO object and connects to the database.
      *
@@ -134,6 +141,11 @@
 
             // always use exceptions.
             $this->_connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+            
+            if ( ('mysql' == $this->_pdoType) || ('pgsql' == $this->_pdoType))
+            {
+                $this->_setCharset();
+            }
 
         } catch (PDOException $e) {
             /**
Index: library/Zend/Db/Adapter/Mysqli.php
===================================================================
--- library/Zend/Db/Adapter/Mysqli.php  (revision 10902)
+++ library/Zend/Db/Adapter/Mysqli.php  (working copy)
@@ -313,6 +313,16 @@
             require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
             throw new Zend_Db_Adapter_Mysqli_Exception(mysqli_connect_error());
         }
+        
+        if (array_key_exists('charset', $this->_config)) {
+           if(!$this->_connection->set_charset($this->_config['charset'])) {
+                /**
+                * @see Zend_Db_Adapter_Mysqli_Exception
+                */
+                require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
+                throw new Zend_Db_Adapter_Mysqli_Exception('could not set charset');
+            }
+        }
     }
 
     /**

That's great to provide those patches, but I think the interface to supply character set to each respective brand of database is only half the problem.

The other part of the problem is that a given character set may be known by a different name in each database. For example, MySQL uses 'utf8' where Oracle uses 'AL32UTF8'. Oracle even has a charset called 'utf8' but it's different. See http://decipherinfosys.wordpress.com/2007/01/…

This makes it hard to create a set of config parameters that can be used orthogonally for several brands of database. You'd have to know the different names in each database for any given charset you want to use.

How would I recommend solving this? The {{Zend_Db_Adapter}} interface currently supports a config parameter 'driver_options', which is an associative array used for options that are specific to each brand of database. I would suggest that {{Zend_Db_Adapter}} use 'driver_options'->'charset' for the name of the charset as it is known by the brand of database.


$db = Zend_Db::factory('oracle', array('driver_options'=>array('charset'=>'AL32UTF8')));

Then you can implement a charset abstraction layer. Decide on a set of core charsets that will be supported by {{Zend_Db}}, and define these as {{const}} strings.


class Zend_Db
{
  const CHARSET_UTF8 = utf8;
  . . .
}

Then in each {{Zend_Db_Adapter}} class, create a protected associative array mapping the abstract charset names to native charset names. If the database doesn't support one, or if you simply don't know what it it's called, leave it out of the mapping array.


class Zend_Db_Adapter_Oracle extends Zend_Db_Adapter_Abstract
{
  protected $_charsetMap = array(
    Zend_Db::CHARSET_UTF8 => 'AL32UTF8'
  );
  . . .
}

Then if I pass a config parameter 'charset' => 'utf8' to my Db Adapter factory, it'll perform the mapping and add the entry to the driver_options, where it will get applied using code similar to your patch.


$db = Zend_Db::factory('mysqli', array('charset'=>Zend_Db::CHARSET_UTF8));

Developers can still use uncommon charsets that are not in the set of core abstract charsets supported by Zend_Db's mapping table. They just need to specify it in the 'driver_options' array by its native name, instead of in the 'charset' parameter.


$db = Zend_Db::factory('oracle', array('driver_options'=>array('charset'=>'BN8BSCII'))); // Bangladesh BSCII charset

You don't necessarily have to fill out the full set of core charsets in every adapter class. But you do need to throw an exception if I pass an abstract charset name that isn't supported in the adapter I chose.


$db = Zend_Db::factory('pdo_sqlite', array('charset' => Zend_Db::CHARSET_LATIN1));
// may throw exception

Since this has been sitting open for so long, I went ahead and took a stab at making a patch. So here it is, against current SVN r11422. Adds charset support to Mysqli, PDO_Mysql, and PDO_Pgsql adapters. A new optional parameter 'charset' is passed to the adapter.

Whoops. And then there was JIRA not showing me the comment discussion. I feel extremely embarrassed and am going to crawl into a hole now. :)

Hi,

do not forget Zend_Db_Adapter_Oracle : need charset support too !!!

it's ok in PDO_OCI, but PDO_OCI is still unstable and chrashes very often (try use clob :( u'll see ).

current 1.7.0 code


protected function _connect()
{
...
        if (isset($this->_config['dbname'])) {
            $this->_connection = @oci_connect(
                $this->_config['username'],
                $this->_config['password'],
                $this->_config['dbname']);
        } else {
            $this->_connection = oci_connect(
                $this->_config['username'],
                $this->_config['password']);
        }
...

could be


protected function _connect()
{
...
            $this->_connection = @oci_connect(
                $this->_config['username'],
                $this->_config['password'],
                isset($this->_config['dbname'])?$this->_config['dbname']:null,
                isset($this->_config['charset'])?$this->_config['charset']:null,
               );
...

best regards

I aggree .. dont forget :D

This issue has gone unaddressed for too long. I'm re-assigning to Ralph for re-evaluation and categorization.

A quick solution for charset with Pdo_Mysql:


require_once 'Zend/Db/Adapter/Pdo/Mysql.php';

class Zend_Db_Adapter_Pdo_Mysql_Charset extends Zend_Db_Adapter_Pdo_Mysql
{
    protected function _connect(){
        if ($this->_connection) {
            return;
        }
        parent::_connect();
        if(array_key_exists('charset',$this->_config) && $this->_config['charset']){
            global $logger;
            $logger->debug('Setting db charset to '.$this->_config['charset']);
            $this->_connection->exec('SET NAMES '.$this->_config['charset']);
        }
    }
}

Then use something like this:


$db = Zend_Db::factory(Pdo_Mysql_Charset', array(
        'host'     => '.....', 
        'username' => '....' ,
        'password' => '....',
        'dbname'   => '....',
        'charset'  => 'utf8',
    ));

After cleanup:


require_once 'Zend/Db/Adapter/Pdo/Mysql.php';

class Zend_Db_Adapter_Pdo_Mysql_Charset extends Zend_Db_Adapter_Pdo_Mysql
{
    protected function _connect(){
        if ($this->_connection) {
            return;
        }
        parent::_connect();
        if(array_key_exists('charset',$this->_config) && !empty($this->_config['charset'])){
            $this->_connection->exec('SET NAMES '.$this->_config['charset']);
        }
    }
}

Usage of SET NAMES for setting the charset of the connection, the result and the client for MySQL is WRONG, WRONG, WRONG! Opens the door for SQL Injections. SET NAMES exists only for the sake of the mysql command line client where there is no way to set the connection's character set when you connect, thus SET NAMES is used. mysql's API, libmysql, has means of setting the character set, for good reasons. Using SET NAMES can lead to security problems with specific character sets...Think - SQL Injection. Either use: http://bg.php.net/manual/en/… or mysqli_options() on a handle returned from mysqli_init() and this should be done before mysql_real_connect()

$mysql = mysqli_init(); mysqli_options($mysql, 7, "utf8"); //sorry for the magic number but ext/mysqli doesn't register the value of MYSQL_SET_CHARSET_NAME // coming from mysql.h as constant. In mysql.h it is 7 and won't change for the time being. mysqli_real_connect($mysql, ...);

Andrey

Andrey did not provide any information about the problem witht this type of sql injections and while it is hard to find anything on that i provide a source: http://ilia.ws/archives/…

I needed to have UTF-8 encoding on MySQLi driver, here's a quick patch that I'm using to solve this problem. I would hope every implementation would support this option.

class Zend_Db_Adapter_Mysqli extends Zend_Db_Adapter_Abstract
{

    ...

    protected function _connect()
    {

        ...

        // line 342 using Zend 1.7.5
        if (isset($this->_config['charset'])) {
            mysqli_set_charset($this->_connection, $this->_config['charset']);
        }
    }

    ...

}

Sorry if I'm repeating code.

Well, I've re-read the entire thread, and Sorin Alin Stoiana's solution (13/Aug/08 05:49 AM) works great ! Why hasn't it been released with Zend 1.7.5 last feb 16th ?

Collecting the proposed solutions inside the description of the issue.

@Ralph: will Db2 adapter hold this issue or it is to be fixed for 1.8 release?

bleah... can`t edit my comment. I mean will lack of solution for Db2 adapters prevent this issue from fixing for other adapters? (please remove the above comment)

Bill: I like the idea of supporting charsets by using the constants. However, I feel like that's a different issue than this one. The focus of this issue should be on supporting setting the charset in the first place. Adding a layer of abstraction on top of that is pretty much a standalone task, even though its implementation would probably rework a part of the code that's being updated for the charset support. Seeing as a lot of people need this feature it might not be worth waiting for a full implementation of the charset abstraction proposal.

Seeing as I need support for this in the Oci8 adapter, I'm going to write a patch for that today. If there's no solution for Db2 (Db2 experts, please comment!) I would like to suggest implementing the suggestions from the table to get this issue resolved.

@Jurrien FYI, the patch I submitted here [#action_23500 ] also provides support for Oci8

This issue has been resolved for the Pdo_Mysql, Pdo_Pgsql, Mysqli and Oracle drivers in revision 14691 and 14692. At the moment I can only verify that this works on Oracle. Before closing this issue I would like to confirm there are no issues with the patch. Would everybody be so kind to verify that the patch works for Pdo_Mysql, Pdo_Pgsql and Mysqli? You can specify the charset in the adapter config using the 'charset' key.

A more complete patch is [here|#action23500] . It implements charset support for Mysql, Oracle, Pdo_Mysql, Pdo_Oracle and Pdo_Pgsql, as well as unit tests for these. It has been tested with Oracle XE, Oracle Real Application Cluster, Mysql, and Pgsql.

Why was this patch disregarded? From what I read in the Contributor's Guide, all changes must come with unit tests.

While I approve the kind of swift action Jurrien took in solving the issue at hand, I believe we shouldn't compromise when it comes to providing fixes.

A test was available already, but was marked as skipped. It's enabled in revision 14952 and successfully passes on Mysqli, Pdo_Mysql, Pdo_Oci and Oracle. Still looking for someone to test on Pdo_Pgsql.

I've installed Postgres for myself and identified and fixed one last issue there. As of revision 14953 I can successfully run the test on Mysql, Pdo_Mysql, Oci8 and Pdo_Pgsql. Pdo_Oci already supported the charset option. Closing issue as "fixed". :)

I'm working with Zend Framework Version 1.9.6 here and cannot confirm that this issue has been resolved (using pdo_mysql rev 16942). My html output is set to utf-8, the database runs on utf-8 as well (utf8_general_ci) but all special chars are messed up.

Yanick Rochon's hotfix worked for me though. (http://framework.zend.com/issues/browse/…)

what version on PHP? there was a regression in PHP 5.3.0 that would affect this from working.

-ralph

I'm afraid it's 5.3.0... :(

PHP 5.3.0 (cli) (built: Jul 19 2009 00:34:29) Copyright (c) 1997-2009 The PHP Group Zend Engine v2.3.0, Copyright (c) 1998-2009 Zend Technologies

In fact it's the apache/php combo that came with MacOS Snow Leopard (MySQL installed with MacPorts).

The problem is fixed with PHP 5.3.1.