function Connection::open

Same name in this branch
  1. 11.x core/modules/sqlite/src/Driver/Database/sqlite/Connection.php \Drupal\sqlite\Driver\Database\sqlite\Connection::open()
  2. 11.x core/modules/pgsql/src/Driver/Database/pgsql/Connection.php \Drupal\pgsql\Driver\Database\pgsql\Connection::open()
  3. 11.x core/lib/Drupal/Core/Database/Connection.php \Drupal\Core\Database\Connection::open()
Same name in other branches
  1. 9 core/modules/sqlite/src/Driver/Database/sqlite/Connection.php \Drupal\sqlite\Driver\Database\sqlite\Connection::open()
  2. 9 core/modules/mysql/src/Driver/Database/mysql/Connection.php \Drupal\mysql\Driver\Database\mysql\Connection::open()
  3. 9 core/modules/pgsql/src/Driver/Database/pgsql/Connection.php \Drupal\pgsql\Driver\Database\pgsql\Connection::open()
  4. 9 core/lib/Drupal/Core/Database/Connection.php \Drupal\Core\Database\Connection::open()
  5. 8.9.x core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php \Drupal\Core\Database\Driver\sqlite\Connection::open()
  6. 8.9.x core/lib/Drupal/Core/Database/Driver/mysql/Connection.php \Drupal\Core\Database\Driver\mysql\Connection::open()
  7. 8.9.x core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php \Drupal\Core\Database\Driver\pgsql\Connection::open()
  8. 8.9.x core/lib/Drupal/Core/Database/Connection.php \Drupal\Core\Database\Connection::open()
  9. 10 core/modules/sqlite/src/Driver/Database/sqlite/Connection.php \Drupal\sqlite\Driver\Database\sqlite\Connection::open()
  10. 10 core/modules/mysql/src/Driver/Database/mysql/Connection.php \Drupal\mysql\Driver\Database\mysql\Connection::open()
  11. 10 core/modules/pgsql/src/Driver/Database/pgsql/Connection.php \Drupal\pgsql\Driver\Database\pgsql\Connection::open()
  12. 10 core/lib/Drupal/Core/Database/Connection.php \Drupal\Core\Database\Connection::open()

Overrides Connection::open

File

core/modules/mysql/src/Driver/Database/mysql/Connection.php, line 100

Class

Connection
MySQL implementation of \Drupal\Core\Database\Connection.

Namespace

Drupal\mysql\Driver\Database\mysql

Code

