kreait/firebase-php
Firebase Admin SDK for PHP by kreait lets you access Firebase services like Auth, Firestore, Realtime Database, Storage, and Cloud Messaging from privileged server or cloud environments. Install with Composer: kreait/firebase-php ^8.0.
composer require kreait/firebase-php. Ensure you’re using PHP 8.0+ and have ext-json enabled. Version 8.5.0+ adds PSR-14 event dispatching—worth pinning to ^8.5 if you want lifecycle hooks for Auth, Messaging, and Remote Config. Version 8.6.0+ adds Remote Config experiment values and credential-free emulator support—pin ^8.6 if you run integration tests in CI or read experiment variants.config/services.php, add:
'firebase' => [
'credential' => env('FIREBASE_CREDENTIAL', storage_path('app/firebase-admin.json')),
'database_uri' => env('FIREBASE_DATABASE_URL', 'https://your-project-id.firebaseio.com'),
'storage_bucket' => env('FIREBASE_STORAGE_BUCKET', 'your-project-id.appspot.com'),
],
Or use Laravel’s config()->set() dynamically for flexibility.$firebase = (new Factory)->withServiceAccount(config('services.firebase.credential'));
$auth = $firebase->getAuth();
$user = $auth->getUserByEmail('[email protected]');
Start with auth or FCM—they’re the most common day-to-day needs.$factory = (new Factory)
->withServiceAccount(config('services.firebase.credential'))
->withEventDispatcher($psr14Dispatcher); // required, otherwise no events fire
Nothing is dispatched unless you opt in—so add this early rather than retrofitting listeners later.Firebase instance in a service provider (e.g., FirebaseServiceProvider) for consistent access. As of 8.5.0, inject the dispatcher here so every resolved service emits events:
$this->app->singleton(\Kreait\Firebase\Factory::class, function ($app) {
return (new \Kreait\Firebase\Factory)
->withServiceAccount(config('services.firebase.credential'))
->withDatabaseUri(config('services.firebase.database_uri'))
->withEventDispatcher($app->make(\Psr\EventDispatcher\EventDispatcherInterface::class));
});
Bind EventDispatcherInterface to a PSR-14 adapter wrapping Laravel’s dispatcher (see Gotchas) so listeners live in app/Listeners like normal Laravel code.users table, audit logs, or invalidating cached profiles.ShouldQueue) so a slow audit write doesn’t block the SDK call.Cache::remember) so per-request lookups don’t hammer the API, and invalidate on the template-published event.
$template = $remoteConfig->getTemplate();
$parameters = $template->getParameters(); // now includes experiment-backed entries
FirestoreUserRepository—to decouple business logic from SDK calls. Use DocumentReference and CollectionReference for type-safe queries.SendFirebaseNotification) for reliability. Leverage topic messaging for broadcast ($messaging->sendToTopic('news', $message)) and token-based for targeted sends. Pair this with the new messaging events to reconcile delivery results.FIREBASE_EMULATOR_HOST, FIREBASE_DATABASE_EMULATOR_HOST) and override Factory initialization in the testing environment. As of 8.6.0:
TESTING.md and helper scripts are the fastest way to reproduce a known-good emulator setup before debugging your own.
Use a fake/recording PSR-14 dispatcher in tests to assert which Firebase events fired.$auth->verifyIdToken($token) in API middleware to validate Firebase ID tokens and hydrate the user into the request. The new refresh-token-revocation events give you a push-based signal to force logout in your own session store.Illuminate\Contracts\Events\Dispatcher does not implement Psr\EventDispatcher\EventDispatcherInterface. You need an adapter—e.g. symfony/psr-event-dispatcher-adapter (new PsrEventDispatcherAdapter($app['events'])) or a tiny 15-line wrapper—otherwise withEventDispatcher() fails on type-hint. Note the adapter dispatches the event object itself, so Laravel listeners should type-hint the Firebase event class rather than receiving (Event $event) style parameters.withEventDispatcher(), 8.5.0+ behaves as before—no events, no listeners, no errors. Conversely, if you do provide one, an exception thrown inside a listener can surface from an unrelated SDK call, so keep listener logic defensive and queued.Event namespaces (Kreait\Firebase\Auth\Event, ...\Messaging\Event, ...\RemoteConfig\Event) after upgrading and register listeners against those classes; don’t guess class names from the changelog.app()->environment('testing') so it can never activate in production.storage_path() or environment-specific paths; rotate credentials if compromised.Google\Type\DateTime objects—always convert to native PHP DateTimeImmutable with ->toDateTime() before storage or serialization to avoid JSON encoding surprises. The same applies to timestamps carried on event payloads.Kreait\Firebase\Exception\InvalidArgumentException, Unavailable, NotFound) to handle partial failures—especially during batch operations (e.g., bulk FCM sends where some tokens may be invalid). Where a messaging validation-error event fires, treat it as a complement to exception handling, not a replacement.$factory = (new Factory)->withHttpOptions(['retries' => 3]);
Retried calls can emit events more than once—make listeners idempotent.finfo_open() and proper file MIME detection. Use StorageObject::upload($filePath, ['predefinedAcl' => 'publicRead']) for simplicity—but avoid public ACLs in production.\Kreait\Firebase\Auth)—not low-level HTTP calls. Use Factory::withServiceAccount() to inject test credentials (e.g., mock service accounts) for fast, isolated tests. For event assertions, bind a spy dispatcher and check it received the expected Firebase events rather than asserting on Laravel’s global event fake.How can I help you explore Laravel packages today?