Gacela
Documentation version: 1.21.0
Colour theme

Docs 1.21.0 Core concepts

On this page

Facade

The Facade (opens in a new tab) is the entry point of your module. It exposes what the module can do through a clean, public API while hiding the internal classes, services, and wiring behind simple method calls.

Defining a Facade

Extend AbstractFacade and use getFactory() to access the module's internal services.

Full code snippet: gacela-example/comment-spam-score/facade (opens in a new tab)

<?php # src/Comment/CommentFacade.php

namespace App\Comment;

use Gacela\Framework\AbstractFacade;

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

Using the Facade

Instantiate the Facade and call its methods. No need to know about the Factory, services, or config behind it.

Full code snippet: gacela-example/comment-spam-score/entry-point (opens in a new tab)

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

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

Gacela::bootstrap(__DIR__);

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

echo sprintf('Spam Score: %d', $score) . PHP_EOL;

Accessing the Facade from controllers and commands

In your infrastructure layer (controllers, CLI commands, etc.) you often can't extend AbstractFacade. Use ServiceResolverAwareTrait together with the #[ServiceMap] attribute to let Gacela resolve the Facade lazily through the Locator singleton. No constructor injection needed.

<?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);
        // ...
    }
}

#[ServiceMap] is repeatable. Declare as many resolvable services as the class needs. Full reference: Service Map.

Alternative: DocBlock @method

Still fully supported; useful on PHP versions where attributes are awkward, or when migrating a legacy code base.

<?php

use Gacela\Framework\ServiceResolverAwareTrait;

/**
 * @method RunFacade getFacade()
 */
final class TestCommand extends Command
{
    use ServiceResolverAwareTrait;

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

Why not simply instantiate the Facade?

Instantiating the Facade would be another alternative, but using ServiceResolverAwareTrait Gacela will use the Locator singleton to avoid duplicating the creation of the same Facade multiple times.

How does this work?

The ServiceResolverAwareTrait resolves at runtime the type from #[ServiceMap] (or the DocBlock @method), so this trait is not limited to the Facade. You can use it to lazily load any Gacela-resolvable class without constructor injection. Gacela handles the autoloading of its dependencies.