writeConnection = $writeConnection; $this->readConnections = $readConnections; if (empty($this->readConnections)) { throw new DatabaseException('At least one read connection is required'); } // Initialize advanced router if dependencies are provided if ($this->config && $this->clock && $this->lagDetector) { $this->router = new MasterSlaveRouter( $writeConnection, $readConnections, $this->config, $this->clock, $this->lagDetector ); } } public function execute(SqlQuery $query): int { $this->forceWrite = true; return $this->writeConnection->execute($query); } public function query(SqlQuery $query): ResultInterface { $connection = $this->getConnection($query->sql); return $connection->query($query); } public function queryOne(SqlQuery $query): ?array { $connection = $this->getConnection($query->sql); return $connection->queryOne($query); } public function queryColumn(SqlQuery $query): array { $connection = $this->getConnection($query->sql); return $connection->queryColumn($query); } public function queryScalar(SqlQuery $query): mixed { $connection = $this->getConnection($query->sql); return $connection->queryScalar($query); } public function beginTransaction(): void { $this->forceWrite = true; $this->writeConnection->beginTransaction(); } public function commit(): void { $this->writeConnection->commit(); $this->forceWrite = false; } public function rollback(): void { $this->writeConnection->rollback(); $this->forceWrite = false; } public function inTransaction(): bool { return $this->writeConnection->inTransaction(); } public function lastInsertId(): string { return $this->writeConnection->lastInsertId(); } public function getPdo(): \PDO { return $this->writeConnection->getPdo(); } public function forceWriteConnection(): void { $this->forceWrite = true; } public function resetConnectionMode(): void { $this->forceWrite = false; $this->router?->resetStickyConnection(); } private function shouldUseWriteConnection(string $sql): bool { if ($this->forceWrite || $this->inTransaction()) { return true; } $sql = trim(strtoupper($sql)); $writeOperations = ['INSERT', 'UPDATE', 'DELETE', 'CREATE', 'ALTER', 'DROP', 'TRUNCATE']; return array_any($writeOperations, fn ($operation) => str_starts_with($sql, $operation)); } /** * Get appropriate connection for SQL query */ private function getConnection(string $sql): ConnectionInterface { if ($this->router) { return $this->router->route($sql, $this->forceWrite); } // Fallback to simple routing if ($this->shouldUseWriteConnection($sql)) { return $this->writeConnection; } return $this->getReadConnection(); } /** * Simple round-robin read connection selection (fallback) */ private function getReadConnection(): ConnectionInterface { static $currentReadIndex = 0; $connection = $this->readConnections[$currentReadIndex]; $currentReadIndex = ($currentReadIndex + 1) % count($this->readConnections); return $connection; } /** * Get read/write statistics */ public function getStatistics(): array { if ($this->router) { return $this->router->getStatistics(); } return [ 'router' => 'simple', 'master_connection' => 'active', 'replica_count' => count($this->readConnections), 'load_balancing_strategy' => 'round_robin', ]; } /** * Get write connection (for direct access if needed) */ public function getWriteConnection(): ConnectionInterface { return $this->writeConnection; } /** * Get read connections */ public function getReadConnections(): array { return $this->readConnections; } /** * Check if advanced routing is enabled */ public function hasAdvancedRouting(): bool { return $this->router !== null; } }