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

# Facade

> Come funzionano le facade di Laravel, come si usano, le real-time facade, come testarle e quando preferire la dependency injection.

## Cos'è una facade

Una facade fornisce un'interfaccia "statica" alle classi disponibili nel [service container](/it/service-container) dell'applicazione. Laravel include molte facade che danno accesso a quasi tutte le sue funzionalità.

Le facade di Laravel fungono da "proxy statici" alle classi reali all'interno del service container: offrono una sintassi concisa ed espressiva mantenendo maggiore testabilità e flessibilità rispetto ai metodi statici tradizionali.

Tutte le facade di Laravel sono definite nel namespace `Illuminate\Support\Facades`.

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

Route::get('/cache', function () {
    return Cache::get('key');
});
```

<Info>
  Non è un problema se non comprendi ancora completamente il funzionamento delle facade. Impara prima come usarle e continua a studiare Laravel.
</Info>

## Come funzionano le facade

Nelle applicazioni Laravel, una facade è una classe che offre accesso a un oggetto proveniente dal container. Questo meccanismo è implementato dalla classe `Facade`. Tutte le facade di Laravel e le facade personalizzate estendono la classe base `Illuminate\Support\Facades\Facade`.

La classe base `Facade` usa il metodo magico `__callStatic()` per delegare le chiamate alla facade all'oggetto risolto dal container.

```mermaid theme={null}
flowchart LR
    A["Cache::get('key')"] --> B["Facade::__callStatic()"]
    B --> C["getFacadeAccessor()<br>→ 'cache'"]
    C --> D["Service container<br>make('cache')"]
    D --> E["Istanza reale della classe<br>CacheManager"]
    E --> F["Esegue get('key')"]
```

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

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Cache;
use Illuminate\View\View;

class UserController extends Controller
{
    /**
     * Mostra il profilo dell'utente specificato
     */
    public function showProfile(string $id): View
    {
        $user = Cache::get('user:'.$id);

        return view('profile', ['user' => $user]);
    }
}
```

All'inizio del file importi la facade `Cache`. Questa facade fa da proxy verso l'implementazione dell'interfaccia `Illuminate\Contracts\Cache\Factory`. Tutte le chiamate effettuate tramite la facade vengono passate all'istanza interna del servizio di cache di Laravel.

Se guardi la classe `Illuminate\Support\Facades\Cache`, non troverai un metodo statico `get`.

```php theme={null}
class Cache extends Facade
{
    /**
     * Restituisce il nome di registrazione del componente
     */
    protected static function getFacadeAccessor(): string
    {
        return 'cache';
    }
}
```

La facade `Cache` estende la classe base `Facade` e definisce il metodo `getFacadeAccessor()`. Questo metodo restituisce il nome del binding nel service container. Quando l'utente chiama un metodo statico della facade `Cache`, Laravel risolve il binding `cache` dal service container ed esegue su quell'oggetto il metodo richiesto (in questo caso `get`).

## Quando usare (o non usare) le facade

### Vantaggi delle facade

Le facade offrono molti vantaggi. Forniscono una sintassi concisa e memorabile che consente di usare le funzionalità di Laravel senza dover ricordare lunghi nomi di classi da iniettare e configurare manualmente. Inoltre, grazie all'uso peculiare dei metodi dinamici di PHP, sono facili da testare.

### Attenzione allo scope creep

Il rischio principale nell'uso delle facade è lo "scope creep" delle classi. Poiché sono comode e non richiedono iniezione, si tende a far crescere una classe continuando ad aggiungere facade. Con la dependency injection, un costruttore che si allunga dà un chiaro segnale visivo. Quando usi le facade, presta attenzione alla dimensione delle classi e mantieni una responsabilità ristretta.

<Warning>
  Se senti che una classe è cresciuta troppo, valuta di suddividerla in più classi più piccole.
</Warning>

### Facade vs dependency injection

Uno dei principali vantaggi della dependency injection è la possibilità di sostituire l'implementazione della classe iniettata. Utile nei test: puoi iniettare mock o stub e verificare che vari metodi vengano invocati sullo stub.

Normalmente i metodi statici veri e propri non possono essere mockati né sostituiti, ma le facade — grazie ai metodi dinamici che fanno da proxy verso l'oggetto risolto dal service container — possono essere testate esattamente come un'istanza di classe iniettata.

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

Route::get('/cache', function () {
    return Cache::get('key');
});
```

Per questa route puoi scrivere il seguente test per verificare che `Cache::get` sia stato chiamato con l'argomento atteso.

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

test('basic example', function () {
    Cache::shouldReceive('get')
        ->with('key')
        ->andReturn('value');

    $response = $this->get('/cache');

    $response->assertSee('value');
});
```

### Facade vs funzioni helper

Oltre alle facade, Laravel fornisce funzioni "helper" per svolgere compiti comuni come creare viste, emettere eventi, dispatchare job e inviare risposte HTTP. Molte funzioni helper eseguono la stessa funzione della facade corrispondente.

```php theme={null}
// Chiamata tramite facade
return Illuminate\Support\Facades\View::make('profile');

// Chiamata equivalente tramite funzione helper
return view('profile');
```

Non ci sono differenze sostanziali tra facade e funzioni helper. Anche usando le funzioni helper puoi testarle come le facade corrispondenti.

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

test('cache helper test', function () {
    Cache::shouldReceive('get')
        ->with('key')
        ->andReturn('value');

    $response = $this->get('/cache');

    $response->assertSee('value');
});
```

## Real-time facade

Con le real-time facade puoi trattare qualsiasi classe dell'applicazione come una facade. Per spiegare come si usano, vediamo prima un codice senza real-time facade.

Supponi che il modello `Podcast` abbia un metodo `publish`. Per pubblicare il podcast è però necessario iniettare un'istanza di `Publisher`.

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

namespace App\Models;

use App\Contracts\Publisher;
use Illuminate\Database\Eloquent\Model;

class Podcast extends Model
{
    /**
     * Pubblica il podcast
     */
    public function publish(Publisher $publisher): void
    {
        $this->update(['publishing' => now()]);

        $publisher->publish($this);
    }
}
```

Usando una real-time facade non serve più passare esplicitamente un'istanza di `Publisher`, pur mantenendo la stessa testabilità. Per generare una real-time facade aggiungi il prefisso `Facades` al namespace della classe da importare.

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

namespace App\Models;

use Facades\App\Contracts\Publisher;
use Illuminate\Database\Eloquent\Model;

class Podcast extends Model
{
    /**
     * Pubblica il podcast
     */
    public function publish(): void
    {
        $this->update(['publishing' => now()]);

        Publisher::publish($this);
    }
}
```

Quando si usa una real-time facade, l'implementazione del publisher viene risolta dal service container usando la parte di interfaccia o classe che appare dopo il prefisso `Facades`.

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

use App\Models\Podcast;
use Facades\App\Contracts\Publisher;
use Illuminate\Foundation\Testing\RefreshDatabase;

pest()->use(RefreshDatabase::class);

test('podcast can be published', function () {
    $podcast = Podcast::factory()->create();

    Publisher::shouldReceive('publish')->once()->with($podcast);

    $podcast->publish();
});
```

<Tip>
  Le real-time facade sono comode quando vuoi eliminare la necessità di passare l'oggetto come argomento pur semplificando la creazione dei mock nei test.
</Tip>

## Testare le facade

Per testare le facade usa il metodo `shouldReceive`, che restituisce un'istanza mock di Mockery. Poiché le facade sono realmente risolte e gestite dal service container, sono molto più testabili delle classi statiche tradizionali.

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

test('mostra il profilo utente', function () {
    Cache::shouldReceive('get')
        ->once()
        ->with('user:1')
        ->andReturn(['name' => 'Taylor']);

    $response = $this->get('/users/1');

    $response->assertSee('Taylor');
});
```

I metodi di mock più comuni sono i seguenti.

| Metodo                    | Descrizione                                                |
| ------------------------- | ---------------------------------------------------------- |
| `shouldReceive('method')` | Ci si aspetta che il metodo venga chiamato                 |
| `once()`                  | Ci si aspetta che venga chiamato una sola volta            |
| `times(n)`                | Ci si aspetta che venga chiamato n volte                   |
| `with(args)`              | Ci si aspetta che venga chiamato con determinati argomenti |
| `andReturn(value)`        | Restituisce il valore indicato                             |
| `andReturnNull()`         | Restituisce null                                           |

## Elenco delle facade principali

Tabella di corrispondenza tra le facade più usate, la classe reale e il nome del binding nel service container.

| Facade         | Classe                                    | Binding      |
| -------------- | ----------------------------------------- | ------------ |
| `App`          | `Illuminate\Foundation\Application`       | `app`        |
| `Auth`         | `Illuminate\Auth\AuthManager`             | `auth`       |
| `Cache`        | `Illuminate\Cache\CacheManager`           | `cache`      |
| `Config`       | `Illuminate\Config\Repository`            | `config`     |
| `Cookie`       | `Illuminate\Cookie\CookieJar`             | `cookie`     |
| `Crypt`        | `Illuminate\Encryption\Encrypter`         | `encrypter`  |
| `DB`           | `Illuminate\Database\DatabaseManager`     | `db`         |
| `Event`        | `Illuminate\Events\Dispatcher`            | `events`     |
| `File`         | `Illuminate\Filesystem\Filesystem`        | `files`      |
| `Gate`         | `Illuminate\Contracts\Auth\Access\Gate`   | —            |
| `Hash`         | `Illuminate\Contracts\Hashing\Hasher`     | `hash`       |
| `Http`         | `Illuminate\Http\Client\Factory`          | —            |
| `Log`          | `Illuminate\Log\LogManager`               | `log`        |
| `Mail`         | `Illuminate\Mail\Mailer`                  | `mailer`     |
| `Notification` | `Illuminate\Notifications\ChannelManager` | —            |
| `Queue`        | `Illuminate\Queue\QueueManager`           | `queue`      |
| `RateLimiter`  | `Illuminate\Cache\RateLimiter`            | —            |
| `Redirect`     | `Illuminate\Routing\Redirector`           | `redirect`   |
| `Request`      | `Illuminate\Http\Request`                 | `request`    |
| `Route`        | `Illuminate\Routing\Router`               | `router`     |
| `Schema`       | `Illuminate\Database\Schema\Builder`      | —            |
| `Session`      | `Illuminate\Session\SessionManager`       | `session`    |
| `Storage`      | `Illuminate\Filesystem\FilesystemManager` | `filesystem` |
| `URL`          | `Illuminate\Routing\UrlGenerator`         | `url`        |
| `Validator`    | `Illuminate\Validation\Factory`           | `validator`  |
| `View`         | `Illuminate\View\Factory`                 | `view`       |

## Prossimi passi

<Card title="Contracts (contratti)" icon="file-contract" href="/it/contracts">
  Impara i concetti dei Contracts, controparte delle facade, e quando preferire l'uno o l'altro.
</Card>


## Related topics

- [Analisi statica dei pacchetti (PHPStan / Larastan)](/it/advanced/package-static-analysis.md)
- [Sviluppo di pacchetti Laravel](/it/advanced/package-development.md)
- [Contracts (contratti)](/it/contracts.md)
- [Mock](/it/mocking.md)
- [Logging](/it/logging.md)
