Weave 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

Forrest Laravel Package

omniphx/forrest

Laravel package for authenticating with Salesforce via OAuth and calling the REST, SOAP, and Apex APIs. Provides a clean wrapper around Guzzle with token refresh, query helpers, and configuration for seamless Salesforce integrations in Laravel apps.

View on GitHub
Deep Wiki
Context7

Getting Started

First Steps

  1. Installation

    composer require omniphx/forrest
    php artisan vendor:publish --provider="Omniphx\Forrest\ForrestServiceProvider" --tag="forrest-config"
    
    • Publishes config (config/forrest.php) with default Salesforce credentials (client ID, secret, redirect URI, etc.).
    • Run php artisan forrest:install to generate .env keys if missing.
  2. Configuration

    • Update .env with Salesforce credentials:
      FORREST_CLIENT_ID=your_consumer_key
      FORREST_CLIENT_SECRET=your_consumer_secret
      FORREST_REDIRECT_URI=http://your-app.test/salesforce/callback
      FORREST_LOGIN_URL=https://login.salesforce.com  # or sandbox
      
    • Configure in config/forrest.php:
      'scopes' => ['api', 'refresh_token', 'web'], // Required scopes
      'default' => 'main', // Default connection name
      'connections' => [
          'main' => [
              'client_id' => env('FORREST_CLIENT_ID'),
              'client_secret' => env('FORREST_CLIENT_SECRET'),
              'redirect_uri' => env('FORREST_REDIRECT_URI'),
              'login_url' => env('FORREST_LOGIN_URL'),
          ],
      ],
      
  3. First Use Case: OAuth Authentication

    • Redirect users to Salesforce for login:
      use Omniphx\Forrest\Facades\Forrest;
      
      return Forrest::auth()->redirect();
      
    • Handle the callback in a route:
      Route::get('/salesforce/callback', function () {
          $user = Forrest::auth()->user(); // Hydrated Salesforce user
          auth()->loginUsingId($user->id); // Optional: Sync with Laravel auth
          return redirect('/dashboard');
      });
      

Implementation Patterns

Common Workflows

  1. User Synchronization

    • Fetch and sync Salesforce users with Laravel:
      $salesforceUser = Forrest::auth()->user();
      $laravelUser = User::updateOrCreate(
          ['email' => $salesforceUser->email],
          [
              'name' => $salesforceUser->name,
              'salesforce_id' => $salesforceUser->id,
          ]
      );
      
  2. SOQL Queries

    • Execute SOQL (Salesforce Object Query Language) directly:
      $accounts = Forrest::query()
          ->from('Account')
          ->where('Name', 'like', '%Acme%')
          ->limit(10)
          ->get();
      
    • Use query builder for complex operations:
      $query = Forrest::query()->from('Opportunity');
      $query->where('StageName', '=', 'Closed Won');
      $query->select(['Id', 'Name', 'Amount']);
      $results = $query->get();
      
  3. Bulk API Operations

    • Insert/update records in bulk:
      $data = [
          ['Name' => 'Test Account 1', 'Type' => 'Customer'],
          ['Name' => 'Test Account 2', 'Type' => 'Partner'],
      ];
      Forrest::bulk()->insert('Account', $data);
      
  4. Webhooks and Real-Time Events

    • Subscribe to Salesforce platform events:
      Forrest::events()->subscribe('AccountChangeEvent', function ($payload) {
          // Handle real-time updates
          Log::info('Account changed:', $payload);
      });
      
    • Requires configuring a Platform Event Channel in Salesforce and updating config/forrest.php:
      'events' => [
          'channel' => env('FORREST_EVENT_CHANNEL', 'your_channel_name'),
          'consumer_key' => env('FORREST_EVENT_CONSUMER_KEY'),
      ],
      
  5. Metadata API

    • Retrieve or deploy Salesforce metadata:
      // Retrieve a component (e.g., Apex class)
      $metadata = Forrest::metadata()->retrieve('ApexClass', ['MyClass.cls']);
      // Deploy changes
      Forrest::metadata()->deploy($metadata);
      

