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 PHP database abstraction layer offering portable connections, a fluent query builder, schema introspection, and schema management tools. It supports multiple database platforms and underpins many Doctrine-based applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

Install via Composer:

composer require doctrine/dbal

First Use Case: Database Connection Leverage DBAL alongside Laravel's built-in Eloquent or Query Builder for raw SQL operations:

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DriverManager;

// Configure connection (similar to Laravel's .env)
$connectionParams = [
    'dbname' => env('DB_DATABASE'),
    'user' => env('DB_USERNAME'),
    'password' => env('DB_PASSWORD'),
    'host' => env('DB_HOST'),
    'driver' => 'pdo_mysql',
];

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

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

Key Starting Points:

  1. DBAL Documentation – Official API reference.
  2. Connection Class – Core interface for queries, transactions, and schema operations.
  3. QueryBuilder – Fluent SQL builder (alternative to Laravel’s Query Builder).
  4. SchemaManager – Introspect and manage database schemas.

Implementation Patterns

1. Query Execution Workflows

Basic CRUD with DBAL:

// Insert
$conn->insert('users', ['name' => 'John', 'email' => 'john@example.com']);

// Update
$conn->update('users', ['name' => 'Jane'], ['id' => 1]);

// Delete
$conn->delete('users', ['id' => 1]);

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

Bulk Operations:

// Batch insert
$conn->executeStatement(
    'INSERT INTO users (name, email) VALUES (:name, :email)',
    ['name' => 'Alice', 'email' => 'alice@example.com']
);

// Transaction
$conn->beginTransaction();
try {
    $conn->executeQuery('UPDATE accounts SET balance = balance - 100 WHERE id = 1');
    $conn->executeQuery('UPDATE accounts SET balance = balance + 100 WHERE id = 2');
    $conn->commit();
} catch (\Exception $e) {
    $conn->rollBack();
    throw $e;
}

2. Schema Management

Introspection (Inspect Database Structure):

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

Schema Updates (Migrations):

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

$sm = $conn->createSchemaManager();
$sm->createSchema($schema); // Apply schema

Laravel Integration Tip: Use DBAL’s SchemaManager in migrations or seeder classes:

use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\DriverManager;

public function up()
{
    $conn = DriverManager::getConnection(config('database.connections.mysql'));
    $schema = new Schema();
    // Define schema changes...
    $sm = $conn->createSchemaManager();
    $sm->createSchema($schema);
}

3. Query Builder for Complex Queries

Fluent SQL Construction:

$queryBuilder = $conn->createQueryBuilder();
$queryBuilder
    ->select('u.*')
    ->from('users', 'u')
    ->where('u.active = :active')
    ->andWhere('u.created_at > :date')
    ->setParameter('active', 1)
    ->setParameter('date', '2023-01-01')
    ->orderBy('u.name', 'ASC');

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

Subqueries and CTEs (Common Table Expressions):

// Subquery
$subQuery = $conn->createQueryBuilder()
    ->select('id')
    ->from('orders')
    ->where('status = :status')
    ->setParameter('status', 'completed');

$mainQuery = $conn->createQueryBuilder();
$mainQuery
    ->select('u.*')
    ->from('users', 'u')
    ->where('u.id IN (' . $subQuery->getSQL() . ')')
    ->setParameters($subQuery->getParameters());

Laravel Synergy: Use DBAL’s QueryBuilder for raw SQL where Eloquent’s query builder falls short (e.g., window functions, complex joins).


4. Type Handling and Portability

Database-Specific Types:

// JSON column handling
$conn->executeQuery(
    'INSERT INTO posts (content) VALUES (:content)',
    ['content' => json_encode(['title' => 'Hello'])]
);

// Enum/Set types
$conn->executeQuery(
    'INSERT INTO users (role) VALUES (:role)',
    ['role' => 'admin'] // DBAL auto-converts based on platform
);

Platform-Specific Logic:

$platform = $conn->getDatabasePlatform();
if ($platform->getName() === 'mysql') {
    // MySQL-specific syntax
    $conn->executeQuery('SET NAMES utf8mb4');
}

Gotchas and Tips

1. Connection Handling

  • Pitfall: Forgetting to close connections or reuse them inefficiently. Fix: Laravel’s service container manages connections, but for raw DBAL:
    // Reuse connections (avoid creating new ones per request)
    $conn = app(Connection::class); // If using Laravel's DBAL binding
    
  • Tip: Use DriverManager::getConnection() for one-off operations, but cache connections in Laravel’s service container for performance.

2. Transactions and Connection Loss

  • Pitfall: Transactions failing silently due to lost connections (e.g., MySQL timeouts). Fix: Wrap transactions in error handling:
    try {
        $conn->beginTransaction();
        // Operations...
        $conn->commit();
    } catch (\Doctrine\DBAL\Exception $e) {
        $conn->rollBack();
        throw new \RuntimeException('Transaction failed: ' . $e->getMessage());
    }
    
  • Tip: Use Connection::getWrappedConnection()->isTransactionActive() to check state.

3. Schema Introspection Quirks

  • Pitfall: Default values or expressions not being read correctly. Fix: Use SchemaManager::introspectTable() and inspect Column objects:
    $column = $schemaManager->listTableColumns('users')['email'];
    if ($column->getDefault() instanceof \Doctrine\DBAL\Types\DefaultExpression) {
        echo 'Default is an expression: ' . $column->getDefault()->getExpression();
    }
    
  • Tip: For complex defaults (e.g., NOW()), use DefaultExpression explicitly:
    $table->addColumn('created_at', 'datetime', [
        'default' => new \Doctrine\DBAL\Types\DefaultExpression('CURRENT_TIMESTAMP')
    ]);
    

4. Query Builder Gotchas

  • Pitfall: Parameter binding not working as expected in nested queries. Fix: Use QueryBuilder::createNamedParameter() for clarity:
    $qb->where('u.id = :id')
       ->setParameter('id', $userId, \PDO::PARAM_INT);
    
  • Tip: For dynamic conditions, build the WHERE clause incrementally:
    $qb = $conn->createQueryBuilder();
    $qb->select('*')->from('users');
    if ($activeOnly) {
        $qb->andWhere('active = :active')->setParameter('active', 1);
    }
    

5. Performance Tips

  • Bulk Inserts: Use executeStatement() for non-returning queries:
    $conn->executeStatement(
        'INSERT INTO logs (message) VALUES (:msg)',
        ['msg' => 'Event triggered'],
        ['msg' => \PDO::PARAM_STR]
    );
    
  • Batch Fetching: For large result sets, use iterateAssociative():
    $stmt = $conn->executeQuery('SELECT * FROM large_table');
    foreach ($stmt->iterateAssociative() as $row) {
        // Process row-by-row (memory efficient)
    }
    

6. Debugging and Logging

  • Enable SQL Logging:
    $conn->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger());
    
  • Tip: Use
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.
codraw/framework-extra-bundle
codraw/messenger
codraw/security
codraw/mailer
codraw/contracts
codraw/profiling
codraw/dependency-injection
codraw/tester
codraw/core
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony