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

# Facades

> Uitleg over hoe facades in Laravel werken en hoe je ze gebruikt, real-time facades, testmethoden en de afweging tussen facades en dependency injection.

## Wat zijn facades?

Facades bieden een "statische" interface naar klassen die beschikbaar zijn in de [servicecontainer](/nl/service-container) van je applicatie. Laravel wordt geleverd met veel facades die toegang geven tot vrijwel alle functionaliteit.

Laravel-facades werken als "statische proxy's" naar de onderliggende klassen in de servicecontainer en bieden een beknopte, expressieve syntaxis, terwijl ze beter testbaar en flexibeler blijven dan traditionele statische methoden.

Alle Laravel-facades zijn gedefinieerd in de 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>
  Het is geen probleem als je het mechanisme achter facades nog niet volledig begrijpt. Leer eerst hoe je ze gebruikt en ga verder met het leren van Laravel.
</Info>

## Hoe facades werken

In een Laravel-applicatie is een facade een klasse die toegang biedt tot een object uit de container. Dit mechanisme wordt gerealiseerd door de `Facade`-klasse. Alle facades van Laravel, en ook je eigen facades, extenden de basisklasse `Illuminate\Support\Facades\Facade`.

De `Facade`-basisklasse gebruikt de magic method `__callStatic()` om aanroepen op de facade te delegeren naar het object dat uit de container is geresolved.

```mermaid theme={null}
flowchart LR
    A["Cache::get('key')"] --> B["Facade::__callStatic()"]
    B --> C["getFacadeAccessor()<br>→ 'cache'"]
    C --> D["Servicecontainer<br>make('cache')"]
    D --> E["Instantie van de echte klasse<br>CacheManager"]
    E --> F["get('key')<br>uitvoeren"]
```

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

namespace App\Http\Controllers;

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

class UserController extends Controller
{
    /**
     * Toon het profiel van de opgegeven gebruiker
     */
    public function showProfile(string $id): View
    {
        $user = Cache::get('user:'.$id);

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

Bovenaan het bestand importeren we de `Cache`-facade. Deze facade proxyt de toegang tot de implementatie van de `Illuminate\Contracts\Cache\Factory`-interface. Alle aanroepen via de facade worden doorgegeven aan de onderliggende instantie van de cacheservice van Laravel.

Als je naar de klasse `Illuminate\Support\Facades\Cache` kijkt, zie je dat er geen statische methode `get` bestaat.

```php theme={null}
class Cache extends Facade
{
    /**
     * Haal de registratienaam van het component op
     */
    protected static function getFacadeAccessor(): string
    {
        return 'cache';
    }
}
```

De `Cache`-facade extendt de basisklasse `Facade` en definieert de methode `getFacadeAccessor()`. Deze methode geeft de naam van de servicecontainerbinding terug. Wanneer een gebruiker een statische methode op de `Cache`-facade aanroept, resolvet Laravel de `cache`-binding uit de servicecontainer en voert het de gevraagde methode (in dit geval `get`) op dat object uit.

## Wanneer wel en niet facades gebruiken

### Voordelen van facades

Facades hebben veel voordelen. Ze bieden een beknopte, gemakkelijk te onthouden syntaxis waarmee je de functionaliteit van Laravel kunt gebruiken zonder lange klassennamen te hoeven onthouden die je handmatig moet injecteren en configureren. Bovendien zijn ze door hun unieke gebruik van de dynamische methoden van PHP eenvoudig te testen.

### Pas op voor scope creep

Het grootste gevaar bij het gebruik van facades is "scope creep" van je klassen. Omdat facades makkelijk te gebruiken zijn en geen injectie vereisen, is het verleidelijk om je klassen te laten groeien en steeds meer facades te gebruiken. Bij dependency injection geeft een grote constructor je visuele feedback. Let bij het gebruik van facades dus op de omvang van je klassen en houd hun verantwoordelijkheden beperkt.

<Warning>
  Als je het gevoel hebt dat een klasse te groot wordt, overweeg dan om die op te splitsen in meerdere kleinere klassen.
</Warning>

### Facades vs. dependency injection

Een van de belangrijkste voordelen van dependency injection is dat je de implementatie van een geïnjecteerde klasse kunt vervangen. Dat is handig bij het testen: je kunt een mock of stub injecteren en asserteren dat verschillende methoden op de stub zijn aangeroepen.

Echt statische klassemethoden kun je normaal gesproken niet mocken of stubben, maar omdat facades dynamische methoden gebruiken om methodeaanroepen te proxyen naar objecten die uit de servicecontainer zijn geresolved, kun je facades net zo testen als een geïnjecteerde klasse-instantie.

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

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

Voor deze route kun je de volgende test schrijven om te verifiëren dat `Cache::get` met de verwachte argumenten is aangeroepen.

```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');
});
```

### Facades vs. helperfuncties

Naast facades biedt Laravel "helper"-functies waarmee je veelvoorkomende taken kunt uitvoeren, zoals views genereren, events afvuren, jobs dispatchen en HTTP-responses versturen. Veel helperfuncties bieden dezelfde functionaliteit als hun bijbehorende facade.

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

// Equivalente aanroep via een helperfunctie
return view('profile');
```

Er is geen praktisch verschil tussen facades en helperfuncties. Ook wanneer je helperfuncties gebruikt, kun je ze op dezelfde manier testen als de bijbehorende facade.

```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 facades

Met real-time facades kun je elke klasse in je applicatie als facade behandelen. Om het gebruik uit te leggen, kijken we eerst naar code zonder real-time facades.

Stel bijvoorbeeld dat het `Podcast`-model een `publish`-methode heeft. Om de podcast te publiceren, moet echter een `Publisher`-instantie worden geïnjecteerd.

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

namespace App\Models;

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

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

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

Met real-time facades hoef je de `Publisher`-instantie niet meer expliciet door te geven, terwijl je dezelfde testbaarheid behoudt. Om een real-time facade te genereren, zet je de prefix `Facades` voor de namespace van de klasse die je importeert.

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

namespace App\Models;

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

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

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

Wanneer een real-time facade wordt gebruikt, wordt de publisher-implementatie uit de servicecontainer geresolved op basis van het gedeelte van de interface- of klassennaam dat na de `Facades`-prefix komt.

```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>
  Real-time facades zijn handig wanneer je het mocken in tests eenvoudig wilt houden en tegelijkertijd niet langer als argument wilt hoeven doorgeven.
</Tip>

## Facades testen

Om facades te testen gebruik je de `shouldReceive`-methode. Deze geeft een Mockery-mockinstantie terug. Omdat facades feitelijk door de servicecontainer worden geresolved en beheerd, zijn ze veel gemakkelijker te testen dan gewone statische klassen.

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

test('gebruikersprofiel wordt getoond', function () {
    Cache::shouldReceive('get')
        ->once()
        ->with('user:1')
        ->andReturn(['name' => 'Taylor']);

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

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

Veelgebruikte mockmethoden:

| Methode                   | Beschrijving                                                 |
| ------------------------- | ------------------------------------------------------------ |
| `shouldReceive('method')` | Verwacht dat de methode wordt aangeroepen                    |
| `once()`                  | Verwacht dat hij precies één keer wordt aangeroepen          |
| `times(n)`                | Verwacht dat hij n keer wordt aangeroepen                    |
| `with(args)`              | Verwacht dat hij met specifieke argumenten wordt aangeroepen |
| `andReturn(value)`        | Geeft de opgegeven waarde terug                              |
| `andReturnNull()`         | Geeft null terug                                             |

## Overzicht van de belangrijkste facades

Een overzicht van veelgebruikte facades, hun onderliggende klassen en de bindingnamen in de servicecontainer.

| Facade         | Klasse                                    | 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`       |

## Volgende stappen

<Card title="Contracts" icon="file-contract" href="/nl/contracts">
  Leer het concept van Contracts, de tegenhanger van facades, en wanneer je welke gebruikt.
</Card>


## Related topics

- [Statische analyse van packages (PHPStan / Larastan)](/nl/advanced/package-static-analysis.md)
- [Laravel-packages ontwikkelen](/nl/advanced/package-development.md)
- [Contracts](/nl/contracts.md)
- [Mocking](/nl/mocking.md)
- [Service container](/nl/service-container.md)
