The `DriverManager` returns an instance of `Doctrine\DBAL\Connection` which is a wrapper around any configured database driver, for example the PDO Mysql driver in the previous example.
The `DriverManager` returns an instance of `Doctrine\DBAL\Connection` which is a
wrapper around the underlying driver connection (which is often a PDO instance).
The following sections describe the available connection parameters in detail.
+++ Driver
The driver specifies the actual implementations of the DBAL interfaces to use.
It can be configured in one of three ways:
* `driver`: The built-in driver implementation to use. The following drivers are currently available:
* `pdo_mysql`: A MySQL driver that uses the pdo_mysql PDO extension.
* `pdo_sqlite`: An SQLite driver that uses the pdo_sqlite PDO extension.
* `pdo_pgsql`: A PostgreSQL driver that uses the pdo_pgsql PDO extension.
* `pdo_oci`: An Oracle driver that uses the pdo_oci PDO extension. **Note that this driver caused problems in our tests. Prefer the oci8 driver if possible.**
* `oci8`:` An Oracle driver that uses the oci8 PHP extension.
* `driverClass`: Specifies a custom driver implementation if no 'driver' is specified. This allows the use of custom drivers that are not part of the Doctrine DBAL itself.
* `pdo`: Specifies an existing PDO instance to use.
+++ Wrapper Class
By default a `Doctrine\DBAL\Connection` is wrapped around a driver `Connection`.
The `wrapperClass` option allows to specify a custom wrapper implementation to use,
however, custom wrapper class must be a subclass of `Doctrine\DBAL\Connection`.
+++ Connection Details
The connection details identify the database to connect to as well as the
credentials to use. The connection details can differ depending on the used
driver. The following sections describe the options recognized by each built-in
driver.
> *NOTE*
> When using an existing PDO instance through the `pdo` option, specifying
> connection details is obviously not necessary.
++++ pdo_sqlite
* `user` (string): Username to use when connecting to the database.
* `password` (string): Password to use when connecting to the database.
* `path` (string): The filesystem path to the database file. Mutually exclusive with `memory`. `path` takes precedence.
* `memory` (boolean): True if the SQLite database should be in-memory (non-persistent). Mutually exclusive with `path`. `path` takes precedence.
++++ pdo_mysql
++ Connection Options
* `user` (string): Username to use when connecting to the database.
* `password` (string): Password to use when connecting to the database.
* `host` (string): Hostname of the database to connect to.
* `port` (integer): Port of the database to connect to.
* `dbname` (string): Name of the database/schema to connect to.
* `unix_socket` (string): Name of the socket used to connect to the database.
Common Configuration Options across all database drivers:
++++ pdo_pgsql
* **driver** - Allows to specify the default drivers shipped with Doctrine 2, 'pdo_mysql', 'pdo_sqlite', 'pdo_pgsql, and 'oci'.
* `user` (string): Username to use when connecting to the database.
* **driverClass** - If no 'driver' is specified this allows usage of a userland implementation of Doctrine\DBAL\Driver.
* `password` (string): Password to use when connecting to the database.
* **pdo** - If PDO is already instantiated for Mysql, SqLite or PgSQL this key can be used to pass this instance into Doctrine.
* `host` (string): Hostname of the database to connect to.
* **wrapperClass** - By default Doctrine\DBAL\Connection is wrapped around each driver, however this option allows to specify a userland sub-class.
* `port` (integer): Port of the database to connect to.
* `dbname` (string): Name of the database/schema to connect to.
Driver Configuration Options can be different for each Database Driver, here are some of the driver specific ones:
++++ pdo_oci / oci8
* `user` (string): Username to use when connecting to the database.
* `password` (string): Password to use when connecting to the database.
* `host` (string): Hostname of the database to connect to.
* `port` (integer): Port of the database to connect to.
* `dbname` (string): Name of the database/schema to connect to.
* `charset` (string): The charset used when connecting to the database.
+++ Custom Platform
Each built-in driver uses a default implementation of `Doctrine\DBAL\Platforms\AbstractPlatform`.
If you wish to use a customized or custom implementation, you can pass a precreated instance
in the `platform` option.
+++ Custom Driver Options
The `driverOptions` option allows to pass arbitrary options through to the driver.
This is equivalent to the 4th argument of the [PDO constructor](http://php.net/manual/en/pdo.construct.php).
+++ Events
++++ PostConnect Event
`Doctrine\DBAL\Events::postConnect` is triggered right after the connection to
the database is established. It allows to specify any relevant connection
specific options and gives access to the `Doctrine\DBAL\Connection` instance
that is responsible for the connection management via an instance of
Doctrine is already shipped with two implementations for the "PostConnect" event:
* `Doctrine\DBAL\Event\Listeners\OracleSessionInit` allows to specify any number of Oracle Session related enviroment variables that are set right after the connection is established.
* `Doctrine\DBAL\Event\Listeners\MysqlSessionInit` allows to specify the Charset and Collation of the Client Connection if these options are not configured correctly on the MySQL server side.
You can register events by subscribing them to the `EventManager` instance
* **platform** - An instance of `Doctrine\DBAL\Platforms\AbstractPlatform`. This is only required for userland implementations, each driver shipped with Doctrine 2 has a default platform.
The DBAL contains several methods for executing queries against your configured database for data retrieval and manipulation. Below we'll introduce these methods and provide some examples for each of them.
The DBAL contains several methods for executing queries against your configured
database for data retrieval and manipulation. Below we'll introduce these
methods and provide some examples for each of them.
++ prepare($sql)
++ prepare($sql)
...
@@ -8,7 +10,7 @@ Prepare a given sql statement and return the `\Doctrine\DBAL\Driver\Statement` i
...
@@ -8,7 +10,7 @@ Prepare a given sql statement and return the `\Doctrine\DBAL\Driver\Statement` i
$statement = $conn->prepare('SELECT * FROM user');
$statement = $conn->prepare('SELECT * FROM user');
$statement->execute();
$statement->execute();
$users = $statement->fetchAll();
$users = $statement->fetchAll();
/*
/*
array(
array(
0 => array(
0 => array(
...
@@ -20,7 +22,8 @@ Prepare a given sql statement and return the `\Doctrine\DBAL\Driver\Statement` i
...
@@ -20,7 +22,8 @@ Prepare a given sql statement and return the `\Doctrine\DBAL\Driver\Statement` i
++ executeUpdate($sql, array $params)
++ executeUpdate($sql, array $params)
Executes a prepared statement with the given sql and parameters and returns the affected rows count:
Executes a prepared statement with the given sql and parameters and returns the
affected rows count:
[php]
[php]
$count = $conn->executeUpdate('UPDATE user SET username = ? WHERE id = ?', array('jwage', 1));
$count = $conn->executeUpdate('UPDATE user SET username = ? WHERE id = ?', array('jwage', 1));
...
@@ -28,12 +31,13 @@ Executes a prepared statement with the given sql and parameters and returns the
...
@@ -28,12 +31,13 @@ Executes a prepared statement with the given sql and parameters and returns the
++ execute($sql, array $params)
++ execute($sql, array $params)
Creates a prepared statement for the given sql and passes the parameters to the execute method, then returning the statement:
Creates a prepared statement for the given sql and passes the parameters to the
execute method, then returning the statement:
[php]
[php]
$statement = $conn->execute('SELECT * FROM user WHERE username = ?', array('jwage'));
$statement = $conn->execute('SELECT * FROM user WHERE username = ?', array('jwage'));
$user = $statement->fetch();
$user = $statement->fetch();
/*
/*
array(
array(
0 => 'jwage',
0 => 'jwage',
...
@@ -47,7 +51,7 @@ Execute the query and fetch all results into an array:
...
@@ -47,7 +51,7 @@ Execute the query and fetch all results into an array:
[php]
[php]
$users = $conn->fetchAll('SELECT * FROM user');
$users = $conn->fetchAll('SELECT * FROM user');
/*
/*
array(
array(
0 => array(
0 => array(
...
@@ -56,7 +60,7 @@ Execute the query and fetch all results into an array:
...
@@ -56,7 +60,7 @@ Execute the query and fetch all results into an array:
)
)
)
)
*/
*/
++ fetchArray($sql, array $params)
++ fetchArray($sql, array $params)
...
@@ -64,7 +68,7 @@ Numeric index retrieval of first result row of the given query:
...
@@ -64,7 +68,7 @@ Numeric index retrieval of first result row of the given query:
[php]
[php]
$user = $conn->fetchArray('SELECT * FROM user WHERE username = ?', array('jwage'));
$user = $conn->fetchArray('SELECT * FROM user WHERE username = ?', array('jwage'));
/*
/*
array(
array(
0 => 'jwage',
0 => 'jwage',
...
@@ -86,7 +90,7 @@ Retrieve assoc row of the first result row.
...
@@ -86,7 +90,7 @@ Retrieve assoc row of the first result row.
[php]
[php]
$user = $conn->fetchRow('SELECT * FROM user WHERE username = ?', array('jwage'));
$user = $conn->fetchRow('SELECT * FROM user WHERE username = ?', array('jwage'));
/*
/*
array(
array(
'username' => 'jwage',
'username' => 'jwage',
...
@@ -120,7 +124,11 @@ Update all rows for the matching key value identifiers with the given data.
...
@@ -120,7 +124,11 @@ Update all rows for the matching key value identifiers with the given data.
// UPDATE user (username) VALUES (?) WHERE id = ? (jwage, 1)
// UPDATE user (username) VALUES (?) WHERE id = ? (jwage, 1)
By default the Doctrine DBAL does no escaping. Escaping is a very tricky business to do automatically, therefore there is none by default. The ORM internally escapes all your values, because it has lots of metadata available about the current context. When you use the Doctrine DBAL as standalone, you have to take care of this yourself. The following methods help you with it:
By default the Doctrine DBAL does no escaping. Escaping is a very tricky
business to do automatically, therefore there is none by default. The ORM
internally escapes all your values, because it has lots of metadata available
about the current context. When you use the Doctrine DBAL as standalone, you
have to take care of this yourself. The following methods help you with it:
Both `Doctrine\DBAL\DriverManager` and `Doctrine\DBAL\Connection` accept an instance of `Doctrine\Common\EventManager`. The EventManager has a couple of events inside the DBAL layer that are triggered for the user to listen to.
Both `Doctrine\DBAL\DriverManager` and `Doctrine\DBAL\Connection` accept an
instance of `Doctrine\Common\EventManager`. The EventManager has a couple of
events inside the DBAL layer that are triggered for the user to listen to.
++ PostConnect Event
++ PostConnect Event
`Doctrine\DBAL\Events::postConnect` is triggered right after the connection to the database is established. It allows to specify any relevant connection specific options and gives access to the `Doctrine\DBAL\Connection` instance that is responsible for the connection management via an instance of `Doctrine\DBAL\Event\ConnectionEventArgs` event arguments instance.
`Doctrine\DBAL\Events::postConnect` is triggered right after the connection to
the database is established. It allows to specify any relevant connection
specific options and gives access to the `Doctrine\DBAL\Connection` instance
that is responsible for the connection management via an instance of
Doctrine is already shipped with two implementations for the "PostConnect" event:
Doctrine is already shipped with two implementations for the "PostConnect" event:
* `Doctrine\DBAL\Event\Listeners\OracleSessionInit` allows to specify any number of Oracle Session related enviroment variables that are set right after the connection is established.
* `Doctrine\DBAL\Event\Listeners\OracleSessionInit` allows to specify any number of Oracle Session related enviroment variables that are set right after the connection is established.
* `Doctrine\DBAL\Event\Listeners\MysqlSessionInit` allows to specify the Charset and Collation of the Client Connection if these options are not configured correctly on the MySQL server side.
* `Doctrine\DBAL\Event\Listeners\MysqlSessionInit` allows to specify the Charset and Collation of the Client Connection if these options are not configured correctly on the MySQL server side.
You can register events by subscribing them to the `EventManager` instance passed to the Connection factory:
You can register events by subscribing them to the `EventManager` instance
The Doctrine 2 database layer can be used independently of the object-relational mapping. It offers a lightweight abstraction layer around a PDO like API and allows optional access to lots of convenience functionality as the ability to generate platform independent SQL and DDL statements.
The Doctrine database abstraction & access layer (DBAL) offers a leightweight
and thin runtime layer around a PDO-like API and a lot of additional, horizontal
features like database schema introspection and manipulation through an OO API.
In order to use the DBAL all you need is the `Doctrine\Common` and `Doctrine\DBAL` namespaces. Once you have the Common and DBAL namespaces you must setup a class loader to be able to autoload the classes:
The fact that the Doctrine DBAL abstracts the concrete PDO API away through the
use of interfaces that closely resemble the existing PDO API makes it possible
to implement custom drivers that may use existing native or self-made APIs. For
example, the DBAL ships with a driver for Oracle databases that uses the oci8
extension under the hood.
The Doctrine 2 database layer can be used independently of the object-relational
mapper. In order to use the DBAL all you need is the `Doctrine\Common` and
`Doctrine\DBAL` namespaces. Once you have the Common and DBAL namespaces you
must setup a class loader to be able to autoload the classes:
[php]
[php]
use Doctrine\Common\ClassLoader;
use Doctrine\Common\ClassLoader;
...
@@ -10,4 +21,6 @@ In order to use the DBAL all you need is the `Doctrine\Common` and `Doctrine\DBA
...
@@ -10,4 +21,6 @@ In order to use the DBAL all you need is the `Doctrine\Common` and `Doctrine\DBA
$classLoader = new ClassLoader('Doctrine', '/path/to/doctrine');
$classLoader = new ClassLoader('Doctrine', '/path/to/doctrine');
$classLoader->register();
$classLoader->register();
Now you are able to load classes that are in the `/path/to/doctrine` directory like `/path/to/doctrine/Doctrine/DBAL/DriverManager.php` which we will use later in this documentation to configure our first Doctrine DBAL connection.
Now you are able to load classes that are in the `/path/to/doctrine` directory
\ No newline at end of file
like `/path/to/doctrine/Doctrine/DBAL/DriverManager.php` which we will use later
in this documentation to configure our first Doctrine DBAL connection.
Doctrine handles transactions with a PDO like API, having methods for `beginTransaction()`, `commit()` and `rollBack()`. For consistency across different drivers Doctrine also handles the nesting of transactions internally. You can call `beginTransaction()` more than once, and only a matching amount of calls to `commit()` triggers the commit to the database.
A `Doctrine\DBAL\Connection` provides a PDO-like API for transaction management, with the
methods `Connection#beginTransaction()`, `Connection#commit()` and `Connection#rollback()`.
Transaction demarcation with the Doctrine DBAL looks as follows:
The Doctrine connection also has a method to set the transaction isolation level of the connection as supported by the underlying database. Here are the available isolation level constants that can be used:
[php]
[php]
class Connection
$conn->beginTransaction();
{
try{
/**
// do stuff
* Constant for transaction isolation level READ UNCOMMITTED.
$conn->commit();
*/
} catch(Exception $e) {
const TRANSACTION_READ_UNCOMMITTED = 1;
$conn->rollback();
throw $e;
/**
* Constant for transaction isolation level READ COMMITTED.
*/
const TRANSACTION_READ_COMMITTED = 2;
/**
* Constant for transaction isolation level REPEATABLE READ.
*/
const TRANSACTION_REPEATABLE_READ = 3;
/**
* Constant for transaction isolation level SERIALIZABLE.
*/
const TRANSACTION_SERIALIZABLE = 4;
}
}
Then you can use the above constants when configuring your connection instance:
Alternatively, the control abstraction `Connection#transactional($func)` can be used to make
the code more concise and to make sure you never forget to rollback the transaction in the case
of an exception. The following code snippet is functionally equivalent to the previous one:
However, **a rollback in a nested transaction block will always mark the current transaction so that the only possible outcome of the transaction is to be rolled back**.
That means in the above example, the rollback in the inner transaction block marks the whole transaction for rollback only.
Even if the nested transaction block would not rethrow the exception, the transaction is marked for rollback only and the commit of
the outer transaction would trigger an exception, leading to the final rollback.
This also means that you can not successfully commit some changes in an outer transaction if an inner transaction block fails and issues a rollback,
even if this would be the desired behavior (i.e. because the nested operation is "optional" for the purpose of the outer transaction block).
To achieve that, you need to restructure your application logic so as to avoid nesting transaction blocks. If this is not possible
because the nested transaction blocks are in a third-party API you're out of luck.
All that is guaruanteed to the inner transaction is that it still happens atomically, all or nothing, the transaction just gets a wider scope
and the control is handed to the outer scope.
> *CAUTION*
> The transaction nesting described here is a debated feature that has it's critics. Form your own opinion.
> We recommend avoiding nesting transaction blocks when possible, and most of the time, it is possible.
> Transaction control should mostly be left to a service layer and not be handled in data access objects or similar.
-
> **CAUTION**
> Directly invoking `PDO#beginTransaction()`, `PDO#commit()` or `PDO#rollback()` or the
> corresponding methods on the particular `Doctrine\DBAL\Driver\Connection` instance in
> use bybasses the transparent transaction nesting that is provided by
> `Doctrine\DBAL\Connection` and can therefore corrupt the nesting level, causing errors
> with broken transaction boundaries that may be hard to debug.