MVC ¬ framework: usando a arquitetura sem código de terceiros
Muitos desenvolvedores têm a curiosidade de dissecar padrões e arquiteturas de projeto para ver como eles funcionam sem o uso de um framework e consequentemente aprender mais sobre ele, tirando suas próprias vantagens e desvantagens.
Na web, de longe a arquitetura mais usada é a MVC (Model-View-Controller)❤, exemplificada na imagem a seguir:
… 😘 Meio complicado, não? Mas vamos lá, vou explicar esse fluxo em um resumo:
Quando o usuário entra no site uma requisição é lançada para a máquina que hospeda o sistema, lá é papel do controlador receber os dados enviados e fazer alguma ação, usando ou não dados do modelo para complementar essa ação, e por fim criando uma visão de retorno para o usuário, que é retornada em uma resposta.
Nesse artigo vamos criar uma aplicação bem simples em PHP, onde teremos uma agendinha de usuários 🙆, na página inicial podemos apertar para dar um start ▶️ na agenda, na próxima tela podemos criar ➕ novos usuário ou resetar 🔃 toda a aplicação, voltando para o start.
Antes de tudo e deixando tudo mais claro ✡️, não iremos usar nenhuma biblioteca ou framework para qualquer coisa, porém iremos precisar do PHP 7.1 ou superior (por causa de algumas features novas que usei) e do Composer instalado para gerenciar facilmente o autoload das classes, então instale-o para continuar.
Para iniciar, em um diretório novo do seu computador 💻, execute o comando composer init
para criar o arquivo composer.json
que gerencia as dependências e também o autoload do projeto, nas perguntas feitas pelo comando basta ir pressionando aquele Enter maroto 👀.
No final o arquivo json será criado com as informações perguntadas. Antes de iniciar a codificação precisamos criar a estrutura do projeto, definindo quais diretórios usar e qual o objetivo de cada um. Eu defini assim para esse artigo:
- A pasta public é onde vamos guardar os arquivos estáticos e o index.php, que será sempre o arquivo executado inicialmente pelo servidor 🖥.
- No diretório source vamos armazenar o código da aplicação, ali já deixei as camadas (pastas) dos controladores e modelos criadas ✔️.
- Temos também a pasta views, que irá armazenar as interfaces, que são nossa última camada 🔚.
- Por fim temos arquivos do Git, do Composer e o Makefile que irá ajudar a servir a aplicação 💁.
Agora vamos realizar algumas configurações… No arquivo composer.json temos que configurar um autoload, para que ele vincule um diretório de código com um namespace do PHP, permitindo a importação de classes a partir da keyword use. Então crie o objeto autoload no arquivo fazendo o vínculo com o diretório source, deixando-o parecido com esse:
No Makefile, vamos criar um comando chamado serve, assim ao executarmos make serve no diretório do projeto será iniciado um servidor built in do PHP com a aplicação disponível na porta 8008 👍.
Agora sim, vamos ao código 🤗 ! Para realizar o fluxo de uma aplicação (requisição → resposta → requisição ↩️) precisamos de uma classe auxiliadora para manipular a URL do site e tomar caminhos diferentes baseados no link atual.
Essa classe é uma espécie de router, como do Laravel, e poderia ser uma biblioteca a parte, mas para não tirar o foco do assunto principal, vamos construir algo bem simples. Nosso router irá apenas armazenar as rotas definidas, e quando a aplicação se iniciar ele irá verificar a existência da rota enviada por parâmetro, caso exista irá chamar o seu callback e armazenar os parâmetros do método HTTP atual, caso não exista irá exibir uma mensagem de erro.
Crie o arquivo Router.php no diretório source com o código a seguir, leia os comentários e em caso de dúvida deixe nos comentário. Lembrando que se trata de um controlador de fluxo da aplicação, não entrando na arquitetura MVC.
Agora que temos uma classe para controlar o fluxo do sistema, vamos definir quais rotas a aplicação irá ter, essas rotas serão definidas no arquivo de entrada, o public/index.php:
Note que defini algumas rotas usando a classe qua criamos anteriormente, o callback irá retornar a ação de um controlador que iremos criar a seguir 🔜. Nesse caso foram definidas quatro rotas:
- / |GET — irá apresentar a tela inicial do sistema, com o título do site e o botão de start.
- /list | GET — irá mostrar o formulário de criação de um usuário e a lista de usuários já cadastrados.
- /list | POST — irá servir para casdastrar um novo usuário, chamada quando o formulário for submetido.
- /out | GET — irá apagar todos os usuários da aplicação, fazendo resete da mesma.
Agora que já temos todas as páginas do sistema declaradas o fluxo do cliente está definido, o que nos deixa com foco total no MVC 💪. Seguindo o fluxo da imagem 🔝, o próximo arquivo executado é o controlador, onde iremos executar a ação para servir um conteúdo ao cliente.
Mas ao usar alguns framework você já deve ter notado que ao criar um controlador temos que estender alguma classe já pronta, e é essa classe que dá o poder ao controlador 🤔, pois geralmente os controladores possuem muitas funções iguais, como: redirecionar páginas; encaminhar para a camada de visão; etc; Então vamos criar uma super classe 💪 para definir esses métodos genéricos em source/Controller/Controler.php:
Nesse aquivo declarei três métodos que qualquer aplicação fará o uso:
- view — irá receber o nome de uma visão e então pesquisar por ela no diretório da camada view, caso ela exista será importada e poderá fazer uso das variáveis definidas no array
$vars
. - params — irá voltar ao nosso router para pegar os parâmetros do HTTP que ele salvou ao iniciar a aplicação, assim podemos pegar os dados que o cliente nos enviou.
- redirect — irá redirecionar a página de acordo com a rota recebida por parâmetro.
Após a classe abstrata ser criada já temos todo um esqueleto 💀 das principais ações de um controlador, então dentro do diretório Controller podemos criar o AppController para finalmente dar uma ação a cada rota definida anteriormente:
Note que graças ao tratamento feito pelo router e pelo controlador abstrato temos um código bem enxuto e limpo 👍, vamos terminar criando o modelo e as visões que cada método está usando.
Método index
O primeiro método do controlador é bem simples, ele é chamado assim que o cliente acessa o site pela primeira vez, onde deverá mostrar uma tela com o título da aplicação e um link para a próxima página. Então crie a visão com esses elementos no aquivo views/index.php com o código a seguir:
Note que o href do link cita apenas o parâmetro GET da página, que irá indicar ao router qual rota seguir.
Método list
Após clicar no link de iniciar a aplicação, iremos iniciar o modelo User para recuperar a lista de usuários salvos, um modelo é responsável pelas as ações com o banco de dados do sistema (no nosso caso vai usar variáveis de sessão mesmo 😂). No diretório Model, crie a classe User com os seguintes métodos:
Onde:
- O construtor é responsável por iniciar a sessão e criar um array em branco de usuários caso não exista. Seria o mesmo que executar uma query de migration para criar sua tabela no banco.
- O método listAll apenas retorna a lista da sessão. Na real, seria a query de busca na tabela users do banco.
- O método createNew adiciona um novo nome de usuário no array de sessão. Correspondente a uma query de criação.
- O método deteleAll apaga todo o array de usuário e finaliza a sessão. Correspondente a ação de truncar uma tabela.
Voltando ao método list ↩️, após pegar a lista de usuário do modelo, ele retorna a visão list fazendo uso da variável users pega do modelo para mostrar os usuários na tela. O arquivo views/list.php ficará assim:
Além de ter um link de reset e um formulário de criação, apontando respectivamente para as rotas /out e /list. Temos uma lista de usuários, acessamos o array $vars
criado no método view do controlador abstrato para pegar a lista que o AppController passou para a camada de visão.
Método write
Temos a lista de usuários pronta, mas nenhum usuário foi criado, vamos resolver isso! Ou melhor… isso já está pronto rs 🤗, o método write é executado quando o formulário de criação é submetido, nele criamos um novo usuário com o nome recebido pelo router a partir do metódo createNew do modelo. E por fim redirecionamos a tela para a rota list.
Método logout
Como você já está imaginando, já temos isso pronto 🤗. Ao clicar no link de resetar o sistema, a rota /out chama esse método que apenas fala para o modelo apagar tudo que existe, então retorna ao cliente um redirecionamento para a tela inicial.
Com todas essas explicações e complemento de código temos nossa aplicação pronta ✔️, tudo que precisamos fazer é executar dois comandos: o composer dump para que o Composer crie todo o autoload das classes que criamos; e o make serve para iniciarmos um servidor built in com nossa aplicação.
Ao fazer isso e acessar http://localhost:8008 será possível ver a tela inicial da aplicação, com o link para a próxima página e tudo funcionando 🙃.
Isso era nosso objetivo, então bora acabar o artigo? Se você tiver preguiça de seguir os passos, o código escrito aqui está disponível nesse repositório do Github 💾.
Caso tenha alguma crítica, dúvida ou sugestão deixe nos comentários, será um prazer ter um feedback, seja ruim ou bom. Se curtiu dê uma palma 👏 e compartilhe com os amiguinhos 👯.