title: Camada: Kernel description: O coração do framework responsável pelo bootstrap, descoberta de recursos e ciclo de vida do container.
Camada: Kernel¶
O Kernel é o coordenador central do local_middag. Ele faz a ponte operacional entre o ciclo de vida procedimental do Moodle LMS e a arquitetura orientada a objetos (OO) do framework, garantindo que todas as dependências estejam prontas para uso.
O que é¶
É a camada que governa o Bootstrap (inicialização) e o Ciclo de Vida do sistema. Ela descobre quais Extensions estão instaladas, registra seus serviços no Container de Injeção de Dependência (DI) e compila o grafo de objetos que sustenta todo o framework.
No código, o Kernel é acessado através do ponto de entrada global middag::init(), mas suas responsabilidades internas são distribuídas entre carregadores (loaders), fábricas de containers (container_factory) e serviços de extensão (extension_service).
Por que existe¶
Sem um Kernel centralizado:
1. Dificuldade de Descoberta: Seria necessário incluir arquivos PHP manualmente em todos os pontos do Moodle.
2. Order de Carregamento: Não haveria garantia de que um serviço da Extension A estaria disponível para a Extension B.
3. Burocracia de DI: O desenvolvedor teria que instanciar manualmente dezenas de classes (new ...) para cada pequena tarefa.
O Kernel centraliza o conhecimento de "como montar o framework" em um único lugar, permitindo que o restante do código foque em regras de negócio e não em wiring estrutural.
Sequência de Boot¶
O boot ocorre uma única vez por requisição HTTP (ou execução de Cron) e segue quatro fases determinísticas:
sequenceDiagram
participant Facade as middag::init()
participant Kernel as kernel
participant Loader as loaders
participant Extensions as extension_service
participant Container as ContainerBuilder
Facade->>Kernel: init()
Kernel->>Loader: Descoberta (Fase 1)
Loader-->>Container: Registra services, facades e types
Kernel->>Extensions: Boot de Extensions (Fase 2)
Extensions-->>Container: register() e boot() em ordem topological
Kernel->>Container: Compilação (Fase 3)
Container-->>Container: Resolve grafo e congela definições
Kernel->>Container: Injeção Sintética (Fase 4)
Container-->>Kernel: Container pronto
As quatro fases explicadas:¶
- Descoberta: O framework varre os diretórios para localizar Services, Facades geradas e definições de Types de Item.
- Boot de Extensions: O
extension_serviceexecuta os métodosregister()eboot()de cada módulo. A ordem é definida pelas dependências declaradas emREQUIRES. - Compilação: O
ContainerBuilderdo Symfony é compilado e congelado. Após este ponto, nenhuma definição de serviço pode ser alterada. - Injeção Sintética: Objetos que precisam participar do container, mas que foram criados pelo Moodle (como a conexão global de DB), são injetados.
Decisões de design¶
- Container como Motor Oficial: O framework desencoraja o uso de Singletons clássicos (
getInstance()). Se um objeto precisa ser único, ele deve ser registrado comosharedno container. - Isolamento de Falhas: Se o
boot()de uma Extension falhar, o Kernel captura a exceção, loga o erro e permite que o restante do sistema (e o próprio Moodle) continue funcionando. - Configuração via Código: Diferente do Core do Moodle (baseado em arquivos XML e config globais), o Kernel do framework é configurado via código (PHP), permitindo maior flexibilidade e tipagem.
O que não é¶
- Não é um Local de Regra de Negócio: O Kernel não sabe o que é um "Curso" ou uma "Empresa". Ele só sabe como carregar as classes que sabem disso.
- Não é Global Accessor: Embora ele coordene tudo, o Kernel não deve ser usado como um dicionário global de variáveis. Use Injeção de Dependência nos seus componentes.
- Não deve ser instanciado manualmente: O acesso deve ser feito sempre via Facade principal (
middag).
Perspectiva para builders de extensions¶
Ao herdar de local_middag\base\extension, você ganha acesso ao lifecycle coordenado pelo Kernel:
* register(): Use para registrar seus bindings no container. O container ainda não está compilado.
* boot(): Use para resolver serviços e realizar ações que dependem de outras extensions já estarem registradas.
O Kernel garante que, se você declarar REQUIRES = ['outra_ext'], aquela extension terá seu boot concluído antes da sua começar.
Exemplo ilustrativo¶
A regra de ouro do Kernel para criação de objetos:
// ❌ ANTI-PATTERN: Criar manualmente (fora da governança)
$service = new my_service($db, $cache, $logger);
// ❌ ANTI-PATTERN: Usar o Kernel como Service Locator
$service = middag::get(my_service::class); // Evite em classes estruturais
// ✅ CORRETO: Declarar dependência e deixar o Kernel resolver
final class my_controller {
public function __construct(
private my_service $service // O Kernel injeta automaticamente via DI
) {}
}