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

# Context

> Comment utiliser la fonctionnalité Context de Laravel pour partager des informations entre requêtes, jobs et commandes, et les injecter automatiquement dans les logs.

## Qu'est-ce que Context

Context est le mécanisme de Laravel pour enregistrer et partager des informations entre les requêtes, les jobs de file d'attente et les commandes.
Les informations ajoutées via la façade `Illuminate\Support\Facades\Context` sont automatiquement ajoutées à chaque entrée de log écrite par l'application.

Cela permet de distinguer clairement les informations passées à un appel de log spécifique et celles partagées via Context.
Particulièrement utile pour le tracing dans les systèmes distribués ou basés sur des files d'attente.

### Flux de propagation du contexte

```mermaid theme={null}
sequenceDiagram
    participant Client
    participant Middleware
    participant Controller
    participant Queue
    participant Job

    Client->>Middleware: Requête HTTP
    Middleware->>Middleware: Context::add('trace_id', uuid)
    Middleware->>Controller: next($request)
    Controller->>Controller: Log::info(...) — trace_id ajouté automatiquement
    Controller->>Queue: ProcessPodcast::dispatch()
    Queue->>Job: Sérialisation et envoi du contexte
    Job->>Job: Restauration (Hydrate) du contexte
    Job->>Job: Log::info(...) — trace_id ajouté automatiquement
```

## Utilisation de base

Le cas le plus classique : définir un `trace_id` dans un middleware. Il apparaît alors automatiquement dans toutes les entrées de log qui suivent.

<Steps>
  <Step title="Créer le middleware">
    ```shell theme={null}
    php artisan make:middleware AddContext
    ```
  </Step>

  <Step title="Ajouter un trace ID au Context">
    ```php theme={null}
    <?php

    namespace App\Http\Middleware;

    use Closure;
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Context;
    use Illuminate\Support\Str;
    use Symfony\Component\HttpFoundation\Response;

    class AddContext
    {
        public function handle(Request $request, Closure $next): Response
        {
            Context::add('url', $request->url());
            Context::add('trace_id', Str::uuid()->toString());

            return $next($request);
        }
    }
    ```
  </Step>

  <Step title="Enregistrer le middleware">
    Enregistrez-le comme middleware global dans `bootstrap/app.php`.

    ```php theme={null}
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->append(\App\Http\Middleware\AddContext::class);
    })
    ```
  </Step>
</Steps>

Après cette configuration, les logs écrits dans les contrôleurs ou services contiennent automatiquement `url` et `trace_id`.

```php theme={null}
Log::info('User authenticated.', ['auth_id' => Auth::id()]);
```

```text theme={null}
User authenticated. {"auth_id":27} {"url":"https://example.com/login","trace_id":"e04e1a11-e75c-4db3-b5b5-cfef4ef56697"}
```

## Écriture dans le contexte

### add — Ajouter une valeur

```php theme={null}
use Illuminate\Support\Facades\Context;

Context::add('key', 'value');

// Ajout multiple
Context::add([
    'first_key'  => 'value',
    'second_key' => 'value',
]);
```

`add` écrase les clés existantes. Pour n'ajouter que si la clé n'existe pas, utilisez `addIf`.

```php theme={null}
Context::add('key', 'first');
Context::addIf('key', 'second');

Context::get('key');
// "first" — non écrasée
```

### increment / decrement — Compteurs

Méthodes dédiées à l'incrémentation/décrémentation. Le second argument précise le pas.

```php theme={null}
Context::increment('records_added');
Context::increment('records_added', 5);

Context::decrement('records_added');
Context::decrement('records_added', 5);
```

### when — Ajout conditionnel

`when` permet d'ajouter des données différentes selon un booléen.

```php theme={null}
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Context;

Context::when(
    Auth::user()->isAdmin(),
    fn ($context) => $context->add('permissions', Auth::user()->permissions),
    fn ($context) => $context->add('permissions', []),
);
```

### push — Empiler dans une pile

Context gère des piles pour des données de type liste.
`push` empile dans l'ordre d'ajout.

