Basicamente todas as principais linguagens de programação atualmente possuem frameworks ORM (Object Relational Mapping – Mapeamento Objeto Relacional), que auxiliam bastante o desenvolvimento de aplicações (sob o paradigma de orientação a objetos – POO) que persistem em bancos de dados relacionais (como MySQL, Postgre, SQL Server, dentre outros).
A função de um framework ORM é fazer a abstração dos objetos de um banco de dados (tabelas, colunas, relacionamentos, etc…), mapeá-los, e disponibilizá-los de forma legível dentro de um projeto que está sendo desenvolvido em POO.
Como exemplo de frameworks ORMs, temos o Hibernate para Java, o NHibernate para a plataforma .NET e quando a linguagem de programação em questão é o PHP, podemos citar o Doctrine. Esse framework é bastante robusto e fornece uma alta lista de recursos, entretanto a sua curva de aprendizagem é relativamente acentuada.
Sendo assim, o propósito desse artigo é justamente lhes apresentar uma alternativa “boa e barata” (risos) para fazer o mapeamento objeto-relacional do seu projeto php. O Relational (https://github.com/Respect/Relational).
Vale ressaltar que, além de fazer o mapeamento do banco de dados (relacional), os frameworks ORMs também oferecem classes/bibliotecas que tornam os procedimentos básicos de inserção, edição, exclusão e busca extremamente simples.
PS: No meu canal do youtube eu disponibilizei uma playlist com 5 vídeo-aulas onde mostro como utilizar o Relational ORM. Para conferir, acesse: https://www.youtube.com/watch?v=E8LDJFKfMdM&list=PLwQkYMetu0OZ6uza5WTSe5RDZya_r2Gfr
Para os exemplos que vamos expor aqui nesse post, vamos utilizar um banco de dados com as colunas autor (id AUTO INC, nome) e post (id AUTO INC, titulo, conteudo, datapost e autor_id). A própria documentação do framework recomenda que as chaves primárias (PK) das tabelas sejam definidas como “id” e as chaves estrangeiras (FK) sigam o padrão “”tabela_id” (Ex: a chave estrangeira vinda da tabela “autor” se chamará “autor_id“).
A abordagem sobre a instalação/utilização do framework ORM Relational será o seguinte roteiro:
- Instalação via Composer
- Conexão com o banco de dados
- Exemplo de inserção (INSERT)
- Exemplo de busca (SELECT) simples
- Exemplo de edição (UPDATE)
- Exemplo de exclusão (DELETE)
- Exemplo de busca (SELECT) utilizando “JOIN”
Instalação via Composer
Para fazer a instalação do framework Relational, vamos utilizar o gerenciador de pacotes Composer (https://getcomposer.org/). Abra seu terminal de linha de comandos (ou prompt), vá até a pasta raiz do seu projeto e insira o seguinte comando:
composer require respect/relational |
Esse comando vai baixar todos os arquivos do framework e adicioná-los dentro de uma pasta chamada “vendor“, dentro do seu projeto.
Conexão com o banco de dados
Com o framework acoplado ao projeto, agora vamos criar um arquivo (pode ser o index.php) e conectar ao banco de dados.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | require_once('vendor/autoload.php'); use Respect\Relational\Mapper; $mapper = null; try{ $mapper = new Mapper( new PDO('mysql:host=localhost;port=3306; dbname=NOMEBANCO', 'USUARIOBD', 'SENHABD') ); } catch(Exception $e){ echo $e->getMessage(); } |
Na linha 1 eu faço a importação do arquivo “autoload.php” (criado pelo próprio composer). A partir desse arquivo, eu consigo ter acesso a todas as classes disponíveis dentro do Relational framework.
A classe que vai fazer o mapeamento do banco e permitir a execução de procedimentos no banco de dados (inserir, editar, excluir e pesquisar) será a “Respect\Relational\Mapper“.
Dentro do try/catch eu faço a instanciação da conexão com o banco de dados via PDO (no exemplo eu utilizo o MySQL, mas você pode ficar a vontade para usar outro SGBD, inclusive o SQLite). A instância de conexão gerada é atribuída à variável “$mapper” e agora a partir dessa variável conseguiremos trabalhar com o banco de forma extremamente simples.
Exemplo de inserção (INSERT)
Para fazer uma inserção no banco de dados, basta criar um objeto padrão do php (stdClass) e posteriormente passá-la como parâmetro para a variável $mapper. Os atributos desse objeto devem ser as colunas da tabela referente no banco de dados. Por exemplo, para o “autor“, vamos “setar” o atributo “nome” (não preciso definir o “id” na hora de inserir, pois ele está definido como auto increment). Veja:
17 18 19 20 21 22 23 24 25 26 27 28 | //Criar um objeto do tipo stdClass //"autor" -> "id" (autoinc), "nome" $autor = new stdClass; $autor->nome = "Joseph"; //"persist" salva as informações na memória $mapper->autor->persist($autor); //salvar de forma permanente do BD $mapper->flush(); echo 'Autor de ID #' . $autor->id . "salvo com sucesso!"; |
Após definir os valores dentro do objeto “$autor“, eu passo ele como parâmetro para o método “persist” (linha 23), que vai salvar esses dados, por enquanto, apenas na memória. Na linha 26 é executado o método “flush” e esse sim salva os dados no banco de forma permanente. Com esse esquema, é possível que você faça vários procedimentos a nível de memória (usando o “persist“) e depois faça um único “flush” para salvar tudo de uma vez.
Veja agora um exemplo de inserção para a tabela “post”, que tem as colunas “titulo”, “conteudo”, “datapost” e “autor_id” (o autor de nome “Joseph“, salvo no exemplo anterior ficou definido com o id = 1. Logo, vamos usá-lo para salvar o “post“).
29 30 31 32 33 34 35 36 37 38 39 | $post = new stdClass; $post->titulo = "Sexto post"; $post->conteudo = "Conteúdo do sexto post"; $post->datapost = date('Y-m-d H:i:s'); //pega a data e hora atuais $post->autor_id = 1; //autor criado no exemplo anterior $mapper->post->persist($post); //salva na memória $mapper->flush(); //salva no banco de dados echo 'Post #' . $post->id . ' publicado com sucesso!'; |
Exemplo de busca (SELECT) simples
Da mesma forma que temos métodos para inserir, temos também métodos para buscar dados salvos no banco. Vejamos um exemplo de como buscar todos os autores cadastrados no banco:
1 2 3 4 5 6 | echo '<h2>Listando todos os autores</h2>'; $autores = $mapper->autor->fetchAll(); //retorna uma lista com todos os autores foreach ($autores as $autor){ echo 'ID: ' . $autor->id . '<br />'; echo 'Nome: ' . $autor->nome . '<br /><br />'; } |
O método “fetchAll” vai fazer uma busca de todos os autores cadastrados no banco. No exemplo, ele retorna uma lista (array) de objetos para a variável “$autores“. Cada posição desse array, tem um objeto (stdClass) com os atributos “id” e “nome” (que são as colunas da tabela “autor”).
Para fazer uma busca específica de um “autor” pelo seu “id”, podemos utilizar o método “fetch“.
1 2 3 4 | echo '<h2>Buscando o autor de ID = 3</h2>'; $autor = $mapper->autor[3]->fetch(); //busca o autor com id=3 echo 'ID: ' . $autor->id . '<br />'; echo 'Nome: ' . $autor->nome . '<br /><br />'; |
Para fazer a busca pelo “id” (PK), passamos no índice do atributo o valor desse “id“.
Para fazer uma busca e usar como condição uma outra coluna da tabela, passe um array onde o índice da posição é o nome da coluna e o valor é o parâmetro a ser buscado. Exemplo:
1 2 3 4 | echo '<h2>Buscando o autor de nome = Joseph</h2>'; $autor = $mapper->autor(['nome' => 'Joseph'])->fetch(); echo 'ID: ' . $autor->id . '<br />'; echo 'Nome: ' . $autor->nome . '<br /><br />'; |
Nesse caso, ele vai retornar o primeiro autor encontrado onde o “nome” = “Joseph”. Caso você precise de todos os autores com esse nome, substitua o método “fetch” por “fetchAll“.
Exemplo de edição (UPDATE)
Para editar um registro, antes precisamos buscá-lo no banco. Por exemplo, vamos supor que precisamos editar as informações do post que tem o “id” = 6.
1 2 3 4 5 6 | $post = $mapper->post[6]->fetch(); //busca o "post" de id = 6 //Quero alterar o "conteudo" e o "autor_id" $post->conteudo = 'Esse é o novo conteúdo do sexto post'; $post->autor_id = 2; $mapper->post->persist($post); //salva na memoria $mapper->flush(); //salva no BD. |
No exemplo acima, eu faço a busca e carrego todos os dados do “post” de “id=6” para dentro da variável “$post“. Substituo os atributos “conteudo” e “autor_id” pelos novos valores e daí passo a variável novamente para que o “$mapper” faça o “update” no banco de dados.
Exemplo de exclusão (DELETE)
Para fazer a exclusão de um registro, também precisamos antes recuperá-lo do banco. No exemplo a seguir, vamos fazer a exclusão do “post” que tem o “id=4“.
1 2 3 4 5 6 7 | //remover um registro da tabela "post". //primeiro, busca o registro a ser removido $post = $mapper->post[4]->fetch(); echo 'Excluindo post #' . $post->id . ' ('. $post->titulo .')'; $mapper->post->remove($post); //salvo na memoria $mapper->flush(); //executa o DELETE no BD. |
Exemplo de busca (SELECT) utilizando “JOIN”
Assim com é muito simples inserir, editar, excluir registros em um banco de dados relacional utilizando o Relational, o mesmo acontece quando precisamos fazer uma busca com “joins” em 2 ou N tabelas.
Por exemplo, para buscar em nosso banco todos os “posts” e seus respectivos “autores”. Nesse caso, devemos informar primeiro a tabela que “recebe” a FK (tabela “post“, que recebe o “autor_id“), e depois a tabela que fornece a FK (tabela “autor“).
1 2 3 4 | $rsPostAutor = $mapper->post->autor->fetchAll(); //faz um JOIN entre "post" e "autor" foreach ($rsPostAutor as $reg){ echo $reg->titulo . '(' . $reg->autor_id->nome . ') <br /><br />'; } |
Cada registro retornado será convertido para um objeto “stdClass“. Esse objeto terá todas as informações do “post” e dentro do atributo “autor_id” desse objeto, terá um outro objeto que é justamente as informações do autor (“id” e “nome“).
É possível também inserir condições em consultas com JOINS (em ambas as tabelas). Veja alguns exemplos:
1 2 3 4 5 6 7 8 9 10 11 | //buscar somente as informações do post "1" $rsPost1 = $mapper->post[1]->autor->fetch(); //buscar todos os posts do autor "3" $rsAutor3 = $mapper->post->autor[3]->fetchAll(); //Ex: Buscar os posts do autor "nome" = "Adam" $rsAutorAdam = $mapper->post->autor(["nome" => "Adam"])->fetchAll(); //Utilizando o operador LIKE $rsLike = $mapper->post(['titulo LIKE' => '%Sexto%'])->autor->fetchAll(); |
Para concluir, vejam como é fácil porém eficiente a adoção do framework “Relational” ORM para projetos em php. Ele fornece uma solução leve e segura para a manipulação de dados no banco e a busca dos mesmos. Utilizando-o, não precisamos nos preocupar em criar “querys” de inserção, edição, exclusão, busca e etc. pois os métodos para essas atividades já estão disponíveis. Sendo assim, podemos nos preocupar apenas com as regras de negócio do nosso projeto e consequentemente o seu desenvolvimento se torna mais ágil.
Espero que tenham gostado desse conteúdo e qualquer dúvida deixe seu comentário.
Abs!