Installation:
composer require gabordemooij/redbean
Add to config/app.php under providers:
RedBeanPHP\Laravel\RedBeanServiceProvider::class,
Basic Configuration:
In config/redbean.php (auto-generated), set your database connection:
'connection' => 'mysql', // or 'pgsql', 'sqlite'
First Use Case:
use RedBeanPHP\R;
// Initialize RedBean
R::setup('mysql:host=localhost;dbname=test', 'username', 'password');
// Create a simple model (Eloquent or plain PHP object)
$user = new \App\Models\User; // Eloquent model
$user->name = 'John Doe';
R::store($user); // Works with Simple Models
// Tag a model
R::tag($user, 'admin');
$admins = R::findTagged('admin', 'App\Models\User');
vendor/redbeanphp/redbean/src/RedBeanPHP/Laravel/ (Laravel-specific helpers)// Tag an Eloquent model
$user = User::find(1);
R::tag($user, 'premium', 'vip'); // Multiple tags
// Find tagged models
$premiumUsers = R::findTagged('premium', User::class);
// Count tagged items
$count = R::countTagged('premium');
// Use Eloquent for core logic, RedBean for tags
$user = User::find(1); // Eloquent
R::tag($user, 'active'); // RedBean tagging
// Query with tags
$activeUsers = R::findTagged('active', User::class)->get();
// Dynamically add fields to a model
$post = new Post();
$post->title = 'Dynamic Post';
$post->custom_field = 'value'; // No schema needed
R::store($post);
DB::transaction(function () {
$order = Order::create(['user_id' => 1, 'amount' => 100]);
R::tag($order, 'pending');
});
Laravel Service Provider:
Override RedBean’s default behavior in RedBeanServiceProvider:
public function boot()
{
R::setEnforceUTF8Encoding(true);
R::setAllowFluidTransactions(true); // Laravel-style transactions
}
Eloquent Model Hooks: Use model events to sync RedBean tags:
// app/Models/User.php
protected static function booted()
{
static::saved(function ($user) {
if ($user->wasRecentlyCreated) {
R::tag($user, 'new_user');
}
});
}
Query Builder Integration: Combine Laravel’s query builder with RedBean:
$users = User::whereHas('posts', function ($q) {
$q->where('published', true);
})->get();
// Tag all published users
foreach ($users as $user) {
R::tag($user, 'published_author');
}
Caching Tags: Cache frequent tag queries:
$cachedTags = Cache::remember('premium_users', now()->addHours(1), function () {
return R::findTagged('premium', User::class)->pluck('id');
});
Simple Model Limitations:
No automatic relationship loading: Unlike Eloquent, RedBean doesn’t auto-load relationships. Use R::load() or R::loadJoined() explicitly.
// ❌ Won't work as expected
$user = User::find(1);
$user->posts; // May return null
// ✅ Correct
$user = R::load('user', 1);
$posts = R::findJoined('post', 'user_id = ?', [$user->id]);
Mass Assignment Risks: Simple Models bypass Eloquent’s $fillable. Sanitize inputs:
$user = new User();
$user->name = request()->input('name'); // Unsafe!
R::store($user);
Transaction Quirks:
R::transaction() doesn’t play well with Laravel’s DB::transaction(). Use Laravel’s transactions for consistency:
// ❌ Avoid mixing
DB::transaction(function () {
R::store($user); // May cause issues
});
// ✅ Preferred
R::setAllowFluidTransactions(true); // Then use R::transaction()
Tagging Edge Cases:
R::tag($user, strtolower('Premium')); // Store as 'premium'
Hybrid Mode Confusion:
// ❌ Double-save issues
$user = User::find(1);
$user->name = 'Updated';
$user->save(); // Eloquent
R::store($user); // RedBean (may cause conflicts)
Enable Debug Logging:
R::debug(true); // Logs all SQL queries to Laravel logs
Check for Frozen Beans: RedBean freezes beans after first load. Unfreeze if needed:
$user = R::load('user', 1);
R::unfreeze($user); // Allows modifications
PHP 8.5+ Gotchas:
// ✅ Preferred
R::tag($user, 'admin');
// ❌ May fail in PHP 8.5+
R::tag(user: $user, tag: 'admin');
Performance Bottlenecks:
R::loadJoined() or R::findWith() for related data:
$users = R::findWith('user', 'posts', 'user_id = ?', [1]);
R::findTagged() results aggressively.Custom Tag Handlers: Extend tag behavior via plugins:
R::addPlugin('tag', function ($bean, $tags) {
// Custom logic before tagging
return $tags;
});
Override Model Behavior:
Use R::setModel() to customize Simple Model handling:
R::setModel('user', [
'name' => 'App\Models\User',
'extra' => function ($bean) {
$bean->customMethod = function () { return 'Hello'; };
}
]);
DDL Templates: Customize schema generation:
R::setDDLTemplate('user', [
'id' => 'INTEGER PRIMARY KEY AUTO_INCREMENT',
'name' => 'VARCHAR(255) NOT NULL',
'custom_field' => 'TEXT'
]);
Event Listeners: Hook into RedBean’s lifecycle:
R::addEventListener('beforeStore', function ($bean) {
if ($bean instanceof User) {
$bean->created_at = now();
}
});
Service Container Binding:
Bind RedBean’s R facade to Laravel’s container:
$this->app->singleton('RedBeanPHP\R', function ($app) {
$r = new \RedBeanPHP\R();
$r->setWriteAheadLogging(true);
return $r;
});
Migration Conflicts: RedBean’s schema-less approach may conflict with Laravel migrations. Use:
R::
How can I help you explore Laravel packages today?