```php theme={null}
Context::push('breadcrumbs', 'first_value');
Context::push('breadcrumbs', 'second_value', 'third_value');

Context::get('breadcrumbs');
// ['first_value', 'second_value', 'third_value']
```

Exemple : enregistrer l'historique des requêtes SQL dans une pile.

```php theme={null}
use Illuminate\Support\Facades\Context;
use Illuminate\Support\Facades\DB;

// Dans la méthode boot de AppServiceProvider.php
DB::listen(function ($event) {
    Context::push('queries', [$event->time, $event->sql]);
});
```

## Lecture du contexte

### get / all

```php theme={null}
$value = Context::get('key');

// Tout récupérer
$data = Context::all();
```

### only / except — Sous-ensembles

```php theme={null}
$data = Context::only(['first_key', 'second_key']);

$data = Context::except(['first_key']);
```

### pull / pop — Lire et supprimer

`pull` lit la valeur puis la retire du contexte.

```php theme={null}
$value = Context::pull('key');
```

Pour dépiler la dernière valeur d'une pile, utilisez `pop`.

```php theme={null}
Context::push('breadcrumbs', 'first_value', 'second_value');

Context::pop('breadcrumbs');
// 'second_value'

Context::get('breadcrumbs');
// ['first_value']
```

### remember — Définir si absent

```php theme={null}
$permissions = Context::remember(
    'user-permissions',
    fn () => $user->permissions,
);
```

### has / missing — Existence d'une clé

```php theme={null}
if (Context::has('key')) {
    // ...
}

if (Context::missing('key')) {
    // ...
}
```

<Info>
  `has` retourne `true` même si la valeur stockée est `null`. Elle vérifie uniquement la présence de la clé.
</Info>

## Suppression

Utilisez `forget` pour supprimer une clé.

```php theme={null}
Context::add(['first_key' => 1, 'second_key' => 2]);

Context::forget('first_key');

Context::all();
// ['second_key' => 2]

// Suppression multiple
Context::forget(['first_key', 'second_key']);
```

## Contexte scopé

`scope` modifie temporairement le contexte pour la durée d'une closure, puis restaure l'état initial.
Pratique pour joindre des informations locales à vos logs.

```php theme={null}
use Illuminate\Support\Facades\Context;
use Illuminate\Support\Facades\Log;

Context::add('trace_id', 'abc-999');
Context::addHidden('user_id', 123);

Context::scope(
    function () {
        Context::add('action', 'adding_friend');

        $userId = Context::getHidden('user_id');

        Log::debug("Adding user [{$userId}] to friends list.");
        // Adding user [987] to friends list.  {"trace_id":"abc-999","user_name":"taylor_otwell","action":"adding_friend"}
    },
    data: ['user_name' => 'taylor_otwell'],
    hidden: ['user_id' => 987],
);

// Après le scope, l'état d'origine est restauré
Context::all();
// ['trace_id' => 'abc-999']

Context::allHidden();
// ['user_id' => 123]
```

<Warning>
  Si vous modifiez un objet dans le scope, la modification persiste au-delà du scope. Ce n'est pas un problème pour les valeurs primitives.
</Warning>

## Hidden Context

