Getting Started
Database
Unified PDO-based DB class. Migrations, seeding, rollbacks. Use it or swap in Eloquent/Doctrine.
Configuration
Set creds in .env:
DB_HOST=localhost
DB_NAME=strata
DB_USER=root
DB_PASS=secret
DB_PREFIX=strata_
Access via config('database') or the DB class.
DB Class
All database access uses the unified DB class. No legacy mysqli code.
use App\DB;
// Assume $config is your database config array
$db = new DB($config);
// Query
$users = $db->query('SELECT * FROM users WHERE active = ?', [1])->fetchAll();
// Insert (you may need to write your own insert logic)
$db->query('INSERT INTO users (email, name) VALUES (?, ?)', ['barry@example.com', 'Barry']);
$userId = $db->insertId();
// Update
$db->query('UPDATE users SET name = ? WHERE id = ?', ['Barry Smith', $userId]);
// Transaction
try {
$db->beginTransaction();
$db->query('INSERT INTO orders (...) VALUES (...)', [...]);
$db->query('UPDATE inventory SET ... WHERE ...', [...]);
$db->commit();
} catch (Exception $e) {
$db->rollBack();
// handle error
}
Parameterized queries only. Prevents SQL injection by default.
Migrations
Schema changes are versioned. Never edit the DB directly.
php bin/migrate.php # Apply all new migrations
php bin/rollback.php 2 # Roll back last 2 migrations
php bin/migration_status.php # Show applied/pending
php bin/create_migration.php AddUsersTable # Scaffold new migration
Example Migration
File: migrations/002_create_users_table.php
// Migration: Create users table
return [
'up' => function($db) {
$db->query("CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
display_name VARCHAR(100) DEFAULT NULL,
first_name VARCHAR(100) NOT NULL,
second_name VARCHAR(100) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
pwd VARCHAR(255) NOT NULL,
is_admin TINYINT(1) DEFAULT 0,
active TINYINT(1) DEFAULT 1,
security_hash VARCHAR(64) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;");
echo "✅ Created users table\n";
},
'down' => function($db) {
$db->query("DROP TABLE IF EXISTS users");
echo "✅ Dropped users table\n";
}
];
Always create a down() method. Migration locking prevents concurrent runs in CI.
Seeding
Populate DB with test/demo data:
php bin/seed.php # Run all seeds/
php bin/seed.php --down # Remove seeded data
Example Seed
File: seeds/UserSeeder.php
function($db) {
$db->query("INSERT INTO users (first_name, second_name, email, pwd, is_admin, active, security_hash) VALUES
('Alice', 'Admin', 'alice@example.com', ?, 1, 1, ?),
('Bob', 'User', 'bob@example.com', ?, 0, 1, ?)
ON DUPLICATE KEY UPDATE email=email;", [
password_hash('secret', PASSWORD_DEFAULT), 'hash1',
password_hash('secret', PASSWORD_DEFAULT), 'hash2'
]);
},
'down' => function($db) {
$db->query("DELETE FROM users WHERE email IN ('alice@example.com', 'bob@example.com')");
}
];
Using an ORM
Don’t want the DB class? Bring Eloquent:
composer require illuminate/database
// In your bootstrap or config file:
use Illuminate\Database\Capsule\Manager as Capsule;
$capsule = new Capsule;
$capsule->addConnection($config['db']); // Use your actual config array
$capsule->setAsGlobal();
$capsule->bootEloquent();
Note:
- Make sure your
$config['db']array matches Eloquent’s expected format (host, database, username, password, etc.). - If you want to inject Eloquent models into routes via PSR-11, you must register/bind them in your container.
Strata doesn’t care. PSR-11 means you can inject Eloquent models into routes just like the DB class.