Driver MySQL/MariaDB para Phobos Framework Database Layer. Proporciona conectividad completa con características específicas de MySQL incluyendo strict mode, Unix sockets, configuración de sesión y operaciones de mantenimiento y algunas otras cosillas.
- 🔌 Conectividad MySQL/MariaDB - Soporte completo para ambos motores
- 🔒 Strict Mode - SQL estricto habilitado por defecto para seguridad
- ⚡ Unix Sockets - Conexiones locales de alto rendimiento
- 🌍 Timezone Configuration - Configuración de zona horaria por sesión
- 🔧 Session Variables - Configuración personalizada de variables MySQL
- 📊 Database Maintenance - OPTIMIZE TABLE y ANALYZE TABLE integrados
- 🔀 Transaction Isolation - Configuración de niveles de aislamiento
- 🎯 Savepoints Support - Transacciones anidadas completas
- 🏷️ MariaDB Detection - Detección automática de MariaDB vs MySQL
composer require mongoose-studio/phobos-framework-database-mysqlEste driver requiere:
mongoose-studio/phobos-framework^3.0mongoose-studio/phobos-framework-database^3.0- Extensión
ext-pdohabilitada - Extensión
ext-pdo_mysqlhabilitada
En tu config/database.php:
<?php
return [
'default' => 'mysql',
'drivers' => [
'mysql' => PhobosFramework\Database\Drivers\MySQL\MySQLDriver::class,
],
'connections' => [
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'port' => env('DB_PORT', 3306),
'database' => env('DB_DATABASE', 'myapp'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'strict' => true,
'timezone' => '+00:00',
],
],
];En tu archivo .env:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=myapp
DB_USERNAME=root
DB_PASSWORD=secret'mysql' => [
'driver' => 'mysql',
'host' => 'localhost', // Hostname o IP del servidor
'port' => 3306, // Puerto (opcional, default: 3306)
'database' => 'myapp', // Nombre de la base de datos
'username' => 'root', // Usuario
'password' => 'secret', // Contraseña
]'mysql' => [
// ...
'charset' => 'utf8mb4', // Default: utf8mb4
'collation' => 'utf8mb4_unicode_ci', // Default: utf8mb4_unicode_ci
]Charsets comunes:
utf8mb4- Full Unicode (recomendado, soporta emojis)utf8- Unicode básico (3 bytes, legacy)latin1- ISO-8859-1 (legacy)
Collations comunes:
utf8mb4_unicode_ci- Case-insensitive, correcto para la mayoríautf8mb4_general_ci- Más rápido pero menos precisoutf8mb4_bin- Case-sensitive, comparación binaria
'mysql' => [
// ...
'strict' => true, // Default: true (recomendado para producción)
]Strict Mode habilitado (true): (Recomendado)
- Rechaza datos inválidos en INSERT/UPDATE
- Previene fechas cero (0000-00-00)
- Division por cero genera error
- Más seguro y predecible
Strict Mode deshabilitado (false):
- Datos inválidos se truncan silenciosamente
- Permite fechas cero
- División por cero retorna NULL
- Útil solo para compatibilidad con sistemas legacy
'mysql' => [
// ...
'timezone' => '+00:00', // UTC (recomendado)
// 'timezone' => '-05:00', // EST
// 'timezone' => 'America/Santiago', // Timezone name
]Establece la zona horaria de la sesión MySQL. Recomendado usar UTC (+00:00) en la BD y manejar timezones en la aplicación.
Para conexiones locales, los Unix sockets ofrecen mejor rendimiento que TCP:
'mysql' => [
'driver' => 'mysql',
'database' => 'myapp',
'username' => 'root',
'password' => 'secret',
'unix_socket' => '/var/run/mysqld/mysqld.sock', // Path al socket
'charset' => 'utf8mb4',
// 'host' y 'port' son ignorados cuando se usa unix_socket
]Rutas comunes de sockets:
- Ubuntu/Debian:
/var/run/mysqld/mysqld.sock - RedHat/CentOS:
/var/lib/mysql/mysql.sock - macOS (Homebrew):
/tmp/mysql.sock - XAMPP:
/Applications/XAMPP/xamppfiles/var/mysql/mysql.sock
Configura variables MySQL específicas para cada conexión:
'mysql' => [
// ...
'session_variables' => [
'sql_mode' => 'TRADITIONAL',
'wait_timeout' => 28800,
'interactive_timeout' => 28800,
'max_execution_time' => 30000,
'group_concat_max_len' => 1000000,
],
]'mysql' => [
// ...
'options' => [
PDO::ATTR_TIMEOUT => 5,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
PDO::MYSQL_ATTR_FOUND_ROWS => true,
],
]El driver usa backticks para identificadores (tablas, columnas):
// Internamente el driver genera:
SELECT `users`.`id`, `users`.`name` FROM `users` WHERE `status` = 'active'
// Escapa backticks dentro de identificadores:
// `column`with`backticks` -> `column``with``backticks`MySQL soporta 4 niveles de aislamiento:
use PhobosFramework\Database\Connection\TransactionManager;
// READ UNCOMMITTED - Permite dirty reads
$tm->setIsolationLevel('READ UNCOMMITTED');
// READ COMMITTED - Previene dirty reads
$tm->setIsolationLevel('READ COMMITTED');
// REPEATABLE READ - Default de MySQL, previene non-repeatable reads
$tm->setIsolationLevel('REPEATABLE READ');
// SERIALIZABLE - Máximo aislamiento, previene phantom reads
$tm->setIsolationLevel('SERIALIZABLE');Nota: MySQL requiere establecer el nivel de aislamiento antes de iniciar la transacción.
MySQL soporta savepoints para transacciones anidadas:
beginTransaction(); // Transacción principal
try {
query()->insert('users')->values(['name' => 'John'])->execute();
beginTransaction(); // Savepoint sp_1
try {
query()->insert('posts')->values(['title' => 'Post'])->execute();
commit('sp_1'); // Commit savepoint
} catch (Exception $e) {
rollback('sp_1'); // Rollback solo el savepoint
}
commit(); // Commit transacción principal
} catch (Exception $e) {
rollback(); // Rollback completo
}El driver proporciona métodos para mantenimiento de base de datos:
Desfragmenta tablas, reclama espacio no utilizado y actualiza estadísticas:
use PhobosFramework\Database\Drivers\MySQL\MySQLDriver;
$driver = new MySQLDriver();
$pdo = db()->getPdo();
// Optimizar tabla específica
$driver->optimizeTable($pdo, 'users');
// Útil después de:
// - Muchas operaciones DELETE
// - Muchas operaciones UPDATE que cambian tamaño de registros
// - Carga masiva de datosActualiza estadísticas de la tabla para el optimizador de consultas:
$driver->analyzeTable($pdo, 'products');
// Útil después de:
// - Cambios significativos en los datos
// - Inserciones masivas
// - Para mejorar planes de ejecución de queriesEl driver puede detectar si estás usando MariaDB:
$driver = new MySQLDriver();
$pdo = db()->getPdo();
if ($driver->isMariaDB($pdo)) {
echo "Usando MariaDB";
// Habilitar características específicas de MariaDB
} else {
echo "Usando MySQL";
}
// Obtener versión
$version = $driver->getServerVersion($pdo);
echo "Versión: $version";'mysql_dev' => [
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'myapp_dev',
'username' => 'root',
'password' => '',
'charset' => 'utf8mb4',
'strict' => false, // Modo permisivo para desarrollo
'unix_socket' => '/var/run/mysqld/mysqld.sock',
]'mysql_prod' => [
'driver' => 'mysql',
'host' => env('DB_HOST'),
'port' => env('DB_PORT', 3306),
'database' => env('DB_DATABASE'),
'username' => env('DB_USERNAME'),
'password' => env('DB_PASSWORD'),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'strict' => true, // Modo estricto para producción
'timezone' => '+00:00', // UTC
'options' => [
PDO::ATTR_TIMEOUT => 5,
PDO::ATTR_PERSISTENT => false,
],
'session_variables' => [
'wait_timeout' => 28800,
'interactive_timeout' => 28800,
],
]'mysql_test' => [
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'myapp_test',
'username' => 'test_user',
'password' => 'test_pass',
'charset' => 'utf8mb4',
'strict' => true,
'unix_socket' => '/var/run/mysqld/mysqld.sock',
]'connections' => [
'mysql_primary' => [
'driver' => 'mysql',
'host' => 'primary.db.server',
'database' => 'myapp',
'username' => 'app_user',
'password' => 'secret',
],
'mysql_replica' => [
'driver' => 'mysql',
'host' => 'replica.db.server',
'database' => 'myapp',
'username' => 'readonly_user',
'password' => 'secret',
],
'mysql_analytics' => [
'driver' => 'mysql',
'host' => 'analytics.db.server',
'database' => 'analytics',
'username' => 'analytics_user',
'password' => 'secret',
],
]Uso:
// Escritura en primary
query('mysql_primary')
->insert('users')
->values(['name' => 'John'])
->execute();
// Lectura desde replica
$users = query('mysql_replica')
->select('*')
->from('users')
->fetch();
// Analytics
$stats = query('mysql_analytics')
->select('COUNT(*) as total')
->from('events')
->fetchOne();MySQLDriver
├── getDSN() - Construye DSN (tcp o unix_socket)
├── getPDOOptions() - Opciones PDO específicas de MySQL
├── configure() - Configuración post-conexión
├── getName() - Retorna 'mysql'
├── supportsSavepoints() - Retorna true
├── quoteIdentifier() - Envuelve en backticks
├── getSetIsolationLevelSQL() - SQL para isolation level
├── getServerVersion() - Obtiene versión del servidor
├── isMariaDB() - Detecta MariaDB
├── optimizeTable() - OPTIMIZE TABLE
└── analyzeTable() - ANALYZE TABLE
-
DSN Generation:
getDSN()construye la cadena DSN- TCP:
mysql:host=localhost;port=3306;dbname=myapp - Unix Socket:
mysql:unix_socket=/path/to/socket;dbname=myapp
- TCP:
-
PDO Creation: Se crea instancia PDO con opciones
MYSQL_ATTR_INIT_COMMANDpara charset/collation- Opciones adicionales del usuario
-
Post-Connection Config:
configure()ejecuta- Establece timezone si está configurado
- Configura strict mode
- Aplica session variables personalizadas
- MySQL 5.7+
- MySQL 8.0+
- MySQL 8.1+
- MySQL 8.2+
- MariaDB 10.3+
- MariaDB 10.4+
- MariaDB 10.5+
- MariaDB 10.6+
- MariaDB 10.11+ (LTS)
- MariaDB 11.0+
SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost'
Solución:
- Verifica usuario y contraseña en configuración
- Verifica que el usuario tenga permisos:
GRANT ALL PRIVILEGES ON mydb.* TO 'user'@'localhost'; - Ejecuta
FLUSH PRIVILEGES;después de cambiar permisos
SQLSTATE[HY000] [2002] Can't connect to MySQL server on 'localhost'
Solución:
- Verifica que MySQL esté corriendo:
systemctl status mysql - Verifica host y puerto en configuración
- Si usas
localhost, prueba con127.0.0.1 - Verifica firewall:
sudo ufw allow 3306/tcp
SQLSTATE[HY000] [1049] Unknown database 'myapp'
Solución:
- Crea la base de datos:
CREATE DATABASE myapp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - Verifica el nombre en la configuración
SQLSTATE[HY000] [2002] No such file or directory
Solución:
- Verifica la ruta del socket:
mysqladmin variables | grep socket - Verifica permisos del archivo socket
- Prueba con conexión TCP en su lugar
Si tienes problemas con strict mode en aplicaciones legacy:
'strict' => false, // Desactiva strict mode temporalmenteO configura solo algunos modos:
'session_variables' => [
'sql_mode' => 'NO_ZERO_DATE,NO_ZERO_IN_DATE',
]-
Usa Unix Sockets para conexiones locales
'unix_socket' => '/var/run/mysqld/mysqld.sock',
-
Configura timeouts apropiados
'options' => [ PDO::ATTR_TIMEOUT => 5, ], 'session_variables' => [ 'wait_timeout' => 28800, ],
-
Usa conexiones persistentes con cuidado
'options' => [ PDO::ATTR_PERSISTENT => true, // Solo en ambientes controlados ],
-
Optimiza tablas regularmente
// En un comando/cron $driver->optimizeTable($pdo, 'high_traffic_table'); $driver->analyzeTable($pdo, 'high_traffic_table');
Este proyecto está licenciado bajo la Licencia MIT - ver el archivo LICENSE para más detalles.
Marcel Rojas
marcelrojas16@gmail.com
Mongoose Studio
Las contribuciones son bienvenidas. Por favor:
- Fork el proyecto
- Crea una rama para tu feature (
git checkout -b feature/amazing-feature) - Commit tus cambios (
git commit -m 'Add amazing feature') - Push a la rama (
git push origin feature/amazing-feature) - Abre un Pull Request
Phobos Framework by Mongoose Studio