Skip to content

Cannot set driver options in Nette\Database when using NetteExtension #700

@spaze

Description

@spaze

Nette\Database\Connection uses options in constructor for both the PDO and the driver:

    public function __construct($dsn, $username = NULL, $password  = NULL, array $options = NULL, $driverClass = NULL)
    {
        parent::__construct($this->dsn = $dsn, $username, $password, $options);
        // ...
        $this->driver = new $driverClass($this, (array) $options);
        // ...
    }

this is wrong because NetteExtension::loadConfiguration() tries to convert the options keys to constants (because of the PDO::foobar constants?):

foreach ((array) $info['options'] as $key => $value) {
    unset($info['options'][$key]);
    $info['options'][constant($key)] = $value;
}

and when you want to specify e.g. sqlmode key for MySQL in the config it tries to use the sqlmode constant which does not exist, obviously. MySQL driver constructor uses these options, though:

    /**
     * Driver options:
     *   - charset => character encoding to set (default is utf8)
     *   - sqlmode => see http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html
     */
    public function __construct(Nette\Database\Connection $connection, array $options)
    {
        $this->connection = $connection;
        $charset = isset($options['charset']) ? $options['charset'] : 'utf8';
        if ($charset) {
            $connection->exec("SET NAMES '$charset'");
        }
        if (isset($options['sqlmode'])) {
            $connection->exec("SET sql_mode='$options[sqlmode]'");
        }
        $connection->exec("SET time_zone='" . date('P') . "'");
    }

My idea is to introduce separate driver options from PDO options and introduce driverOptions config key, something like in this patch against Nette 2.0.3-PHP5.3:

Index: Nette/Config/Extensions/NetteExtension.php
===================================================================
--- Nette/Config/Extensions/NetteExtension.php  (revision 4)
+++ Nette/Config/Extensions/NetteExtension.php  (working copy)
@@ -72,6 +72,7 @@
        'user' => NULL,
        'password' => NULL,
        'options' => NULL,
+       'driverOptions' => NULL,
        'debugger' => TRUE,
        'explain' => TRUE,
        'reflection' => 'Nette\Database\Reflection\DiscoveredReflection',
@@ -251,7 +252,7 @@
            }

            $connection = $container->addDefinition($this->prefix("database.$name"))
-               ->setClass('Nette\Database\Connection', array($info['dsn'], $info['user'], $info['password'], $info['options']))
+               ->setClass('Nette\Database\Connection', array($info['dsn'], $info['user'], $info['password'], $info['options'], NULL, $info['driverOptions']))
                ->setAutowired($info['autowired'])
                ->addSetup('setCacheStorage')
                ->addSetup('Nette\Diagnostics\Debugger::$blueScreen->addPanel(?)', array(
Index: Nette/Database/Connection.php
===================================================================
--- Nette/Database/Connection.php   (revision 4)
+++ Nette/Database/Connection.php   (working copy)
@@ -48,14 +48,14 @@



-   public function __construct($dsn, $username = NULL, $password  = NULL, array $options = NULL, $driverClass = NULL)
+   public function __construct($dsn, $username = NULL, $password  = NULL, array $options = NULL, $driverClass = NULL, array $driverOptions = NULL)
    {
        parent::__construct($this->dsn = $dsn, $username, $password, $options);
        $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('Nette\Database\Statement', array($this)));

        $driverClass = $driverClass ?: 'Nette\Database\Drivers\\' . ucfirst(str_replace('sql', 'Sql', $this->getAttribute(PDO::ATTR_DRIVER_NAME))) . 'Driver';
-       $this->driver = new $driverClass($this, (array) $options);
+       $this->driver = new $driverClass($this, (array) $driverOptions);
        $this->preprocessor = new SqlPreprocessor($this);
    }

Any ideas, thoughts? (Sorry if this is not the right way to report bugs)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions