Introdução

Temma em 3 minutos

Temma é um Model-View-Controller (MVC, em português Modelo-Visão-Controlador), criado para facilitar e acelerar o desenvolvimento de sites.

O framework cuida das requisições recebidas, evitando que você tenha que desenvolver repetidamente as camadas mais básicas das suas aplicações, deixando você livre para se concentrar no "código de negócio", a parte mais importante.

Sua filosofia: convenções simples em vez de configuração.

  • Nenhuma rota a declarar: por padrão, a URL /articles/show/2 chama o método show(2) do controlador Articles.
  • Nenhuma consulta SQL a escrever nos casos simples: o framework cria sozinho o objeto de acesso à tabela correspondente.
  • Nenhuma visão a conectar: o template associado à ação é interpretado automaticamente; para as APIs, a visão JSON é ativada em uma linha.

O restante desta página demonstra isso em um exemplo completo.


0Com um agente de IA

Se você desenvolve com um agente de programação (Claude Code, Codex, Copilot…), não precisa instalar nada à mão. Basta dar a ele esta frase:

Crie um site usando o Temma (temma.net/go)

O agente lê temma.net/go, um guia de instalação executável: ele verifica os pré-requisitos, cria o projeto, configura o banco de dados e o servidor web, e inicia o site. A partir daí ele conta com os skills de IA do Temma, instalados no projeto, para escrever código conforme as convenções do framework.

O restante desta página continua útil: explica como o Temma funciona e, portanto, o que o agente terá produzido.


1Princípios básicos

Temma facilita o desenvolvimento de sites compostos por URLs como:

http://www.site.com/controller/action/p1/p2/p3

As URLs são divididas em 3 partes:

  • O nome do controlador, um objeto que será instanciado ao receber a requisição.
  • O nome da ação, um método desse objeto que será chamado.
  • Um número variável de parâmetros que esse método poderá utilizar.

O seguinte código será então executado:

Controller::action(p1, p2, p3)

Por padrão, o framework vai gerar uma página interpretando o arquivo de template templates/controller/action.tpl

Do lado do modelo, o Temma pode criar automaticamente um DAO (Data Access Object, objeto de acesso a dados): um objeto que lê e grava na tabela com o nome do controlador, sem SQL a escrever. Para as consultas complexas, você retoma o controle escrevendo o seu próprio DAO.

Obviamente, é possível modificar os comportamentos padrão. Um controlador pode optar por ler dados recebidos via POST em vez de − ou além de − dados recebidos na URL ou como parâmetro GET. Uma ação pode definir um template específico a usar, ou até mesmo definir um tipo de visão completamente diferente (que vai gerar JSON ou XML em vez de HTML, por exemplo).

A página do fluxo de execução detalha tudo o que o Temma faz entre o momento em que recebe a requisição e o momento em que envia a resposta.


2Exemplo de desenvolvimento

Para este exemplo, vamos criar um site bem simples, com duas páginas:

  • /articles/list: exibe a lista de artigos.
  • /articles/show/2: exibe o artigo cujo identificador é 2.

Você pode ler este exemplo sem instalar nada.

Quatro arquivos estão envolvidos, indicados em negrito abaixo. O arquivo de configuração já existe depois da instalação, e vamos preenchê-lo; os outros três são os que vamos escrever:

meu_projeto/
    controllers/
        Articles.php
    etc/
        temma.php
    templates/
        articles/
            list.tpl
            show.tpl

Observe o diretório templates/articles/: o nome dele é o do controlador, e o nome de cada template que ele contém é o de uma ação. É a convenção de nomenclatura mencionada acima.


2.1Configuração

A primeira coisa a fazer é criar o arquivo de configuração do projeto. É o arquivo etc/temma.php.

Consulte a documentação de configuração para conhecer as diferentes opções.

A instalação do Temma fornece arquivos de exemplo, mas aqui está o conteúdo do que vamos usar:

<?php

return [
    'application' => [
        'dataSources' => [
            // configuração do banco de dados
            'db' => 'mysql://user:passwd@localhost/mybase'
        ],
        // configuração do controlador raiz
        'rootController' => 'Articles'
    ],
    // limiar de gravação dos logs
    'loglevels' => 'WARN',
    // variáveis de template importadas automaticamente
    'autoimport' => [
        'siteName' => 'Site de demonstração'
    ]
];
  • Linha 7: Configuração da conexão com o banco de dados. A fonte de dados se chama db, que é o nome procurado por padrão pelo DAO.
  • Linha 10: A diretiva rootController serve para definir o controlador raiz do site, ou seja, aquele que vai responder quando acessarmos o endereço http://www.my-site.com/.
  • Linha 13: Definimos o nível mínimo de erro que será registrado no arquivo log/temma.log.
  • Linha 16: Definimos uma variável de template contendo o nome do site. As variáveis importadas automaticamente são agrupadas sob a variável conf; portanto, esta será lida nos templates escrevendo {$conf.siteName}.

2.2Banco de dados

Antes de mais nada, vamos criar uma tabela no banco de dados. Você precisa executar a seguinte consulta no seu banco:

CREATE TABLE articles (
    id     INT UNSIGNED AUTO_INCREMENT,
    title  TINYTEXT,
    text   MEDIUMTEXT,
    author TINYTEXT,
    PRIMARY KEY (id)
);

Dois detalhes de nomenclatura têm importância aqui, porque é neles que o Temma vai se basear para criar automaticamente o DAO que fará a ligação com essa tabela (como veremos na próxima seção):

  • A tabela se chama articles, como o controlador que vamos escrever.
  • Sua chave primária se chama id.

Essas são as duas convenções padrão do Temma. Elas podem ser alteradas (veja a documentação do DAO genérico), mas respeitá-las permite não ter nada a configurar.

E podemos adicionar dados a ela:

INSERT INTO articles (title, text, author)
VALUES ('Primeiro artigo', 'Texto do primeiro artigo', 'John'),
       ('Segundo artigo',  'Texto do segundo artigo',  'Bob'),
       ('Terceiro artigo', 'Texto do terceiro artigo', 'John');

2.3Controlador

Vamos escrever nosso primeiro controlador. Um controlador é um objeto que recebe conexões e as gerencia para enviar dados de volta.
Controladores têm ações, e cada ação pode receber parâmetros.

Nosso controlador vai se chamar Articles. Em vez de escrevê-lo de uma só vez, vamos começar pelo mínimo necessário: o suficiente para exibir a lista de artigos.

No diretório controllers/ do seu projeto, crie um arquivo chamado Articles.php.

Uma linha merece atenção antes de ler o código: $_temmaAutoDao. Ao declarar esse atributo, pedimos ao Temma que crie automaticamente o DAO que servirá para acessar os dados. Ele será configurado para usar a tabela articles, com base no nome do controlador. Ele estará disponível no atributo $this->_dao do controlador, que poderá usá-lo para consultar o banco de dados sem escrever SQL.

<?php

/** Controlador de gerenciamento de artigos. */
class Articles extends \Temma\Web\Controller {
    /** Informa ao framework que ele deve criar automaticamente o DAO. */
    protected $_temmaAutoDao = true;

    /** Ação que exibe a lista de artigos. */
    public function list() {
        // recuperação da lista de itens no banco de dados
        $articles = $this->_dao->search();

        // a lista é disponibilizada para o template
        $this['articles'] = $articles;
    }
}
  • Linha 4: Controladores devem herdar do objeto \Temma\Web\Controller.
  • Linha 6: O DAO é solicitado. O Temma o cria antes de a ação ser executada.
  • Linha 9: A ação list, que responde à URL http://www.my-site.com/articles/list
  • Linha 11: O método search() do DAO retorna todas as linhas da tabela, na forma de uma lista de arrays associativos cujas chaves são os nomes das colunas:
    [
        ['id' => 1, 'title' => 'Primeiro artigo', 'text' => '...', 'author' => 'John'],
        ['id' => 2, 'title' => 'Segundo artigo',  'text' => '...', 'author' => 'Bob'],
        ['id' => 3, 'title' => 'Terceiro artigo', 'text' => '...', 'author' => 'John'],
    ]
    É essa estrutura que vamos reencontrar no template.
  • Linha 14: Copiamos o valor da variável $articles para a variável de template articles. O template usado será (implicitamente) o arquivo templates/articles/list.tpl.

Isso já basta para a página de lista funcionar. Aqui está agora o controlador completo: acrescentamos a ação show(), que exibe um único artigo, e a ação raiz __invoke(), cujo único papel é receber conexões na raiz do site e redirecioná-las para a lista de artigos.

<?php

/** Controlador de gerenciamento de artigos. */
class Articles extends \Temma\Web\Controller {
    /** Informa ao framework que ele deve criar automaticamente o DAO. */
    protected $_temmaAutoDao = true;

    /** Ação raiz (nenhuma ação explícita). */
    public function __invoke() {
        // redirecionamento para a lista de artigos
        $this->_redirect('/articles/list');
    }

    /** Ação que exibe a lista de artigos. */
    public function list() {
        // recuperação da lista de itens no banco de dados
        $articles = $this->_dao->search();

        // a lista é disponibilizada para o template
        $this['articles'] = $articles;
    }

