Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Dbal Laravel Package

doctrine/dbal

Doctrine DBAL is a powerful database abstraction layer for PHP, providing a consistent API across drivers plus rich schema introspection and management tools. Ideal for building portable SQL queries, migrations, and database tooling beyond PDO.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

Install via Composer:

composer require doctrine/dbal

First Use Case: Database Connection

use Doctrine\DBAL\DriverManager;

// Basic connection configuration
$connectionParams = [
    'dbname'   => env('DB_DATABASE'),
    'user'     => env('DB_USERNAME'),
    'password' => env('DB_PASSWORD'),
    'host'     => env('DB_HOST'),
    'driver'   => 'pdo_mysql', // or 'pdo_pgsql', 'pdo_sqlite', etc.
];

$conn = DriverManager::getConnection($connectionParams);

// Execute a simple query
$stmt = $conn->executeQuery('SELECT * FROM users LIMIT 10');
$users = $stmt->fetchAllAssociative();

Where to Look First:

  1. DBAL Documentation – Start with the "Getting Started" section.
  2. DriverManager – The entry point for creating connections.
  3. Connection Interface – Core methods like executeQuery(), executeStatement(), and schema management.
  4. QueryBuilder – For building complex queries programmatically.

Implementation Patterns

1. Query Execution Workflows

Basic Queries

// Fetch all rows
$stmt = $conn->executeQuery('SELECT * FROM products');
$products = $stmt->fetchAllAssociative();

// Fetch a single row
$product = $conn->fetchAssociative('SELECT * FROM products WHERE id = ?', [1]);

Prepared Statements (Recommended)

$stmt = $conn->prepare('INSERT INTO orders (user_id, amount) VALUES (?, ?)');
$stmt->bindValue(1, $userId);
$stmt->bindValue(2, $amount);
$stmt->execute();

Transactions

$conn->beginTransaction();
try {
    $conn->executeStatement('UPDATE accounts SET balance = balance - 100 WHERE id = ?', [$userId]);
    $conn->executeStatement('UPDATE accounts SET balance = balance + 100 WHERE id = ?', [$vendorId]);
    $conn->commit();
} catch (\Exception $e) {
    $conn->rollBack();
    throw $e;
}

2. Schema Introspection and Management

Inspecting Schema

$schemaManager = $conn->createSchemaManager();
$tables = $schemaManager->listTables(); // Array of Table objects
$table = $schemaManager->describeTable('users'); // Table metadata

Creating/Updating Tables

$schema = new \Doctrine\DBAL\Schema\Schema();
$table = $schema->createTable('users');
$table->addColumn('id', 'integer', ['autoincrement' => true]);
$table->addColumn('name', 'string', ['length' => 255]);
$table->setPrimaryKey(['id']);

$schemaManager->createTable($table); // Creates table if it doesn't exist
$schemaManager->dropTable('users'); // Drops table

Migrations (Advanced)

Use with Doctrine Migrations Bundle for Laravel:

composer require doctrine/doctrine-migrations-bundle
php artisan doctrine:migrations:diff
php artisan doctrine:migrations:migrate

3. QueryBuilder for Dynamic Queries

$queryBuilder = $conn->createQueryBuilder();
$queryBuilder
    ->select('u.id', 'u.name', 'o.amount')
    ->from('users', 'u')
    ->join('u', 'orders', 'o', 'u.id = o.user_id')
    ->where('o.created_at > :date')
    ->setParameter('date', new \DateTime('-1 month'))
    ->orderBy('o.amount', 'DESC')
    ->limit(10);

$stmt = $queryBuilder->execute();
$results = $stmt->fetchAllAssociative();

4. Integration with Laravel’s Eloquent

Use DBAL for raw queries when Eloquent is overkill:

use Doctrine\DBAL\Connection;

// In a Laravel service or repository
public function getRawUserData(Connection $conn, int $id)
{
    return $conn->fetchAssociative('SELECT * FROM users WHERE id = ?', [$id]);
}

Register DBAL Connection in Laravel:

// config/database.php
'dbal' => [
    'driver'   => 'pdo_mysql',
    'url'      => env('DATABASE_URL'),
    'host'     => env('DB_HOST', '127.0.0.1'),
    'port'     => env('DB_PORT', '3306'),
    'database' => env('DB_DATABASE', 'forge'),
    'username' => env('DB_USERNAME', 'forge'),
    'password' => env('DB_PASSWORD', ''),
    'unix_socket' => env('DB_SOCKET', ''),
    'charset'  => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix'   => '',
    'prefix_indexes' => true,
    'strict'   => true,
    'engine'   => null,
    'options'  => extension_loaded('pdo_mysql') ? array_filter([
        PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
    ]) : [],
],
// In a service provider
public function register()
{
    $this->app->bind(\Doctrine\DBAL\Connection::class, function ($app) {
        $config = $app['config']['database.dbal'];
        return \Doctrine\DBAL\DriverManager::getConnection($config);
    });
}

Gotchas and Tips

1. Connection Handling

  • Close connections explicitly in long-running scripts to avoid memory leaks:
    $conn->close();
    
  • Use connection pooling for high-traffic apps (e.g., pdo_pgsql with pgbouncer).

2. Query Performance

  • Avoid fetchAll() for large datasets – Use iterateAssociative() or chunked fetching:
    $stmt->iterateAssociative(function ($row) {
        // Process row-by-row
    });
    
  • Use executeStatement() for non-select queries (e.g., INSERT, UPDATE) to avoid fetching results.

3. Schema Management Pitfalls

  • Transactions in schema changes: Wrap schema operations in transactions to avoid partial updates:
    $conn->beginTransaction();
    try {
        $schemaManager->createTable($table);
        $conn->commit();
    } catch (\Exception $e) {
        $conn->rollBack();
        throw $e;
    }
    
  • Foreign key constraints: Disable them during bulk operations if needed:
    $conn->executeStatement('SET FOREIGN_KEY_CHECKS = 0');
    // ... bulk operations ...
    $conn->executeStatement('SET FOREIGN_KEY_CHECKS = 1');
    

4. Debugging Tips

  • Enable SQL logging:
    $conn->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger());
    
  • Check for reserved keywords: Use backticks for table/column names:
    $table->addColumn('`order`', 'string'); // Avoids SQL syntax errors
    

5. Laravel-Specific Quirks

  • Avoid mixing DBAL and Eloquent connections: Stick to one per use case to prevent confusion.
  • Use DBAL for multi-database queries: If your app uses multiple databases, DBAL provides a unified interface:
    $conn1 = DriverManager::getConnection(['url' => env('DB_URL_PRIMARY')]);
    $conn2 = DriverManager::getConnection(['url' => env('DB_URL_SECONDARY')]);
    

6. Extension Points

  • Custom Drivers: Implement \Doctrine\DBAL\Driver for unsupported databases.
  • Event Listeners: Use \Doctrine\DBAL\Event\Listeners for query logging, profiling, or rewriting.
  • Platform-Specific Features: Override \Doctrine\DBAL\Platforms\AbstractPlatform for database-specific SQL dialect tweaks.

7. Common Errors and Fixes

Error Cause Solution
PDOException: SQLSTATE[HY000] Invalid connection params Verify host, port, username, password.
InvalidParameterException Missing required column Check addColumn() parameters (e.g., length for strings).
ForeignKeyConstraintViolationException Referential integrity Ensure parent records exist before inserting children.
SyntaxErrorException Reserved keyword in query Use backticks: `table` or `column`.

8. Testing

  • Use in-memory SQLite for tests:
    $
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport