Configuració de la base de dades

Com configurar les connexions de base de dades a Laravel: MySQL, PostgreSQL i SQLite.

Configuració bàsica#

La configuració de la base de dades es troba al fitxer config/database.php, però els valors reals es llegeixen del fitxer .env. Això permet que cada desenvolupador de l'equip tingui la seva pròpia configuració local sense afectar la resta:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_andorra
DB_USERNAME=root
DB_PASSWORD=secret

La variable DB_CONNECTION determina quin driver de base de dades s'utilitza per defecte. Laravel suporta MySQL, PostgreSQL, SQLite i SQL Server de manera nativa.

Connexions disponibles#

El fitxer config/database.php conté la configuració de cada driver. Per defecte venen definides les connexions més comunes, i pots modificar-les o afegir-ne de noves:

// config/database.php
'connections' => [
    'sqlite' => [
        'driver' => 'sqlite',
        'database' => database_path('database.sqlite'),
        'prefix' => '',
        'foreign_key_constraints' => true,
    ],
 
    'mysql' => [
        'driver' => 'mysql',
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => env('DB_DATABASE', 'laravel'),
        'username' => env('DB_USERNAME', 'root'),
        'password' => env('DB_PASSWORD', ''),
        'charset' => 'utf8mb4',
        'collation' => 'utf8mb4_unicode_ci',
    ],
 
    'pgsql' => [
        'driver' => 'pgsql',
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '5432'),
        'database' => env('DB_DATABASE', 'laravel'),
        'username' => env('DB_USERNAME', 'root'),
        'password' => env('DB_PASSWORD', ''),
        'charset' => 'utf8',
        'schema' => 'public',
    ],
],

Cada connexió defineix els paràmetres específics del driver: host, port, nom de la base de dades, credencials i opcions com el charset o la collation. Els valors es llegeixen del .env amb env(), amb valors per defecte en cas que no estiguin definits.

SQLite per a desenvolupament#

SQLite és una opció ideal per a desenvolupament ràpid perquè no necessita un servidor de base de dades separat. Tota la base de dades es guarda en un sol fitxer. Per utilitzar-la, crea el fitxer i configura el .env:

touch database/database.sqlite
DB_CONNECTION=sqlite

No cal definir host, port ni credencials. Laravel 11 utilitza SQLite per defecte en projectes nous, cosa que fa que puguIs començar a treballar immediatament sense instal·lar cap servidor de base de dades.

Múltiples connexions#

Laravel permet configurar i utilitzar múltiples connexions de base de dades al mateix projecte. Això és útil quan necessites llegir dades d'una base de dades externa o separar lectures i escriptures:

// Consulta a la connexió per defecte
$users = DB::table('users')->get();
 
// Consulta a una connexió específica
$logs = DB::connection('logs_db')->table('logs')->get();

Per definir una connexió addicional, afegeix-la a l'array connections del fitxer config/database.php i configura les variables al .env:

LOGS_DB_CONNECTION=mysql
LOGS_DB_HOST=192.168.1.100
LOGS_DB_DATABASE=app_logs
LOGS_DB_USERNAME=logs_user
LOGS_DB_PASSWORD=secret
'logs_db' => [
    'driver' => env('LOGS_DB_CONNECTION', 'mysql'),
    'host' => env('LOGS_DB_HOST', '127.0.0.1'),
    'database' => env('LOGS_DB_DATABASE', 'logs'),
    'username' => env('LOGS_DB_USERNAME', 'root'),
    'password' => env('LOGS_DB_PASSWORD', ''),
],

Als models Eloquent, pots especificar quina connexió utilitza cada model amb la propietat $connection:

class Log extends Model
{
    protected $connection = 'logs_db';
}

Read/Write splitting#

Per a aplicacions amb molt tràfic, pots configurar connexions separades per a lectures i escriptures. Laravel enviarà automàticament les consultes SELECT a la connexió de lectura i les INSERT, UPDATE i DELETE a la d'escriptura:

'mysql' => [
    'read' => [
        'host' => ['192.168.1.1', '192.168.1.2'],
    ],
    'write' => [
        'host' => ['196.168.1.3'],
    ],
    'driver' => 'mysql',
    'database' => env('DB_DATABASE', 'laravel'),
    'username' => env('DB_USERNAME', 'root'),
    'password' => env('DB_PASSWORD', ''),
],

Comprovar la connexió#

Laravel proporciona comandes Artisan per inspeccionar la base de dades:

# Informació general de la connexió
php artisan db:show
 
# Informació d'una taula concreta
php artisan db:table users
 
# Obrir un client de base de dades interactiu
php artisan db

La comanda db:show mostra el driver, la versió del servidor, el nombre de taules i la mida de la base de dades. La comanda db:table mostra les columnes, tipus, índexs i claus foranes d'una taula concreta. Són eines molt útils per verificar que l'esquema està configurat correctament.

Consultes SQL directes#

Tot i que el Query Builder i Eloquent cobreixen la gran majoria de casos, de vegades necessites executar SQL directe. Laravel proporciona mètodes per fer-ho de manera segura:

use Illuminate\Support\Facades\DB;
 
// SELECT amb bindings (protegit contra SQL injection)
$users = DB::select('SELECT * FROM users WHERE active = ?', [true]);
 
// INSERT
DB::insert('INSERT INTO users (name, email) VALUES (?, ?)', ['Joan', 'joan@ex.com']);
 
// UPDATE
$affected = DB::update('UPDATE users SET active = ? WHERE id = ?', [true, 1]);
 
// DELETE
$deleted = DB::delete('DELETE FROM users WHERE active = ?', [false]);
 
// Statement genèric
DB::statement('ALTER TABLE users ADD COLUMN phone VARCHAR(20)');

Utilitza sempre bindings (el ? als exemples) en lloc de concatenar valors directament a la consulta SQL. Els bindings protegeixen contra atacs d'injecció SQL.

Transaccions#

Quan necessites que múltiples operacions de base de dades s'executin com una unitat atòmica (o totes o cap), utilitza transaccions:

use Illuminate\Support\Facades\DB;
 
DB::transaction(function () {
    DB::table('users')->where('id', 1)->update(['credits' => 0]);
    DB::table('orders')->insert([
        'user_id' => 1,
        'total' => 99.99,
    ]);
});

Si qualsevol operació dins de la transacció llança una excepció, tots els canvis es revertiran automàticament. Si tot va bé, els canvis es confirmen.

Per a un control més precís, pots gestionar la transacció manualment:

DB::beginTransaction();
 
try {
    DB::table('users')->where('id', 1)->update(['credits' => 0]);
    DB::table('orders')->insert(['user_id' => 1, 'total' => 99.99]);
 
    DB::commit();
} catch (\Exception $e) {
    DB::rollBack();
    throw $e;
}