    /**
     * Ação que exibe o conteúdo completo de um artigo.
     * @param  int  $id  Identificador do artigo.
     */
    public function show(int $id) {
        // recuperação do conteúdo do artigo no banco de dados
        $article = $this->_dao->get($id);

        // verificamos se o item solicitado existe ou não
        if (!$article) {
            // ele não existe, redireciona para a lista
            $this->_redirect('/articles/list');
        } else {
            // ele existe, os dados são enviados para o template
            $this['article'] = $article;
        }
    }
}
  • Linha 9: A ação raiz é executada quando nenhuma ação é solicitada especificamente. Como esse controlador foi definido como o controlador raiz (rootController no arquivo etc/temma.php), esta é, portanto, a ação que será chamada ao acessar a raiz do site.
    • Esta ação responde às duas URLs seguintes:
      http://www.my-site.com/
      http://www.my-site.com/articles
    • Linha 11: O internauta é redirecionado para a página que exibe a lista de artigos.
  • Linha 27: A ação show, que exibe o conteúdo de um artigo cujo identificador é fornecido como parâmetro na URL. O parâmetro $id do método recebe o valor lido na URL, convertido em inteiro.
    • Esta ação responde à URL: http://www.my-site.com/articles/show/2
    • Linha 29: O método get() do DAO recupera uma única linha a partir do seu identificador, e a retorna na forma de um array associativo (ou um valor vazio se ela não existir).
    • Linha 34: Se o artigo não existir, redirecionamos para a lista de artigos.
    • Linha 37: Se o artigo existir, salvamos como uma variável de template. O template usado será (implicitamente) o arquivo templates/articles/show.tpl.

2.4Templates

Temma usa o motor de templates Smarty, que é muito popular e tem uma sintaxe muito fácil de entender.

Para a página que exibe a lista de artigos, vamos criar o arquivo templates/articles/list.tpl:

<html>
<head>
    <title>{$conf.siteName}</title>
</head>
<body>
    <ul>
        {* loop pela lista de artigos *}
        {foreach $articles as $article}

            {* adiciona um link para o artigo *}
            <li>
                <a href="/articles/show/{$article.id}">
                    {$article.title}
                </a>
            </li>

        {/foreach}
    </ul>
</body>
</html>
  • Linha 3: O nome do site é colocado na tag <title>. Ele vem da diretiva autoimport do arquivo de configuração. Ele é escapado, para converter eventuais caracteres especiais em entidades HTML.
  • Linha 8: Loop pelos itens da lista de artigos, aquela que o controlador armazenou na variável de template articles.
  • Linhas 11 a 15: Criação do link para a página de um artigo. Cada $article é um dos arrays associativos retornados pelo DAO; suas colunas são lidas, portanto, escrevendo {$article.id} e {$article.title}. O título do artigo é escapado automaticamente, para converter caracteres especiais em entidades HTML.

Para a página que exibe um artigo, vamos criar o arquivo templates/articles/show.tpl:

<html>
<head>
    <title>{$conf.siteName}</title>
</head>
<body>
    {* exibe o título do artigo *}
    <h1>{$article.title}</h1>

    {* exibe o autor do artigo *}
    <h2>por {$article.author}</h2>

    <p>
        {* exibe o conteúdo do artigo *}
        {$article.text|raw}
    </p>
</body>
</html>
  • Linha 3: O nome do site é colocado na tag <title>, e seus caracteres especiais são escapados automaticamente.
  • Linha 7: O título do artigo é colocado em uma tag H1, e seus caracteres especiais são escapados automaticamente.
  • Linha 10: O nome do autor é colocado em uma tag H2, e seus caracteres especiais são escapados automaticamente.
  • Linha 14: O texto do artigo é colocado em um parágrafo (tag P), e solicitamos explicitamente que seu conteúdo não seja escapado (já é HTML).

2.5Resumo

Veja o que o navegador exibe:

www.my-site.com/articles/list
  • Primeiro artigo
  • Segundo artigo
  • Terceiro artigo
www.my-site.com/articles/show/1
Primeiro artigo
por John
Texto do primeiro artigo

E aqui está a sequência que o Temma seguiu para produzir a página de um artigo:

  1. O internauta solicita /articles/show/2.
  2. O Temma instancia o controlador Articles e cria seu DAO, configurado para a tabela articles.
  3. O Temma chama a ação show(2), que consulta a tabela por meio de $this->_dao e deposita o resultado em uma variável de template.
  4. O Temma interpreta o template templates/articles/show.tpl com essa variável, e devolve o HTML obtido.

Você não escreveu nenhuma consulta SQL, nenhum código de roteamento, nem nenhum código de ligação entre as camadas: apenas os três arquivos do exemplo.

Uma última coisa: basta uma linha para que esse controlador se torne uma API que retorna JSON, graças às visões. O Temma sabe até fazer negociação de conteúdo: o mesmo controlador pode então enviar HTML ou JSON, dependendo do que o cliente solicita.


3Para saber mais