Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Cloud Firestore Laravel Package

google/cloud-firestore

Idiomatic PHP client for Google Cloud Firestore. Install via Composer, authenticate with Google Cloud credentials, and use the generated FirestoreClient (gRPC required) to read/write documents and collections with robust error handling and API docs support.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require google/cloud-firestore
    

    Ensure the grpc PHP extension is enabled (see gRPC guide).

  2. Authentication: Configure credentials via environment variables (recommended) or service account JSON:

    putenv('GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json');
    

    Or use the credentials option in the client constructor:

    $firestore = new FirestoreClient(['credentials' => $serviceAccount]);
    
  3. First Query:

    use Google\Cloud\Firestore\FirestoreClient;
    
    $firestore = new FirestoreClient();
    $document = $firestore->document('projects/{PROJECT_ID}/databases/(default)/docs/users/123');
    $snapshot = $document->snapshot();
    $data = $snapshot->data();
    

First Use Case: CRUD Operations

// Create
$document->create(['name' => 'John', 'age' => 30]);

// Read
$snapshot = $document->snapshot();
$data = $snapshot->exists() ? $snapshot->data() : null;

// Update
$document->update(['age' => 31]);

// Delete
$document->delete();

Key Files to Reference:


Implementation Patterns

1. Repository Pattern Integration

Wrap Firestore operations in a Laravel repository to abstract away Firestore-specific logic:

class UserRepository
{
    protected $firestore;

    public function __construct(FirestoreClient $firestore)
    {
        $this->firestore = $firestore;
    }

    public function findById(string $id): ?array
    {
        $doc = $this->firestore->document("users/{$id}");
        $snapshot = $doc->snapshot();
        return $snapshot->exists() ? $snapshot->data() : null;
    }

    public function create(array $data): string
    {
        $doc = $this->firestore->collection('users')->document();
        $doc->set($data);
        return $doc->id();
    }
}

2. Real-Time Listeners

Use Firestore’s listeners for live updates (e.g., chat messages, notifications):

use Google\Cloud\Firestore\DocumentSnapshot;

$collection = $firestore->collection('messages');
$listener = $collection->listen(function (DocumentSnapshot $snapshot) {
    if ($snapshot->exists()) {
        $data = $snapshot->data();
        // Broadcast or process update (e.g., via Laravel Echo)
    }
});
// Unsubscribe later: $listener->cancel();

3. Transactions for Atomicity

Handle concurrent writes with transactions:

$firestore->runTransaction(function ($transaction) {
    $doc = $firestore->document('users/123');
    $snapshot = $transaction->get($doc);
    $data = $snapshot->data();
    $data['balance'] -= 100;
    $transaction->set($doc, $data);
});

4. Batching Writes

Optimize performance with batch writes:

$batch = $firestore->batch();
$batch->set($firestore->document('users/1'), ['name' => 'Alice']);
$batch->set($firestore->document('users/2'), ['name' => 'Bob']);
$batch->commit();

5. Querying with Filters

Use composite queries for complex filtering:

$query = $firestore->collection('products')
    ->where('category', '==', 'electronics')
    ->where('price', '>', 100)
    ->orderBy('price')
    ->limit(10);
$snapshot = $query->documents();

6. Offline Persistence

Enable offline persistence for mobile/web apps (requires client-side setup):

$firestore->setSettings([
    'isPersistenceEnabled' => true,
    'cacheSizeBytes' => FirestoreClient::CACHE_SIZE_UNLIMITED,
]);

7. Laravel Service Provider

Register Firestore as a Laravel singleton:

// app/Providers/FirestoreServiceProvider.php
public function register()
{
    $this->app->singleton(FirestoreClient::class, function ($app) {
        return new FirestoreClient([
            'projectId' => config('services.firestore.project_id'),
        ]);
    });
}

Gotchas and Tips

1. Authentication Pitfalls

  • Deprecated keyFile/keyFilePath: Use credentials option or environment variables instead (see #8617).
  • Service Account JSON: Ensure the JSON file has the correct permissions (e.g., roles/datastore.user).
  • Local Development: Use GOOGLE_APPLICATION_CREDENTIALS for simplicity:
    export GOOGLE_APPLICATION_CREDENTIALS="/path/to/key.json"
    

2. Performance Tips

  • Batch Writes: Use batch() for >1 write to reduce latency.
  • Indexing: Firestore requires indexes for queries with filters. Create them via the Cloud Console or API.
  • Pagination: Use limit() + startAfter() for large datasets:
    $lastDoc = $query->limit(10)->documents()[0];
    $nextQuery = $query->limit(10)->startAfter($lastDoc);
    

3. Debugging

  • Enable Logging: Pass a PSR-3 logger to the client:
    $logger = new Monolog\Logger('firestore');
    $firestore = new FirestoreClient(['logger' => $logger]);
    
  • Retry Logic: Wrap calls in retry logic for transient failures (e.g., google/rpc/code 5 or 14):
    try {
        $snapshot = $document->snapshot();
    } catch (ApiException $e) {
        if ($e->getStatusCode() === 5 || $e->getStatusCode() === 14) {
            // Retry with exponential backoff
        }
    }
    
  • Deadlines: Increase timeout for long-running operations (e.g., backups):
    $firestore->setSettings(['defaultDeadline' => 120]); // 2 minutes
    

4. Data Modeling Quirks

  • No Joins: Denormalize data or use subcollections (e.g., users/{uid}/orders).
  • Atomic Updates: Only modify fields you read in a transaction (no "add to array" without reading first).
  • Field Limits: Document fields are limited to ~1MB. For large data, use Cloud Storage or split into subcollections.

5. Laravel-Specific Tips

  • Eloquent Integration: Use spatie/firestore-eloquent for ORM-like usage.
  • Caching: Cache frequent queries with Laravel’s cache:
    $cacheKey = "firestore:products:electronics";
    return cache()->remember($cacheKey, now()->addMinutes(5), function () {
        return $query->documents();
    });
    
  • Events: Dispatch Laravel events on Firestore changes:
    $listener->listen(function (DocumentSnapshot $snapshot) {
        event(new UserUpdated($snapshot->id(), $snapshot->data()));
    });
    

6. Advanced Features

  • Vector Search: Use the Vector Index API for AI/ML workloads:
    $index = $firestore->index('projects/{PROJECT_ID}/locations/{LOCATION}/databases/(default)/indexes/vector_index');
    
  • Backup/Restore: Automate backups with Cloud Scheduler:
    $backup = $firestore->backup('projects/{PROJECT_ID}/databases/(default)');
    $backup->create(['location' => 'us-central1']);
    
  • Security Rules: Combine with Firestore’s security rules for fine-grained access control.

7. Common Errors

Error Cause Solution
INVALID_ARGUMENT: No document Document path malformed Use projects/{PROJECT_ID}/databases/(default)/docs/{COLLECTION}/{ID}
PERMISSION_DENIED Missing IAM permissions Grant roles/datastore.user to service account
UNAVAILABLE gRPC connection issues Check grpc extension and network policies
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport