Installation:
composer require alhames/db-bundle
For Symfony 7+ projects, no manual AppKernel.php registration is needed (Flex handles it).
Basic Configuration (config/packages/alhames_db.yaml):
alhames_db:
connections:
default:
host: '%env(DATABASE_HOST)%'
username: '%env(DATABASE_USER)%'
password: '%env(DATABASE_PASSWORD)%'
database: '%env(DATABASE_NAME)%'
First Use Case:
Inject the AlhamesDbBundle\ConnectionManager service and execute raw queries:
use AlhamesDbBundle\ConnectionManager;
class SomeService {
public function __construct(private ConnectionManager $db) {}
public function fetchUsers() {
$result = $this->db->getConnection('default')->query("SELECT * FROM users");
return $result->fetchAllAssociative();
}
}
ConnectionManager: Central service to access configured connections.Connection: Wrapper for PDO-like operations (e.g., query(), prepare()).Table: ORM-like abstraction for table operations (e.g., find(), insert()).Dynamic Connections: Use named connections (e.g., default, replica) in config:
alhames_db:
connections:
replica:
host: 'replica.example.com'
Access via:
$this->db->getConnection('replica');
Environment Variables: Leverage Symfony’s %env() for secrets:
password: '%env(DATABASE_PASSWORD)%'
Raw Queries:
$stmt = $connection->prepare("INSERT INTO logs (message) VALUES (:msg)");
$stmt->execute(['msg' => 'Test']);
Table Abstraction (ORM-like):
$users = $this->db->getTable('users')->findAll();
$user = $this->db->getTable('users')->find(1);
Transactions:
$connection->beginTransaction();
try {
$connection->query("UPDATE accounts SET balance = balance - 100 WHERE id = 1");
$connection->query("UPDATE accounts SET balance = balance + 100 WHERE id = 2");
$connection->commit();
} catch (\Exception $e) {
$connection->rollBack();
throw $e;
}
Dependency Injection:
// config/services.yaml
services:
App\Service\UserService:
arguments:
$db: '@alhames_db.connection_manager'
Event Listeners:
Use the query event to log/format SQL:
use AlhamesDbBundle\Event\QueryEvent;
class QueryLogger implements EventSubscriber {
public static function getSubscribedEvents() {
return [QueryEvent::QUERY => 'onQuery'];
}
public function onQuery(QueryEvent $event) {
error_log($event->getSql());
}
}
cache.app) in config/packages/alhames_db.yaml:
alhames_db:
cache: cache.app
$result = $connection->query("SELECT * FROM products", ['cache' => true]);
alhames_db:
logger: '@logger'
QueryEvent:
$event->setLogLevel(LogLevel::DEBUG);
Connection Pooling:
Connection objects instead of creating new ones per request.$this->db->getConnection('default')->query(...); // Per-request
$connection = $this->db->getConnection('default');
$connection->query(...); // Reused
PHP 8.4+ Compatibility:
strict_types=1 to catch type issues early.Table Abstraction Quirks:
getTable() assumes a default database/connection. Override via:
$this->db->getTable('users', ['connection' => 'replica']);
JOIN Constants:
AlhamesDbBundle\Query\Join constants for joins:
$query = $this->db->getTable('orders')
->select(['o.id', 'c.name'])
->join('customers', 'c.id = o.customer_id', Join::INNER);
Enable Query Logging:
logger: '@logger' and configure Symfony’s logger to debug:
monolog:
handlers:
main:
level: debug
Row Count Errors:
rowCount() is called after execute():
$stmt->execute();
$affectedRows = $stmt->rowCount(); // Works post-v2.0.2
Configuration Overrides:
!imports to override bundle config:
imports:
- { resource: config/packages/alhames_db.yaml }
alhames_db:
connections:
default:
host: 'custom-host.example.com' # Override
Custom Query Formatter:
AlhamesDbBundle\Query\QueryFormatterInterface and wire it via:
alhames_db:
query_formatter: 'app.query_formatter'
Event Subscribers:
QueryEvent (e.g., SQL sanitization, metrics):
$event->setSql(str_replace('SELECT', 'SELECT /* custom */', $event->getSql()));
Custom Table Classes:
AlhamesDbBundle\Table for domain-specific logic:
class UserTable extends Table {
public function findActive() {
return $this->where('is_active = 1')->findAll();
}
}
alhames_db.table tag.Multi-Database Workflows:
database option in table config to switch databases dynamically:
alhames_db:
tables:
analytics:
database: 'analytics_db'
$this->db->getTable('analytics', ['database' => 'new_analytics_db']);
Batch Operations:
executeBatch() for bulk inserts:
$data = [['name' => 'Alice'], ['name' => 'Bob']];
$connection->executeBatch(
"INSERT INTO users (name) VALUES (:name)",
$data
);
Connection Reuse:
Connection objects in services to avoid reconnection overhead.Query Caching:
$connection->query("SELECT * FROM products", ['cache' => true, 'ttl' => 3600]);
How can I help you explore Laravel packages today?