> ## Documentation Index
> Fetch the complete documentation index at: https://docs.squasher.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# PHP

> Send errors, logs, and traces from PHP and Laravel apps to Squasher with OpenTelemetry or the HTTP API.

## Recommended: OpenTelemetry SDK

Use the official PHP OTel SDK for auto-instrumentation of Laravel, Symfony, and other frameworks.

### 1. Install

```bash theme={null}
composer require open-telemetry/sdk \
  open-telemetry/exporter-otlp \
  open-telemetry/transport-grpc
```

### 2. Configure

Set environment variables:

```bash theme={null}
export OTEL_EXPORTER_OTLP_ENDPOINT=https://ingest.squasher.ai
export OTEL_EXPORTER_OTLP_HEADERS="x-squasher-key=sq_pk_your_api_key"
export OTEL_SERVICE_NAME=my-php-app
export OTEL_PHP_AUTOLOAD_ENABLED=true
```

### 3. Run

```bash theme={null}
php artisan serve
```

## Laravel Exception Handler

Hook Squasher into Laravel's exception handler:

```php theme={null}
// app/Exceptions/Handler.php
use Illuminate\Support\Facades\Http;

public function register(): void
{
    $this->reportable(function (\Throwable $e) {
        Http::withHeaders([
            'x-squasher-key' => config('services.squasher.api_key'),
        ])->post(
            'https://ingest.squasher.ai/v1/ingest/' . config('services.squasher.project_id'),
            [
                'message' => $e->getMessage(),
                'type' => get_class($e),
                'level' => 'error',
                'stack' => $e->getTraceAsString(),
                'environment' => app()->environment(),
                'tags' => [
                    'url' => request()->fullUrl(),
                    'method' => request()->method(),
                ],
            ]
        );
    });
}
```

## Alternative: Direct HTTP API

```php theme={null}
<?php

function squasher_capture(\Throwable $error, array $tags = []): void
{
    $payload = json_encode([
        'message' => $error->getMessage(),
        'type' => get_class($error),
        'level' => 'error',
        'stack' => $error->getTraceAsString(),
        'environment' => getenv('APP_ENV') ?: 'production',
        'tags' => $tags,
    ]);

    $ch = curl_init('https://ingest.squasher.ai/v1/ingest/YOUR_PROJECT_ID');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $payload,
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            'x-squasher-key: sq_pk_your_api_key',
        ],
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 5,
    ]);
    curl_exec($ch);
    curl_close($ch);
}

// Usage
try {
    processPayment($order);
} catch (\Throwable $e) {
    squasher_capture($e, ['order_id' => $order->id]);
    throw $e;
}
```

## Agent handoff

```text theme={null}
For PHP or Laravel, prefer OpenTelemetry when auto-instrumentation is available. Otherwise use direct HTTP from the exception handler, keep keys in env, verify one handled exception, and avoid sending raw secrets in tags or stack-adjacent metadata.
```