public static function open(array &$connection_options = []) {
    // The DSN should use either a socket or a host/port.
    if (isset($connection_options['unix_socket'])) {
        $dsn = 'mysql:unix_socket=' . $connection_options['unix_socket'];
    }
    else {
        // Default to TCP connection on port 3306.
        $dsn = 'mysql:host=' . $connection_options['host'] . ';port=' . (empty($connection_options['port']) ? 3306 : $connection_options['port']);
    }
    // Character set is added to dsn to ensure PDO uses the proper character
    // set when escaping. This has security implications. See
    // https://www.drupal.org/node/1201452 for further discussion.
    $dsn .= ';charset=utf8mb4';
    if (!empty($connection_options['database'])) {
        $dsn .= ';dbname=' . $connection_options['database'];
    }
    // Allow PDO options to be overridden.
    $connection_options += [
        'pdo' => [],
    ];
    $connection_options['pdo'] += [
        \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
        // So we don't have to mess around with cursors and unbuffered queries by default.
\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => TRUE,
        // Make sure MySQL returns all matched rows on update queries including
        // rows that actually didn't have to be updated because the values didn't
        // change. This matches common behavior among other database systems.
\PDO::MYSQL_ATTR_FOUND_ROWS => TRUE,
        // Because MySQL's prepared statements skip the query cache, because it's dumb.
\PDO::ATTR_EMULATE_PREPARES => TRUE,
        // Limit SQL to a single statement like mysqli.
\PDO::MYSQL_ATTR_MULTI_STATEMENTS => FALSE,
        // Convert numeric values to strings when fetching. In PHP 8.1,
        // \PDO::ATTR_EMULATE_PREPARES now behaves the same way as non emulated
        // prepares and returns integers. See https://externals.io/message/113294
        // for further discussion.
\PDO::ATTR_STRINGIFY_FETCHES => TRUE,
    ];
    try {
        $pdo = new \PDO($dsn, $connection_options['username'], $connection_options['password'], $connection_options['pdo']);
    } catch (\PDOException $e) {
        switch ($e->getCode()) {
            case static::CONNECTION_REFUSED:
                if (isset($connection_options['unix_socket'])) {
                    // Show message for socket connection via 'unix_socket' option.
                    $message = 'Drupal is configured to connect to the database server via a socket, but the socket file could not be found.';
                    $message .= ' This message normally means that there is no MySQL server running on the system or that you are using an incorrect Unix socket file name when trying to connect to the server.';
                    throw new DatabaseConnectionRefusedException($e->getMessage() . ' [Tip: ' . $message . '] ', $e->getCode(), $e);
                }
                if (isset($connection_options['host']) && in_array(strtolower($connection_options['host']), [
                    '',
                    'localhost',
                ], TRUE)) {
                    // Show message for socket connection via 'host' option.
                    $message = 'Drupal was attempting to connect to the database server via a socket, but the socket file could not be found.';
                    $message .= ' A Unix socket file is used if you do not specify a host name or if you specify the special host name localhost.';
                    $message .= ' To connect via TCP/IP use an IP address (127.0.0.1 for IPv4) instead of "localhost".';
                    $message .= ' This message normally means that there is no MySQL server running on the system or that you are using an incorrect Unix socket file name when trying to connect to the server.';
                    throw new DatabaseConnectionRefusedException($e->getMessage() . ' [Tip: ' . $message . '] ', $e->getCode(), $e);
                }
                // Show message for TCP/IP connection.
                $message = 'This message normally means that there is no MySQL server running on the system or that you are using an incorrect host name or port number when trying to connect to the server.';
                $message .= ' You should also check that the TCP/IP port you are using has not been blocked by a firewall or port blocking service.';
                throw new DatabaseConnectionRefusedException($e->getMessage() . ' [Tip: ' . $message . '] ', $e->getCode(), $e);
            case static::DATABASE_NOT_FOUND:
                throw new DatabaseNotFoundException($e->getMessage(), $e->getCode(), $e);
            case static::ACCESS_DENIED:
                throw new DatabaseAccessDeniedException($e->getMessage(), $e->getCode(), $e);
            default:
                throw $e;
        }
    }
    // Force MySQL to use the UTF-8 character set. Also set the collation, if a
    // certain one has been set; otherwise, MySQL defaults to
    // 'utf8mb4_general_ci' (MySQL 5) or 'utf8mb4_0900_ai_ci' (MySQL 8) for
    // utf8mb4.
    if (!empty($connection_options['collation'])) {
        $pdo->exec('SET NAMES utf8mb4 COLLATE ' . $connection_options['collation']);
    }
    else {
        $pdo->exec('SET NAMES utf8mb4');
    }
    // Set MySQL init_commands if not already defined.  Default Drupal's MySQL
    // behavior to conform more closely to SQL standards.  This allows Drupal
    // to run almost seamlessly on many different kinds of database systems.
    // These settings force MySQL to behave the same as postgresql, or sqlite
    // in regards to syntax interpretation and invalid data handling.  See
    // https://www.drupal.org/node/344575 for further discussion. Also, as MySQL
    // 5.5 changed the meaning of TRADITIONAL we need to spell out the modes one
    // by one.
    $connection_options += [
        'init_commands' => [],
    ];
    $connection_options['init_commands'] += [
        'sql_mode' => "SET sql_mode = 'ANSI,TRADITIONAL'",
    ];
    if (!empty($connection_options['isolation_level'])) {
        $connection_options['init_commands'] += [
            'isolation_level' => 'SET SESSION TRANSACTION ISOLATION LEVEL ' . strtoupper($connection_options['isolation_level']),
        ];
    }
    // Execute initial commands.
    foreach ($connection_options['init_commands'] as $sql) {
        $pdo->exec($sql);
    }
    return $pdo;
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.