# PHP SDK

Report errors to BugBoard in three steps: install, configure a shared client, then call it.

> **Source on GitHub:** [github.com/bug-board/bugboard-php](https://github.com/bug-board/bugboard-php)
> Requires PHP 8.2+ and any PSR-18 HTTP client (Guzzle recommended).

## 1. Install

```bash
composer require bugboard/sdk
```

## 2. Add your credentials

A server uses a **secret** key — a key id plus a signing secret. Every request is HMAC-signed
and **the secret never travels on the wire**:

```dotenv
BUGBOARD_KEY_ID=bbk_xxxxxxxx
BUGBOARD_SIGNING_SECRET=bb_sec_xxxxxxxx
```

Get them from your project under **Settings → API Keys** (create a **Secret** key).

## 3. Get a client

How you build the client depends on your framework. Each of these has a detailed guide — start
here, then follow the link for error handlers, queue workers, testing and delivery timing.

### Laravel

Nothing to wire up: the package is auto-discovered, binds a shared client, and delivers reports
**after the response has been sent**. The `.env` values above are the whole setup.

```php
use BugBoard\Laravel\Facades\BugBoard;

BugBoard::critical('Payment failed', $e, ['payments', 'checkout']);
```

→ **[Full Laravel guide](/docs/frameworks/laravel)**

### Symfony

Enable the bundle, point it at the env vars, and autowire `BugBoard\Client` anywhere:

```yaml
# config/packages/bugboard.yaml
bugboard:
    key_id: '%env(BUGBOARD_KEY_ID)%'
    signing_secret: '%env(BUGBOARD_SIGNING_SECRET)%'
    environment: '%kernel.environment%'
```

→ **[Full Symfony guide](/docs/frameworks/symfony)** — including the `kernel.terminate`
listener that keeps reporting off the request path.

### Any other framework

Build the client once and hold onto it — reports buffer during the request and are delivered by
a shutdown hook (or call `flush()` yourself):

```php
use BugBoard\ClientBuilder;
use BugBoard\Config;

$bugboard = ClientBuilder::create(new Config(
    keyId: getenv('BUGBOARD_KEY_ID') ?: null,                 // bbk_…
    signingSecret: getenv('BUGBOARD_SIGNING_SECRET') ?: null, // bb_sec_…
    environment: 'production',

    // OPTIONAL — if provided, every payload is encrypted before it leaves the server.
    // encryptionKeyId: getenv('BUGBOARD_ENCRYPTION_KEY_ID') ?: null,         // bbek_…
    // encryptionPublicKey: getenv('BUGBOARD_ENCRYPTION_PUBLIC_KEY') ?: null, // base64 X25519

    // OPTIONAL — log reports locally instead of sending them (local debugging / dry run).
    // logLocally: true,
));

$bugboard->minor('Tooltip misaligned', null, 'ui,polish');
```

If your configuration already lives in an array, `ClientBuilder::createFromArray()` takes
`snake_case` **or** `camelCase` keys — it is what the Laravel and Symfony integrations use
internally.

→ **[Full plain-PHP guide](/docs/frameworks/plain-php)** — Slim, CodeIgniter, WordPress, CLI
tools and workers.

## 4. Use it

Call a severity method with a **title** (required); optionally pass a description — a string or
the caught `Throwable` — and tags.

```php
try {
    $payments->charge($order);
} catch (\Throwable $e) {
    $bugboard->criticalHigh('Payment failed', $e, ['payment', 'backend']);
}
```

The title is all you need:

```php
$bugboard->major('Checkout is slow');
```

That's it — the report is buffered and delivered in the background, and your request keeps
going.

## Common methods

Most apps only need these four (medium priority); each severity also has `…Low` and `…High`
variants — `criticalHigh`, `minorLow`, and so on:

```php
$bugboard->critical('Payment failed', $e); // highest severity
$bugboard->major('Checkout is slow', $e);
$bugboard->moderate('Slow image upload', $e);
$bugboard->minor('Tooltip misaligned');
```

Every method takes `(string $title, string|\Throwable|null $description = null, array|string $tags = [])`.
Tags are an array or a comma-separated string:

```php
$bugboard->critical('Payment failed', $e, ['payments', 'checkout']);
$bugboard->critical('Payment failed', $e, 'payments,checkout');
```

`$bugboard->droppedCount()` reports how many reports the buffer discarded — useful as a health
metric if you sample heavily or report in tight loops.

> **Keep titles stable.** Reports are deduplicated server-side by title, so
> `'Stripe webhook verification failed'` becomes one card with a climbing occurrence count,
> while `"Webhook {$id} failed"` becomes a new card every time. Put the variable parts in the
> description or the tags. See
> **[Deduplication](/docs/api-reference#deduplication-important-for-sdk-design)**.

## Next steps

- **[Framework guides](/docs/frameworks)** — Laravel, Symfony and plain PHP in detail:
  exception handlers, queue workers, Monolog, config caching, testing and troubleshooting.
- **[API Reference](/docs/api-reference)** — config options, every severity/priority variant
  (`criticalHigh`, …), and the full HTTP contract.
- **[Encrypting sensitive reports](/docs/security/encryption)** — seal the payload in transit
  with `encryptionPublicKey`. Needs PHP's `sodium` extension enabled on the host; check with
  `php -m | grep sodium`.
- **[Source on GitHub](https://github.com/bug-board/bugboard-php)** — the full SDK implementation.