Integration Tips

  • Laravel Auth Integration Use Forrest::auth()->user() to hydrate a Laravel User model and leverage Laravel’s auth system for role-based access control (RBAC).

  • Caching Responses Cache SOQL results or metadata to reduce API calls:

    $accounts = Cache::remember('salesforce_accounts', now()->addHours(1), function () {
        return Forrest::query()->from('Account')->get();
    });
    
  • Error Handling Wrap Forrest calls in try-catch blocks to handle Salesforce-specific errors (e.g., AuthException, QueryException):

    try {
        $user = Forrest::auth()->user();
    } catch (\Omniphx\Forrest\Exceptions\AuthException $e) {
        abort(403, 'Salesforce authentication failed');
    }
    
  • Testing Use the ForrestFake service provider for unit tests:

    use Omniphx\Forrest\Testing\ForrestFake;
    
    beforeEach(function () {
        ForrestFake::fake();
    });
    
    it('fetches a user', function () {
        ForrestFake::shouldReceive('user')->andReturn(new SalesforceUser());
        $user = Forrest::auth()->user();
        // Assertions...
    });
    

Gotchas and Tips

Pitfalls

  1. OAuth Token Expiry

    • Refresh tokens expire. Implement a middleware to refresh tokens before they fail:
      Forrest::auth()->refreshTokenIfExpired();
      
    • Store refresh tokens securely in the database or cache.
  2. SOQL Injection

    • Always use the query builder to avoid SOQL injection:
      // UNSAFE: Direct SOQL string
      $results = Forrest::query()->from("Account WHERE Name = '$unsafeInput'");
      
      // SAFE: Query builder
      $results = Forrest::query()->from('Account')->where('Name', '=', $safeInput)->get();
      
  3. Rate Limiting

    • Salesforce enforces API limits (e.g., 15 requests/second for bulk API). Implement exponential backoff:
      try {
          Forrest::query()->from('Account')->get();
      } catch (\Omniphx\Forrest\Exceptions\RateLimitException $e) {
          sleep($e->retryAfter);
          retry();
      }
      
  4. Connection Management

    • Use connection names for multi-tenant setups:
      Forrest::connection('sandbox')->query()->from('Account')->get();
      
    • Ensure config/forrest.php defines all connections.
  5. Platform Event Delays

    • Platform events may have latency. Use replayId to track processed events and avoid duplicates.

Debugging Tips

  1. Enable Logging Add to config/forrest.php:

    'logging' => true,
    

    Logs will appear in storage/logs/laravel.log.

  2. Inspect Raw Responses Use Forrest::getLastResponse() to debug API calls:

    $response = Forrest::query()->from('Account')->get();
    \Log::info(Forrest::getLastResponse()->getBody());
    
  3. Common Errors

    • InvalidClientId: Verify FORREST_CLIENT_ID and FORREST_CLIENT_SECRET in .env.
    • InsufficientAccess: Check OAuth scopes in config/forrest.php.
    • MalformedQuery: Validate SOQL syntax using the Salesforce SOQL Explorer.

Extension Points

  1. Custom Fields and Objects Extend the SalesforceUser model or create custom hydrators:

    Forrest::extend('user', function ($user) {
        $user->customField = Forrest::query()
            ->from('CustomObject__c')
            ->where('User__c', '=', $user->id)
            ->first();
        return $user;
    });
    
  2. Custom API Endpoints Use the underlying Guzzle client for non-SOQL endpoints:

    $client = Forrest::connection()->getClient();
    $response = $client->get('services/data/v56.0/sobjects/Account');
    
  3. Event Listeners Listen for Forrest events (e.g., auth.failed, query.executed):

    Forrest::listen('auth.failed', function ($exception) {
        \Log::warning('Salesforce auth failed', ['error' => $exception->getMessage()]);
    });
    
  4. Testing Helpers Extend ForrestFake for custom test data:

    ForrestFake::fake([
    
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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel