Mirror Laravel model inside Firestore collection.
firevel/firestore-mirror is a Laravel package for mirror laravel model inside firestore collection..
It currently has 6 GitHub stars and 7.257 downloads on Packagist (latest version 0.0.7).
Install it with composer require firevel/firestore-mirror.
Discover more Laravel packages by firevel
or browse all Laravel packages to compare alternatives.
Last updated
Automatically sync your Laravel Eloquent models to Google Firestore collections in real-time. This package provides a seamless way to mirror your database records to Firestore, enabling powerful real-time features and offline capabilities for your applications.
Install the package using Composer:
composer require firevel/firestore-mirror
Add the HasFirestoreMirror trait to any Eloquent model you want to sync with Firestore:
use Firevel\FirestoreMirror\HasFirestoreMirror;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
use HasFirestoreMirror;
// Optional: Customize the Firestore collection name
public $firestoreCollection = 'users';
// Optional: Customize the document structure
public function toFirestoreDocument()
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'created_at' => $this->created_at->toIso8601String(),
];
}
}
That's it! Your User model will now automatically sync to Firestore whenever you create, update, or delete records.
By default, the Firestore collection name matches your model's database table name. You can customize this in two ways:
class User extends Model
{
use HasFirestoreMirror;
public $firestoreCollection = 'app_users';
}
class User extends Model
{
use HasFirestoreMirror;
public function getFirestoreCollectionName()
{
return 'users_' . $this->tenant_id;
}
}
Control exactly what data gets synced to Firestore by overriding the toFirestoreDocument() method:
public function toFirestoreDocument()
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'role' => $this->role,
'metadata' => [
'last_login' => $this->last_login?->toIso8601String(),
'verified' => $this->email_verified_at !== null,
],
'updated_at' => $this->updated_at->toIso8601String(),
];
}
By default, the Firestore document ID matches your model's primary key. Override this behavior:
public function getFirestoreDocumentId()
{
return $this->uuid; // Use a UUID field instead
}
You can mirror a single model to multiple Firestore collections. This is useful for denormalization patterns common in Firestore, where you might want the same data available in different collections for efficient querying.
class User extends Model
{
use HasFirestoreMirror;
// Mirror to multiple collections
public $firestoreCollection = ['users', 'public_profiles'];
}
class User extends Model
{
use HasFirestoreMirror;
public function getFirestoreCollectionName()
{
return ['users', 'public_profiles', 'search_index'];
}
}
class User extends Model
{
use HasFirestoreMirror;
public function getFirestoreCollectionNames(): array
{
return ['users', 'public_profiles'];
}
}
When mirroring to multiple collections:
toFirestoreDocument() with conditional logicPriority Order: If multiple methods are defined, getFirestoreCollectionNames() takes precedence over getFirestoreCollectionName(), which takes precedence over the $firestoreCollection property.
Once you've added the HasFirestoreMirror trait, your models will automatically sync to Firestore on these events:
// This will automatically create a document in Firestore
$user = User::create([
'name' => 'John Doe',
'email' => '[email protected]'
]);
// This will automatically update the document in Firestore
$user->update(['name' => 'Jane Doe']);
// This will automatically delete the document from Firestore
$user->delete();
You can manually sync individual models:
$user = User::find(1);
$user->mirrorToFirestore(); // Manually sync to Firestore
The package provides a powerful mirrorToFirestore() collection macro for efficiently syncing multiple models at once using Firestore's batch operations:
// Sync all users to Firestore
User::all()->mirrorToFirestore();
// Sync filtered collections
User::where('active', true)->get()->mirrorToFirestore();
// Sync users with relationships loaded
User::with('posts')->get()->mirrorToFirestore();
// Sync paginated results
User::paginate(100)->mirrorToFirestore();
The batch operation is atomic - either all documents are synced successfully, or none are.
For large-scale operations or initial data migration, use the included Artisan command to mirror all records of a model to Firestore:
# Mirror all users to Firestore
php artisan firestore:mirror "App\Models\User"
# Mirror with custom chunk size (default: 100)
php artisan firestore:mirror "App\Models\User" --chunk=500
# Mirror any model with the HasFirestoreMirror trait
php artisan firestore:mirror "App\Models\Post" --chunk=200
Features:
HasFirestoreMirror traitExample Output:
Starting mirror process for App\Models\User...
Total records to mirror: 1500
1500/1500 [████████████████████████████] 100%
Successfully mirrored 1500 records to Firestore.
When to Use:
toFirestoreDocument() structureNote: The command respects the shouldMirrorToFirestore() method and will skip records that shouldn't be mirrored. For programmatic batch operations within your application code, use the collection macro ->mirrorToFirestore() instead.
To manually delete a model from Firestore without deleting it from your database:
$user = User::find(1);
$user->deleteFromFirestore();
You can temporarily disable Firestore syncing for specific operations using the withoutSyncingToFirestore() method:
// Disable syncing for a single operation
User::withoutSyncingToFirestore(function () {
User::create([
'name' => 'John Doe',
'email' => '[email protected]'
]);
});
// Disable syncing for multiple operations
User::withoutSyncingToFirestore(function () {
// None of these will sync to Firestore
$user = User::create(['name' => 'Jane']);
$user->update(['email' => '[email protected]']);
User::find(1)->update(['status' => 'inactive']);
});
// The callback return value is passed through
$user = User::withoutSyncingToFirestore(function () {
return User::create(['name' => 'Test User']);
});
This is particularly useful for:
The package provides built-in support for conditional syncing. Override the shouldMirrorToFirestore() method to control when models should be synced to Firestore:
class User extends Model
{
use HasFirestoreMirror;
/**
* Determine if the model should be mirrored to Firestore.
*
* @return bool
*/
public function shouldMirrorToFirestore()
{
// Only mirror active users with verified emails
return $this->is_active && $this->email_verified_at !== null;
}
}
When shouldMirrorToFirestore() returns false:
mirrorToFirestore() and deleteFromFirestore() will return early without making Firestore callsThis is useful for:
For multi-tenant applications, you can dynamically set collection names:
class Order extends Model
{
use HasFirestoreMirror;
public function getFirestoreCollectionName()
{
return "tenants/{$this->tenant_id}/orders";
}
}
Run the test suite:
composer test
Run a specific test:
vendor/bin/phpunit tests/Unit/HasFirestoreMirrorTest.php
Contributions are welcome! Please feel free to submit a Pull Request.
The MIT License (MIT). Please see License File for more information.