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 and use the generated gRPC-based API to read/write documents, run queries, and manage data at scale. Part of the googleapis/google-cloud-php project.

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');
    

    Alternative: Use GOOGLE_CLOUD_PROJECT for ADC (Application Default Credentials).

  3. First Query:

    use Google\Cloud\Firestore\FirestoreClient;
    
    $firestore = new FirestoreClient();
    $document = $firestore->document('users/user123');
    $data = $document->create(['name' => 'John Doe', 'email' => 'john@example.com']);
    

Key First Use Cases

  • CRUD Operations: Replace Eloquent with Firestore’s Document/Collection methods.
  • Real-Time Updates: Use addSnapshotListener for live UI sync (e.g., chat apps).
  • Offline Persistence: Enable via FirestoreClient config for PWA-like behavior.

Implementation Patterns

Core Workflows

  1. Document Management:

    // Create/update
    $docRef = $firestore->collection('posts')->document();
    $docRef->set(['title' => 'Hello', 'views' => 0]);
    
    // Read
    $snapshot = $docRef->snapshot();
    $data = $snapshot->data();
    
    // Delete
    $docRef->delete();
    
  2. Collections & Queries:

    // Query with filters
    $query = $firestore->collection('posts')
        ->where('views', '>', 100)
        ->orderBy('createdAt', 'desc')
        ->limit(10);
    $results = $query->documents();
    
  3. Transactions:

    $firestore->runTransaction(function ($transaction) {
        $docRef = $firestore->document('counter');
        $snapshot = $transaction->get($docRef);
        $newValue = $snapshot->data()['count'] + 1;
        $transaction->update($docRef, ['count' => $newValue]);
    });
    
  4. Real-Time Listeners:

    $query = $firestore->collection('messages');
    $query->addSnapshotListener(function ($snapshot) {
        foreach ($snapshot->documents() as $doc) {
            echo $doc->data()['text'] . PHP_EOL;
        }
    });
    

Laravel Integration Tips

  • Service Provider: Bind the client in AppServiceProvider:

    $this->app->singleton(FirestoreClient::class, function () {
        return new FirestoreClient();
    });
    
  • Eloquent Alternative: Use a FirestoreModel trait to wrap Firestore operations:

    trait FirestoreModel {
        public function save() {
            $this->firestore->document($this->path)->set($this->toArray());
        }
    }
    
  • Query Builder: Extend Laravel’s Builder to support Firestore queries:

    class FirestoreBuilder extends Builder {
        public function whereGreaterThan($field, $value) {
            $this->query->where($field, '>', $value);
            return $this;
        }
    }
    
  • Events: Dispatch Laravel events on Firestore changes:

    $query->addSnapshotListener(function ($snapshot) {
        event(new FirestoreUpdated($snapshot->documents()));
    });
    

Gotchas and Tips

Pitfalls

  1. gRPC Dependencies:

    • Issue: Missing grpc extension causes ClassNotFoundException.
    • Fix: Enable extension=grpc.so in php.ini and restart PHP-FPM/Nginx.
  2. Authentication:

    • Issue: GOOGLE_APPLICATION_CREDENTIALS not found leads to silent failures.
    • Fix: Validate credentials early:
      if (!file_exists(getenv('GOOGLE_APPLICATION_CREDENTIALS'))) {
          throw new RuntimeException('Credentials file not found.');
      }
      
  3. Offline Persistence:

    • Issue: Enabled by default but may cause unexpected writes during network issues.
    • Fix: Disable explicitly if not needed:
      $firestore = new FirestoreClient(['settings' => ['offline' => false]]);
      
  4. Batching Writes:

    • Issue: Large batches (>500 ops) may fail with INVALID_ARGUMENT.
    • Fix: Split writes or use commit():
      $batch = $firestore->batch();
      foreach ($data as $item) {
          $batch->set($firestore->document("items/{$item['id']}"), $item);
          if ($batch->operations()->count() >= 500) {
              $batch->commit();
              $batch = $firestore->batch();
          }
      }
      $batch->commit();
      
  5. Field Paths:

    • Issue: Dot notation in field paths (e.g., user.profile.name) requires escaping:
      $docRef->set(['user.profile.name' => 'John'], ['merge' => true]);
      

Debugging

  • Enable Logging:

    $firestore = new FirestoreClient([
        'logger' => new \Monolog\Logger('firestore', [
            new \Monolog\Handler\StreamHandler('php://stderr', \Monolog\Logger::DEBUG)
        ])
    ]);
    
  • Common Errors:

    • PERMISSION_DENIED: Check IAM roles (e.g., roles/datastore.user).
    • NOT_FOUND: Verify document paths (e.g., projects/{project}/databases/{db}/documents/{path}).
    • DEADLINE_EXCEEDED: Increase timeout in config:
      $firestore = new FirestoreClient(['settings' => ['timeout' => 30]]);
      

Extension Points

  1. Custom Document Hydration: Override Document::data() to transform raw data:

    $snapshot->data(); // Returns array
    $snapshot->data(['casts' => ['createdAt' => 'datetime']]); // Casts fields
    
  2. Security Rules Bypass: Avoid: Disabling Firestore security rules in PHP. Instead, validate data in Laravel middleware:

    $request->validate([
        'email' => 'required|email',
        'role' => 'in:admin,user'
    ]);
    
  3. Performance:

    • Use select() to fetch only needed fields:
      $query->select(['title', 'views']);
      
    • Cache frequent queries with Laravel’s cache:
      $cacheKey = 'posts:featured';
      return Cache::remember($cacheKey, 60, function () use ($query) {
          return $query->documents();
      });
      
  4. Testing: Use the FirestoreTest trait or mock the client:

    $mock = Mockery::mock(FirestoreClient::class);
    $mock->shouldReceive('document')->andReturnSelf();
    $mock->shouldReceive('set')->andReturn(true);
    

Config Quirks

  • Database Selection: Defaults to (default); specify explicitly:

    $firestore = new FirestoreClient(['database' => '(my-database)']);
    
  • Emulator Support: For local testing, use the emulator:

    $firestore = new FirestoreClient([
        'host' => 'localhost:8080',
        'projectId' => 'my-project'
    ]);
    
  • Deprecated Options: Avoid keyFile/keyFilePath (deprecated in v1.54+). Use environment variables instead.

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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope