Gacela
Documentation version: 2.7.1
Colour theme

Docs Core concepts

On this page

Facade

The Facade (opens in a new tab) is the entry point of your module. Its public methods expose what the module can do and hide the internal classes, services and wiring.

Start from the caller

Write the call you want consumers to make before you design the implementation. The caller knows the Facade and nothing behind it.

app.phpphp
<?php

declare(strict_types=1);

use App\Comment\CommentFacade;
use Gacela\Framework\Gacela;

require __DIR__ . '/vendor/autoload.php';

Gacela::bootstrap(__DIR__);

$score = (new CommentFacade())->getSpamScore('Lorem ipsum!');

echo "Spam score: {$score}" . PHP_EOL;

View the complete entry point (opens in a new tab).

Define the boundary

Turn the caller's operation into a Facade method. Extend AbstractFacade and delegate the work through getFactory().

src/Comment/CommentFacade.phpphp
<?php

declare(strict_types=1);

namespace App\Comment;

use Gacela\Framework\AbstractFacade;

/**
 * @extends AbstractFacade<CommentFactory>
 */
final class CommentFacade extends AbstractFacade
{
    public function getSpamScore(string $comment): int
    {
        return $this->getFactory()
            ->createSpamChecker()
            ->getSpamScore($comment);
    }
}

View the complete Facade (opens in a new tab). Keep this API small. Add a method because a real caller needs it, not because an internal service exposes it.

Accessing the Facade from controllers and commands

In your infrastructure layer (controllers, CLI commands, etc.) you often can't extend AbstractFacade. Combine ServiceResolverAwareTrait with the #[ServiceMap] attribute, and Gacela resolves the Facade lazily through the Locator singleton. You need no constructor injection.

<?php

use Gacela\Framework\ServiceResolver\ServiceMap;
use Gacela\Framework\ServiceResolverAwareTrait;

#[ServiceMap(method: 'getFacade', className: RunFacade::class)]
final class TestCommand extends Command
{
    use ServiceResolverAwareTrait;

    protected function execute(InputInterface $in, OutputInterface $out): int
    {
        // getDependencies() is a method on RunFacade
        $dependencies = $this->getFacade()->getDependencies($paths);
        // ...
    }
}

Construct a Facade directly when your code owns the entry point, as in the Quickstart. Use #[ServiceMap] when another framework creates the controller or command and constructor injection is not practical.

Service Map is the full reference: repeatable declarations, the @method DocBlock migration path, and resolution behavior.