Les données à ne pas exposer dans les logs (mots de passe, clés d'API, données personnelles) doivent être placées dans le Hidden Context.
`get` normal ne les retourne pas ; utilisez les méthodes dédiées `getHidden`.

```php theme={null}
use Illuminate\Support\Facades\Context;

Context::addHidden('key', 'value');

Context::getHidden('key');
// 'value'

Context::get('key');
// null — invisible via get normal
```

Le Hidden Context propose les mêmes méthodes que le contexte standard.

```php theme={null}
Context::addHidden(/* ... */);
Context::addHiddenIf(/* ... */);
Context::pushHidden(/* ... */);
Context::getHidden(/* ... */);
Context::pullHidden(/* ... */);
Context::popHidden(/* ... */);
Context::onlyHidden(/* ... */);
Context::exceptHidden(/* ... */);
Context::allHidden(/* ... */);
Context::hasHidden(/* ... */);
Context::missingHidden(/* ... */);
Context::forgetHidden(/* ... */);
```

## Transmission aux jobs de queue

Quand un job est dispatché, le contexte est automatiquement sérialisé dans le payload.
Il est restauré à l'exécution du job, ce qui permet au `trace_id` défini pendant la requête d'être présent dans les logs de la queue.

```php theme={null}
// Définition dans le middleware
Context::add('trace_id', Str::uuid()->toString());

// Dispatch dans le contrôleur
ProcessPodcast::dispatch($podcast);
```

```php theme={null}
class ProcessPodcast implements ShouldQueue
{
    use Queueable;

    public function handle(): void
    {
        Log::info('Processing podcast.', ['podcast_id' => $this->podcast->id]);
    }
}
```

```text theme={null}
Processing podcast. {"podcast_id":95} {"url":"https://example.com/login","trace_id":"e04e1a11-e75c-4db3-b5b5-cfef4ef56697"}
```

Le `trace_id` de la requête est bien présent dans les logs du job.

### Dehydrating — Personnaliser l'envoi du job

`Context::dehydrating` permet de modifier le contexte juste avant l'envoi du job.
Par exemple, pour transmettre la locale déterminée par l'en-tête `Accept-Language`.

```php theme={null}
// AppServiceProvider.php

use Illuminate\Log\Context\Repository;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Context;

public function boot(): void
{
    Context::dehydrating(function (Repository $context) {
        $context->addHidden('locale', Config::get('app.locale'));
    });
}
```

<Warning>
  Dans un callback `dehydrating`, n'utilisez pas la façade `Context`. Manipulez uniquement le `$context` passé en argument.
  L'utilisation de la façade modifierait le contexte du processus courant.
</Warning>

### Hydrated — Restauration lors de l'exécution du job

`Context::hydrated` s'exécute juste avant que le job ne démarre, une fois le contexte restauré.
Par exemple, pour réappliquer la locale stockée dans la configuration.

```php theme={null}
// AppServiceProvider.php

use Illuminate\Log\Context\Repository;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Context;

public function boot(): void
{
    Context::hydrated(function (Repository $context) {
        if ($context->hasHidden('locale')) {
            Config::set('app.locale', $context->getHidden('locale'));
        }
    });
}
```

<Warning>
  Dans un callback `hydrated` aussi, n'utilisez pas la façade `Context` : manipulez uniquement le `$context` fourni.
</Warning>

## Récapitulatif

<AccordionGroup>
  <Accordion title="Différence entre Context et Log::withContext">
    |                       | `Context`                       | `Log::withContext`               |
    | --------------------- | ------------------------------- | -------------------------------- |
    | Cible                 | Tous les channels de log        | Un channel spécifique            |
    | Transmission aux jobs | Automatique (Dehydrate/Hydrate) | Aucune                           |
    | Données cachées       | Prises en charge                | Non                              |
    | Usage                 | Tracing, systèmes distribués    | Métadonnées propres à un channel |
  </Accordion>

  <Accordion title="Données à mettre en Hidden Context">
    Le Hidden Context n'est pas écrit dans les logs, il convient donc pour :

    * Identifiants de session ou utilisateur (à ne pas exposer)
    * Clés d'API et tokens d'authentification
    * Locale et valeurs de configuration à transmettre aux jobs sans polluer les logs
    * Flags internes et états
  </Accordion>

  <Accordion title="Patterns Dehydrate/Hydrate courants">
    1. **Transmission de locale** : sauvegarder `app.locale` en Hidden Context via `dehydrating`, puis restaurer via `Config::set` dans `hydrated`.
    2. **Propagation d'authentification** : partager les informations de l'utilisateur authentifié entre la requête et le job.
    3. **ID de tenant** : partager l'identifiant de tenant entre requête et job dans une application multi-tenant.
  </Accordion>
</AccordionGroup>


## Related topics

- [Contexte de session et filtrage](/fr/packages/laravel-copilot-sdk/session-context.md)
- [Journalisation](/fr/logging.md)
- [Gestion des erreurs](/fr/error-handling.md)
- [Télémétrie](/fr/packages/laravel-copilot-sdk/telemetry.md)
- [Laravel AI SDK](/fr/ai-sdk.md)
