O framework PHP por trás do SitioYa

Documentação do Koshkil

Núcleo

Ciclo de vida de uma requisição

Da URL à resposta

  1. .htaccess encaminha a requisição para webroot/index.php.
  2. core/Koshkil.php é incluído: carrega a configuração global e a do domínio, define error_reporting e registra os manipuladores de erros.
  3. new Application(): startup() salva o POST (para Koshkil::old()) e inicializa o cache; em seguida é aberta a conexão com o banco.
  4. Route::parseURI() detecta os plugins ativos, aplica as regras de reescrita e decompõe a URL em plugin, controlador, ação e argumentos.
  5. ActionDispatcher::_invoke() encontra o arquivo do controlador, instancia-o e executa seu ciclo de vida e a ação.
  6. Response::render() escolhe o template de acordo com o código de status (o da ação, error/error404, error/error4xx ou error/error500) e o exibe dentro do layout, ou envia o corpo como está se for JSON ou um arquivo.
// webroot/index.php
require_once('../core/Koshkil.php');
require('../vendor/autoload.php');
Koshkil::Uses('com.Application');

$app = new Application();
$app->run();
$app->done();

Dentro do controlador

Ao ser construído, o controlador cria Request, Response, Session e View, registra-se em Koshkil::$controller e inicializa o idioma. Depois o dispatcher chama startupProcess():

  1. Se $openAccess for false, verifica a sessão com isLoggedIn(). Sem sessão, chama processLogin() e exibe login.tpl. Com sessão, checkPermissions() valida $roles, $rules e $strictRules.
  2. create(), o primeiro hook.
  3. Os hooks de $lifeCycle, por padrão dispatch(), init() e run().
  4. A ação, com os argumentos da URL.
  5. shutdownProcess(), ao final.

Qualquer hook pode interromper o processo:

Retorna Efeito
null (nada) Segue para o próximo passo.
false Interrompe os hooks restantes e não executa a ação.
um Response Essa resposta é usada imediatamente.

A ação só pode retornar null ou um Response; qualquer outro valor lança uma exceção.

Qual hook usar

create() para preparar dependências, init() para carregar dados comuns a todas as ações (é o que fazem SuperController e AdminSuperController) e a ação para o que é específico. Se sobrescrever init(), chame parent::init() primeiro.

Qual template é exibido

Com código 200, o template é a variável template da view, se a ação a definiu; caso contrário, <controlador>/<ação> em minúsculas. ProductosController::ver() exibe productos/ver.tpl, procurado na pasta templates/<templateFolder>/ do tema (front ou admin).

A view não exibe esse template sozinho: passa-o como $template ao layout ($templateFile, normalmente main.tpl), que o inclui com {html_include file="{$template}"}. Veja Views.

Quando a URL não coincide

Situação O que acontece
O controlador não existe e a ação é index (um único segmento dentro de uma pasta) O último segmento é usado como ação do controlador pai: /admin/perfil é resolvido como AdminController::perfil() quando não existe um Admin/PerfilController.
O controlador não existe e a URL tem um único segmento Responde System.DefaultController com código 404.
O controlador não existe e a ação não é index A requisição vai para System.DefaultController com essa mesma ação.
O controlador existe, mas a ação não Executa o index() dele, se existir (código 200); senão, 404.

Warning

Por causa das duas últimas linhas, uma URL inexistente pode acabar exibindo o index() de um controlador com código 200. Se uma ação recebe parâmetros que não reconhece, responda 404 explicitamente com $this->Response->setCode(404).

Erros

ExceptionRenderer registra manipuladores para erros, exceções não capturadas e erros fatais:

  • Warnings e notices são apenas registrados no log.
  • Exceções não capturadas e erros fatais respondem com código 500 e o template error/error500.tpl, que recebe $Response (getCode(), getMessage()) e $lastError (mensagem, arquivo e linha).

Só são considerados os erros incluídos em Error.Reporting, e os logs são gravados em tmp/logs/ quando Debug.Level é maior que 0.