Pular para o conteúdo principal

Container

O Container é um gerenciador de instâncias introduzido no sistema para organizar dependências de forma inteligente e reutilizável.
Isso permite que o sistema seja mais rápido, mais limpo e mais fácil de manter.

Objetivo
Gerenciar instâncias de classes permitindo injeção de dependência com facilidade.

O container pode fornecer instâncias únicas singleton, múltiplas binding e também forçar novas instâncias com factory.

Antes de usar uma classe através do container, ela precisa ser registrada. Em templates isso normalmente é feito no arquivo features.php, em addons em qualquer arquivos carregado pelo index.php.

Registro:
// classe de exemplo:
class MyClass {
    private PDO $connect;
    public function __construct( PDO $connection ) {
        $this->connect = $connection;
    }
}

// E no registro:
$container = Container::instance();
$container->singleton( 'MyClass', function($c) { 
    return new MyClass( $c->make('Connection') );
});

// Forma abreviada usando arrow function:
$container->singleton( 'MyClass', fn($c) => new MyClass($c->make('Connection')) );

// (Não precisa instanciar Connection, isso já é feito internamente pelo sistema)


// Classe sem argumentos no construtor:
$container->singleton('MyClass', function() {
    return new MyClass;
});

// Classe com mais dependencias:
$container->singleton('TemplateOptions', function($c) {
    return new TemplateOptions(
        $c->make('EmbeddedCodes'), 
        $c->make('DinamicMenu'), 
        $c->make('LatestComments')
    );
});

Uso de Classes já definidas pelo sistema

Muitas classes registradas no container são instanciadas dentro de funções que carregam os arquivos base e dos roteadores, essas variáveis ficam disponíveis para uso no escopo. Acesse: Variáveis de escopo para saber mais.

Dicas de uso dentro de funções:
Se precisar acessar uma classe rapidamente dentro de uma função ou método, você pode evitar o uso de global $var; usando o método call():

function myfunction( $arg ) {
    $MyClass = Container::call('MyClass');
    return $MyClass->my_method( $arg );
}

// O exemplo acima equivale a:
function myfunction( $qty ) {
    $MyClass = Container::instance()->make('MyClass');
    return $MyClass->my_method( $qty );
}

Notas:

  • É recomendado instanciar dependências através do container, principalmente aquelas que realizam consultas ao banco de dados.
  • Evite o uso direto de new em classes registradas no container.
  • Classes de estado isolado (que precisam sempre iniciar um novo estado) não devem ser registradas no container. Nestes casos, utilize new diretamente.
  • Você provavelmente não precisará usar factory() no dia a dia, mas pode ser útil quando necessário sair do singleton.