yajra/laravel-oci8
Oracle database driver for Laravel using the PHP OCI8 extension. Adds an Illuminate/Database-compatible Oracle connection with Laravel version support (5.1+ through 13), plus optional PHPStan/Larastan helpers for OCI8-specific DB methods.
## Getting Started
### Minimal Setup
1. **Install the package**:
```bash
composer require yajra/laravel-oci8:^13
Register the service provider (Laravel < 5.5):
Add to config/app.php:
Yajra\Oci8\Oci8ServiceProvider::class,
(Laravel 5.5+ auto-discovers it.)
Configure Oracle connection: Publish the config (optional but recommended):
php artisan vendor:publish --tag=oracle
Update .env with Oracle credentials:
DB_CONNECTION=oracle
DB_HOST=your_oracle_host
DB_PORT=1521
DB_SERVICE_NAME=your_service
DB_USERNAME=user
DB_PASSWORD=pass
DB_CHARSET=AL32UTF8
First use case: Query Oracle directly in a controller or model:
$users = DB::connection('oracle')->select('SELECT * FROM users WHERE active = 1');
Connection Handling:
DB::connection('oracle') or inject Yajra\Oci8\Oci8Connection into services.dynamic key in config/oracle.php:
'dynamic' => [App\Services\OracleConfig::class, 'getConfig'],
Query Building:
// Case-insensitive LIKE (12cR2+)
$results = DB::table('products')
->whereLike('name', '%search%')
->get();
// JSON filtering (12c02+)
$filtered = DB::table('orders')
->where('metadata', 'IS JSON')
->whereJsonContains('metadata->>\'$.status\'', '"completed"')
->get();
Migrations & Schema:
Schema::create() with Oracle-specific features:
Schema::create('posts', function (Blueprint $table) {
$table->id(); // Uses IDENTITY for 12c+
$table->string('title', 128); // Respects ORA_MAX_NAME_LEN
$table->json('metadata'); // Native JSON (21c+)
$table->comment('Stores blog posts');
});
IDENTITY (12c+):
$table->bigIncrements('id'); // Uses IDENTITY under the hood
Pagination & Performance:
cursor() for large datasets:
$cursor = DB::table('large_table')->cursor();
foreach ($cursor as $row) {
// Process row-by-row
}
retry_count and retry_delay (12c+) in .env for transient failures.Advanced Features:
$results = DB::table('documents')
->whereFullText('content', 'laravel oracle')
->get();
$query = DB::table('orders')
->select('orders.*')
->joinLateral(function ($join) {
$join->select('order_items.*')
->from('order_items')
->whereColumn('order_items.order_id', 'orders.id');
});
Eloquent Models:
class User extends Model {
protected $connection = 'oracle';
protected $primaryKey = 'USER_ID'; // Oracle often uses uppercase PKs
public $timestamps = false; // Oracle lacks default timestamp columns
}
Transactions:
DB::transaction() with Oracle’s SET TRANSACTION:
DB::connection('oracle')->transaction(function () {
// Oracle-specific transaction logic
});
Schema Prefixes:
PREFIX_):
'prefix_schema' => 'PREFIX_',
ORA_MAX_NAME_LEN (default: 30 chars) to avoid ORA-00972:
ORA_MAX_NAME_LEN=128
Load Balancing:
DB_HOST=host1,host2,host3
DB_LOAD_BALANCE=yes
Debugging Queries:
config/logging.php:
'default' => env('LOG_CHANNEL', 'oracle'),
'oracle' => [
'driver' => 'single',
'path' => storage_path('logs/oracle.log'),
'level' => 'debug',
],
Case Sensitivity:
binary_ci for case-insensitive queries (12cR2+):
$query->whereRaw('UPPER(name) = UPPER(?)', ['Search']);
config/auth.php:
'providers' => [
'users' => [
'driver' => 'oracle',
'model' => App\Models\User::class,
],
],
Sequence Ownership:
Schema::table() to manage them:
Schema::table('users', function (Blueprint $table) {
$table->sequence('user_id_seq')->ownedBySchema(true);
});
JSON Limitations:
$user->metadata = json_decode($user->metadata, true);
$user->metadata['status'] = 'updated';
$user->save();
Pagination Quirks:
ROWNUM behaves differently than MySQL. Use offset/limit carefully:
// Avoid:
$query->offset(100)->limit(10); // May skip rows in Oracle
// Prefer:
$query->skip(100)->take(10);
Character Sets:
DB_CHARSET=AL32UTF8 to avoid encoding issues with special characters.Connection Timeouts:
.env:
DB_CONNECT_TIMEOUT=10
DB_TRANSPORT_CONNECT_TIMEOUT=60
Schema Builder Issues:
ifExists() to avoid ORA-00942:
Schema::dropIfExists('users');
$table->index(['column_name'], 'idx_name_1'); // Truncates to 30 chars
Laravel Artisan:
php artisan migrate may fail silently. Enable Oracle logging:
DB_LOG_QUERIES=true
Enable OCI8 Debugging:
Add to php.ini or .htaccess:
oci8.log_file=/tmp/oci8.log
oci8.log_level=1023
Query Logs:
Check storage/logs/oracle.log for raw SQL and execution times.
Common Errors & Fixes:
| Error | Cause | Solution |
|---|---|---|
ORA-00942: table or view does not exist |
Schema prefix mismatch | Verify prefix_schema in config |
ORA-01031: insufficient privileges |
User lacks permissions | Grant CREATE SESSION, RESOURCE roles |
ORA-01795: maximum number of expressions in a list is 1000 |
whereIn with >1000 values |
Use whereRaw with IN (SELECT ...) |
ORA-00979: not a GROUP BY expression |
Grouping mismatch | Explicitly list all non-aggregated columns |
Performance:
SELECT *: Oracle fetchesHow can I help you explore Laravel packages today?