Construindo um simples framework MVC com PHP.
Neste artigo aprenderemos a construir um padrão de apresentação web sem uso de frameworks.
Código completo: https://github.com/JardelGoncalves/simple-framework-mvc-php
Motivação
A principal vantagem de usar o padrão MVC (acrônimo para Model View Controller) é a separação das responsabilidades que você tem entre as camadas. Cada camada possui sua responsabilidade referente a uma parte do trabalho da sua aplicação. Outra vantagem é a facilidade nas manutenções posteriores da sua aplicação, pois em aplicações onde apenas um arquivo “faz tudo” a manutenção se torna uma tarefa complicada e cara.
Requisitos
- PHP 7.2 (e o drive pgsql)
- PostgreSQL
Criando o Banco de dados
Para que nossa aplicação funcione corretamente, devemos criar nosso banco de dados. Acesse o PostgreSQL via pgAdmin ou terminal, crie um database com o nome mvc_db
e com a seguinte tabela:
CREATE TABLE users (
id SERIAL,
name VARCHAR(100)
);
A aplicação
Com o nosso framework, iremos desenvolver uma simples aplicação que lista todos os usuários no banco de dados PostgreSQL e buscar o usuário por ID.
A aplicação é extremamente simples, porém o foco está na construção do framework que pode ser utilizado em outras aplicações mais complexas.
Para iniciar o projeto, podemos criar uma pasta/diretório em sua máquina com o nome do seu projeto. Neste artigo chamaremos de simple-mvc
e criaremos a seguinte estrutura de diretório.
simple-mvc
├── Application/
│ ├── controllers/
│ │ ├── Home.php
│ │ └── User.php
│ ├── core/
│ │ ├── App.php
│ │ ├── Controller.php
│ │ └── Database.php
│ ├── models/
│ │ └── Users.php
│ ├── views/
│ │ ├── home/
│ │ │ └── index.php
│ │ └── user/
│ │ ├── index.php
│ │ └── show.php
│ ├── .htaccess
│ └── autoload.php
│
└── public/
├── assets/
│ ├── css/
│ │ └── bootstrap.min.css
│ ├── img/
│ │ └── erro.png
│ └── js/
│ ├── bootstrap.min.js
│ └── jquery.slim.min.js
├── .htaccess
└── index.php
O código fonte do nosso framework ficará em simple-mvc/Application/
. Quando o usuário acessar nossa aplicação, o diretório raiz será simple-mvc/public
. A baixo, explicaremos a responsabilidade de cada diretório e arquivo em simple-mvc/Application
.
- controllers/ → Este diretório armazenará todos os controladores da aplicação que recebe os dados informados pelo usuário e decide o que fazer com eles e cada método deve realizar uma ação ou chamar
view
. Além disso, toda classe criada herda os métodos da classeController
do arquivo armazenado emApplication/core/Controller.php
que será discutido em breve. - core/ → Neste diretório será armazenado três arquivos:
App.php
que é responsavel por tratar a URL decidindo qual controlador e qual método deve ser executado;Controller.php
responsável por chamar omodel
,view
epageNotFound
que são herdados para as classes no diretórioApplication/controllers
; E por último, o arquivoDatabase.php
que armazena a conexão com o banco de dados. - models/ → Aqui fica a lógica das suas entidades, no nosso caso usaremos classes que irá interagir com o banco de dados e fornecer tais dados para as
views
. - views/ → As
views
serão responsável por interagir com o usuário. Uma das suas principais características é que cadaview
sabe como exibir ummodel
. - .htaccess → Neste arquivo, apenas negaremos a navegação no diretório com a opção
Options -Indexes
. - autoload.php → Neste arquivo, carregaremos de forma automática todas as classes no diretório
Application/
.
Sem mais delongas, vamos para o código 🙂.
Navegando pelo código
O primeiro arquivo e um dos mais importante é Application/core/App.php
que tem a responsabilidade de obter a URL, dividi-la por /
e obtendo um array. O primeiro índice deste array contém o controller
que iremos instanciar; O segundo índice contém o método que iremos chamar do controller
que instanciamos e o restante são considerados como parâmetros do método. Abaixo você pode analisar o código:
Outro arquivo importante, é Application/core/Controller
que fornece para as classes filhas (as classes em Application/controllers/*
) os métodos para instanciar um model
dinâmicamente, exibir uma determinada view
passando para a mesma os dados em um array que podem ser acessado pela variável $data
. Em casos de métodos ou controladores não encontrados (informado pelo usuário) é chamado o método pageNotFound
fornecido por essa classe. Abaixo está o código da mesma:
Como citado anteriormente, usaremos o PostgreSQL como banco de dados e abaixo é apresentado a classe de conexão com o banco de dados presente em Application/core/Database.php
:
Em Application/models
criaremos um model que chamaremos de Users.php
contendo apenas métodos estáticos e que interagem com o banco de dados, sendo um método que retorna todos os usuários na base de dados e o outro retorna apenas um usuário que possui um determinado id
. Veja o código deste arquivo abaixo:
O prómixo arquivo é Application/controllers/Home.php
que simplesmente herda de Controller
todos os métodos. Na classe Home
podem ser criados métodos que se responsabilize por uma determinada ação/processamento que inclui chamar uma determinada view (interface que interagem o usuário). No caso de Home
existe o método index
que é chamado toda vez em que o usuário informa na URL por exemplo http://meusite.com/<controller>/index
substituindo o valor <controller>
por exemplo por home
ou quando é acessado http://meusite.com/<controller>/
e no caso de home
, por padrão pode ser chamado quando for acessado a URL http://meusite.com
(exemplo). Veja o código desta classe abaixo:
Normalmente um controller se responsabiliza por um model. No nosso caso, temos o model Users
e o controlador que se responsabiliza pelo mesmo é User
que pode ser encontrado em Application/controllers/User.php
que possui dois métodos:
- index() → Que é chamado toda vez que a URL
http://<ip-ou-domino>/user/index
ouhttp://<ip-ou-domino>/user/
é acessada e é retornado para a view (Application/views/user/index.php
) todos os usuários no banco de dados em uma variável$data
que na verdade é um array associativo. - show() → É chamado quando o usuário acessa
http://<ip-ou-domino>/user/show/<id>
, caso não seja informado um ID é retornado a página de erro.
Veja o código da classe abaixo:
Com práticamente todas as classes criadas, devemos criar apenas os arquivos da views
e para não deixar mais longo (porque já está! 😅) apresentaremos apenas a view Application/views/user/show.php
e as demais views, os arquivos .htaccess
e arquivos estáticos (css, imagens e js) você pode acessar o link do repositório que está no inicio deste artigo.
Como citado anteriormente, no arquivo Application/core/Controller.php
o método view()
recebe dois argumentos, o primeiro é a view que neste caso é a Application/views/user/show.php
usaremos apenas o caminho após o diretório views/
ou seja, apenas user/show
sem a extensão .php
e o segundo argumento é os dados que serão usados na view e que no caso será o usuário que possui um determinado id.
Esses dados são passados para em um array associativo com a chave 'user'
, você pode observar essas informações no controlador User
citado anteriormente. É ideal entrar em detalhes deste método, pois na view usaremos uma variável (array) $data['user']
, todo e qualquer dado que for passado no array da view ele pode ser obtido através da variável $data
com a chave informada.
Como o método do model Users
retorna um array, nós podemos acessar os dados deste array ($data['user']
) com um foreach
como podemos observar no código da view user/show
abaixo:
O próximo arquivo que fará todas essas classes funcionar, é o autoload.php
encontrado na raiz do diretório Application
. A sua principal responsabilidade é carregar de forma automática as classes utilizando SPL (Standard PHP Library). Abaixo podemos observar seu código:
Está quasse tudo pronto!
Para finalizar e ser possivel testar nosso simples framework MVC, precisamos criar um arquivo index.php
na raiz do diretório public
. Toda vez que o usuário acessar uma rota em nossa aplicação este arquivo será responsável por fazer toda a aplicação funcionar.
Este arquivo é bem simples, contém TAGs html que serão tudo aquilo em comum entre as views, ou seja, o cabeçalho e o rodapé da página, e no centro deste arquivo (que seria a parte do conteudo de cada view que difere entre elas) incialmente incluimos o nosso autoload.php
e instanciamos um objeto App
, ele é o principal arquivo do nosso framework e que faz toda a lógica da URL, chamada dos métodos, dos controladores e etc...
Quase lá!
Caso você queria testar no Apache, lembre-se apenas de habilitar o módulo de reescrita. Porém, utilizaremos o servidor interno do PHP para testar. Na raiz do seu projeto (no meu caso, simple-mvc
) digite o seguinte comando:
php -S localhost:8080 -t public/
Feito isso, podemos testar!
Testando
Primeiro teste que iremos fazer é acessar a raiz do nosso site, ou seja, http://localhost:8080
. Ao acessar é exibido a seguinte página:
No segundo teste, vamos acessar http://localhost:8080/user/
. Neste caso ele chamará o método index()
do controlador User
que retornará uma página listando todos os usuários contidos no banco de dados. Veja:
E por último, acessaremos http://localhost:8080/user/show/<id>
informando um id
que no caso será o 2 e deve retornar uma view contendo apenas um usuário com aquele determinado id
.
É isso galera! Espero ter ajudado.
Abraços ♡