Tutorial de PHP + MongoDB: do feijão à feijoada!

php-mongodb-tutorial

E aí pessoal, tudo bem?
Aqui quem vos escreve é o Luiz da Umbler, e hoje vou ensinar você, passo-a-passo, sobre como usar PHP com MongoDB, desde a configuração do ambiente até deixar tudo funcionando com um sistema de CRUD bem simples. Fácil, fácil!

Pré-requisitos: para o correto entendimento deste post será necessário que você já saiba programar em PHP, HTML e tenha um mínimo de noção de banco de dados (qualquer um, até MS Access – arrrgggh!).

image02

 Parte 1: Preparando o ambiente

Antes de tudo, vamos aprender a montar o ambiente para conseguir desenvolver usando PHP com MongoDB.

#1 – Servidor PHP

Você vai precisar de um servidor web com suporte à PHP para que nossos testes funcionem. Pode ser na sua máquina mesmo, usando um XAMPP, LAMP, WAMP, etc, ou, se preferir, configure “na unha” seu Apache, Nginx, IIS. Tanto faz, desde que ofereçam suporte a PHP 7, a versão mais atual na data em que escrevo este post.

Não vou entrar em detalhes de como instalar e/ou configurar cada um dos ambientes, então coloquei links para posts na Internet no nome de cada um (acima). Para simplificar, você pode usar alguma empresa de hospedagem de sites, que é o que eu faço, pra não me preocupar com infra.

“Pô Luiz, mas aí você quer que eu gaste com hospedagem só pra ‘brincar’ de PHP com MongoDB?”

Não mesmo!

Recomendo usar os ‘dias grátis’ que várias empresas fornecem. Depois,você pode cancelar sua conta se não quiser continuar com o serviço. Na Umbler mesmo, você ganha R$100 de créditos para hospedar seu site PHP. Dependendo dos recursos que precisar, esses créditos devem durar mais de um ano!

Neste exemplo usarei a hospedagem de sites da Umbler, afinal, eu trabalho lá! XD

#2 – Servidor MongoDB

Você vai precisar da versão mais recente do MongoDB (3.x) para rodar os exemplos deste tutorial.

Caso esteja utilizando uma empresa de hospedagem para rodar os testes e ela não oferecer MongoDB (ainda é um banco incomum nas hospedagens brasileiras), você pode fazer esse tutorial usando o serviço gratuito da mLab (antiga MongoLabs). Nesse plano, você tem 500MB de MongoDB, o que dá e sobra para nossos testes.

Você cria uma conta lá, o banco, cria um usuário para o banco e copia a connection string para usar depois (não vou me estender aqui, o processo é realmente bem simples). Sua connection string deve ser alguma coisa parecida com isso aqui:

mongodb://usuario:senha@servidor.mlab.com:23400/nomeDoBanco

Atenção: não recomendo usar esta arquitetura de “hospedagem + mLab” em “projetos de verdade”. Você só conseguirá fazer testes dessa forma. Para projetos em produção, certifique-se de que sua hospedagem possui suporte a MongoDB ou então use Amazon EC2 com mLab pago, pois você consegue configurar para que os dois fiquem na mesma rede. A própria Umbler, no momento em que escrevo este post, ainda está para lançar seu produto de MongoDB e fornecer um serviço realmente bacana nesse sentido. Fique ligado!

Caso vá rodar o PHP e  MongoDB na sua máquina local, apenas acesse o site do MongoDB e baixe a versão mais recente dele (3.x) para seu sistema operacional. Depois instale e ‘bote’ o servidor para rodar com o comando abaixo (considerando que você tenha instalado ele em C:/):

C:\MongoDB\Server\3.1\bin> mongod –dbpath “C:\MongoDB\data”

Caso queira criar um usuário administrador para seu banco de dados (por padrão ele é ‘aberto’), consulte este tutorial oficial. Para testes eu não me preocuparia com isso no momento, pois pode ser um pouco chato para quem não está acostumado com MongoDB.

Não se preocupe também em criar o schema do banco de dados. Ele será criado dinamicamente mais tarde, conforme a gente for inserindo registros nele. Essa é uma das características mais legais do MongoDB! Pelo menos eu acho… :D

#3 – Driver do MongoDB para PHP

Caso você esteja utilizando uma empresa de hospedagem, descubra se ela possui suporte ao driver ‘mongodb’ (não use o driver ‘mongo’, ele é legado). Se essa informação não consta no seu painel de administração da hospedagem, rode um phpinfo que você descobre rapidinho, como no teste abaixo que fiz na minha hospedagem na Umbler:

image01

Caso esteja rodando no seu PC local, você vai ter que instalar esse driver manualmente. O código abaixo (que eu roubei de algum site na Internet) exemplifica esse processo no Linux:

Primeiro copie e instale o driver na sua máquina:

$ git clone https://github.com/mongodb/mongo-php-driver.git
$ cd mongo-php-driver
$ git submodule sync && git submodule update –init
$ phpize
$ ./configure
$ make
$ sudo make install

Agora adicione a extensão ao seu php.ini:

extension=mongodb.so

Para saber se está tudo funcionando, crie um arquivo mongoteste.php e coloque o seguinte código dentro:

$mongo = new MongoDB\Driver\Manager( ‘sua string de conexão’);

if( $mongo )

    echo “Funcionou!”;

else

    echo “Não funcionou!”;

Troque ‘sua string de conexão’ pela sua string de conexão de verdade (*sick*) e mande executar no seu servidor PHP. Caso esteja rodando local e sem autenticação, use:

mongodb://localhost:27017

Neste exemplo apenas estamos tentando criar um objeto de conexão com o banco de dados. Se a conexão for estabelecida com sucesso, será impresso no navegador a frase ‘Funcionou!’, caso contrário será impresso ‘Não funcionou!’ ou mesmo um erro PHP, dependendo do motivo de não ter funcionado.

O erro mais comum é o servidor estar inacessível (não está rodando) ou a connection string possuir algum erro de digitação. Bom, os erros PHP eu deixo para você resolver, está bem?!

Parte 2: Criando o projeto

Agora que sabemos (eu espero!) que nosso ambiente está pronto e funcionando, vamos começar nosso projeto de exemplo. Uhul!

Em nosso exemplo vamos fazer um cadastro de clientes (nooossa, que original…), pois com ele eu não vou passar vergonha vou conseguir te mostrar um CRUD completo em MongoDB, que é o que vai te dar a base para que consiga continuar aprendendo sozinho depois.

#1 – Inserindo clientes de exemplo

Vamos começar adicionando uma carga de dados em nosso banco, para que tenhamos alguns registros para brincar.

O MongoDB trabalha com o conceito de coleções de documentos e, nesses documentos, teremos campos. É diferente do modelo tradicional de tabelas com linhas e nessas linhas tem as colunas. Pensando bem, agora que escrevi não me parece muito diferente, mas isso não vem ao caso agora…O que queremos é criar uma coleção de clientes (documentos) em nosso banco, no qual adicionaremos uns dois clientes de exemplo.

Para fazer isso, você pode usar alguma ferramenta visual de administração do MongoDB como a Studio 3T (a que eu uso) ou o próprio utilitário de linha de comando do Mongo que vem junto com a instalação do servidor, cujo tutorial oficial você encontra aqui.

Basta inicializar o seu utilitário ‘mongo’, considerando que seu mongo está localhost e sem autenticação:

C:\MongoDB\Server\3.1\bin> mongo

definir que deseja ‘usar’ o banco ‘banco’ (sim, esse é o nome do meu banco):

use banco

e rodar o comando abaixo, para inserir três clientes em uma coleção ‘clientes’:

clienteArray = [{“nome”:”Luiz Júnior”, “profissao”:”Professor”},{“nome”:”Luiz Duarte”, “profissao”:”Blogueiro”}]

db.clientes.insert(clienteArray);

Isso deve funcionar perfeitamente. Na minha máquina funciona…

Note que estamos ‘usando’ um banco que não existe e inserindo um array de objetos JSON em uma coleção do Mongo que também não existe, e ainda por cima sem passar um identificador único em cada objeto cliente. MAS QUE *&%$#! DE BANCO É ESSE!!!

O Mongo é assim mesmo, as coisas vão sendo criadas sozinhas conforme vamos chamando elas e não há nada de errado nisso. Já o identificador único de cada objeto será criado automaticamente com o nome de “_id” e o conteúdo sendo um guid gerado pelo servidor. Se você não está acostumado com este fantástico banco schema-less e orientado a documentos, logo, logo, você se acostuma. ;)

Para testar se seu bulk insert funcionou, basta rodar a seguinte consulta abaixo, dentro do mesmo utilitário mongo que ainda deve estar aberto (ao menos eu não mandei você fechar nada…):

db.clientes.find().pretty()

Você deve receber como retorno um array de objetos JSON com tabulação e espaçamento (cortesia da função ‘pretty’) e o campo _id contendo seu identificador único, conforme comentado antes.

Vamos adiante!

#2 –  Consultando clientes

Agora é que o bicho começa a pegar: vamos criar o nosso script PHP que vai consultar os clientes no banco e listar eles em uma página web!

Para isso, vamos começar criando um arquivo PHP com o nome de listagem.php e o seguinte script PHP dentro, que vou explicar na sequência:

 

<?php

try {

    $mongo = new MongoDB\Driver\Manager( ‘string de conexao’ );
    $query = new MongoDB\Driver\Query([], [‘sort’ => [ ‘nome’ => 1], ‘limit’ => 5]);

    $rows = $mongo->executeQuery(“banco.clientes”, $query);    

    foreach ($rows as $row) {

        echo “$row->nome : $row->profissao\n”;

    }
} catch (MongoDB\Driver\Exception\Exception $e) {
   $filename = basename(__FILE__);

   echo “Erro no arquivo $filename.\n”;

   echo “Exception:”, $e->getMessage(), “\n”;

   echo “Arquivo:”, $e->getFile(), “\n”;

   echo “Linha:”, $e->getLine(), “\n”;    

}

?>

A primeira linha de código é para criar a conexão. Já havíamos visto isso antes, lembra? Apenas coloque a sua string de conexão para que funcione corretamente.

$mongo = new MongoDB\Driver\Manager( ‘string de conexao’ );

A segunda linha de código constrói a query que será realizada no MongoDB. O primeiro parâmetro (‘[]’) são os filtros, nenhum neste caso. Já o segundo parâmetro é um array associativo onde definimos a ordenação (‘sort’) e a quantidade máxima de documentos a serem retornados (‘limit’).

$query = new MongoDB\Driver\Query([], [‘sort’ => [ ‘nome’ => 1], ‘limit’ => 5]);

É na terceira linha que a consulta é de fato executada na conexão anteriormente criada. Note que devemos passar por parâmetro o path da coleção, no formato ‘banco.colecao’ e o objeto de consulta ($query). Isso vai nos retornar um array de linhas ($rows).

$rows = $mongo->executeQuery(“banco.clientes”, $query);

A lógica seguinte é para imprimir cada uma das linhas no formato que quisermos. Como sou preguiçoso estava ocupado, apenas atirei na tela as duas informações de cada cliente (nome e profissão). Você, como pessoa caprichosa que é, tenho certeza que vai criar uma listagem macanuda com Bootstrap e tudo mais, não é mesmo?! #sqn

foreach ($rows as $row) {

    echo “$row->nome : $row->profissao\n”;

}

O tratamento de erros dispensa explicação (embora não seja recomendado em produção, para evitar expor informações do seu banco), vamos mandar ver esse arquivo listagem.php em nosso servidor e ver o que acontece:

image05

Cowabanga!

#3 – Criando clientes

Agora que nossa tela de listagem já está funcionando, vamos criar uma página cadastro.php, inicialmente com o formulário de cadastro dos clientes em HTML:

<html>

<head></head>

<body>

    <form method=”POST” action=”cadastro.php”>

    <p><label for=”txtNome”>Nome: <input type=”text” id=”txtNome” name=”txtNome” /></p>

    <p><label for=”txtProfissao”>Profissão: <input type=”text” id=”txtProfissao” name=”txtProfissao” />     </p>

    <input type=”submit” value=”Salvar” />

    </form>

</body>

</html>

Se acessarmos no navegador, veremos essa maravilha abaixo:

image04

Não vou entrar em detalhes do HTML (ele era um dos conhecimentos essenciais para este post, certo?!), mas atentar apenas ao fato de que nossa form action aponta para essa mesma página cadastro.php. Logo, vamos arregaçar as mangas e programar nosso código PHP nessa mesma página, logo antes da tag <html>, para receber o POST e salvar os dados preenchidos no nosso querido MongoDB:

<?php
if ($_SERVER[‘REQUEST_METHOD’] === ‘POST’) {
try {        $mongo = new MongoDB\Driver\Manager( ‘string de conexao’ );   

    $bulk = new         MongoDB\Driver\BulkWrite;           

    $doc = [‘_id’ => new MongoDB\BSON\ObjectID, ‘nome’ => $_POST[“txtNome”], ‘profissao’ => $_POST[“txtProfissao”]];       

    $bulk->insert($doc);$mongo->executeBulkWrite(‘banco.clientes’, $bulk);
    header(‘Location: listagem.php’);    die();
} catch (MongoDB\Driver\Exception\Exception $e) {
     $filename = basename(__FILE__);        

    echo “Erro no arquivo $filename.\n”;    

    echo “Exception:”, $e->getMessage(), “\n”;    

    echo “Arquivo:”, $e->getFile(), “\n”;

    echo “Linha:”, $e->getLine(), “\n”;    

}
}
?>

Argh, ficou grande, não?!

Não se preocupe, vou explicar tudo direitinho!

Primeiro, vamos verificar se é um POST, pois caso contrário, não há necessidade de executar script algum.

if ($_SERVER[‘REQUEST_METHOD’] === ‘POST’) {

Segundo, vamos fazer conexão com o banco de dados. A essa altura do campeonato, é bem possível que você já tenha pensado em colocar esse código em algum arquivo PHP externo, não é mesmo?!

Terceiro, criei um objeto BulkWrite. Esse objeto é o mesmo para qualquer operação de escrita (inserts, deletes, updates, etc).

$bulk = new MongoDB\Driver\BulkWrite;

Na sequência, criei o documento ($doc, chame de objeto JSON/BSON se sentir mais confortável) que será inserido no banco, usando um array associativo, as variáveis POST que vieram pela submissão do formulário e um “_id”, que é gerado usando um objeto específico do MongoDB.

$doc = [‘_id’ => new MongoDB\BSON\ObjectID, ‘nome’ => $_POST[“txtNome”], ‘profissao’ => $_POST[“txtProfissao”]];

E por fim, adicionamos esse documento ao $bulk (o método insert é para informar documentos a serem salvos, existem ainda os métodos delete e update, para fazer exatamente o que o nome sugere) e executamos ele na coleção especificada.

$bulk->insert($doc);

$mongo->executeBulkWrite(‘banco.clientes’, $bulk);

Ok, eu não citei o código que redireciona de volta para a página de listagem, mas acho que não é necessário, não é mesmo?!

Para testar o cadastro você pode voltar na página de listagem e adicionar um link HTML para a página de cadastro. Se estiver com preguiça (eu já disse como sou preguiçoso?) apenas acesse ela no seu navegador, preencha os campos e veja a mágica acontecer!

image03    image00

#4 – Editando e excluindo clientes

Tem um zilhão de posts na Internet que tratam do fluxo ideal de edição e exclusão de clientes.

Alguns dizem que a edição deve ser feita na mesma tela de cadastro, passando o ID do objeto pela querystring para que os campos possam vir preenchidos.

Também falam que a deleção pode ser feita a partir de um botão na listagem, à direita da última coluna do registro a ser excluído. Quando clicado, ele deve pedir confirmação para então excluir de verdade.

Não vou entrar nesses detalhes, vou me focar aqui nos comandos PHP de edição (update) e de deleção (delete) usando o driver mongodb, que é o que te trouxe até esse artigo. Para tanto, vamos relembrar um trecho de código que usamos na inserção:

$mongo = new MongoDB\Driver\Manager( ‘string de conexao’ );

$bulk = new MongoDB\Driver\BulkWrite;    

$doc = [‘_id’ => new MongoDB\BSON\ObjectID, ‘nome’ => $_POST[“txtNome”], ‘profissao’ => $_POST[“txtProfissao”]];
$bulk->insert($doc);

$mongo->executeBulkWrite(‘banco.clientes’, $bulk);

Agora vamos considerar que temos o seguinte documento em nosso banco de dados e que queremos atualizar ele:

{“_id”:”abc-123-def-456”, “nome”: “Luiz Júnior”, “profissao”:”Professor”}

Note que o _id dele (o identificador único de cada registro) é “abc-123-def-456”.

Agora vamos modificar o código que mostrei anteriormente para que o documento ($doc) seja uma versão atualizada do documento que mostrei logo acima (atenção ao ID, que deve ser idêntico):

$mongo = new MongoDB\Driver\Manager( ‘string de conexao’ );

$bulk = new MongoDB\Driver\BulkWrite;
$filter = [‘_id’ => “abc-123-def-456”];    

$doc = [‘_id’ => “abc-123-def-456”, ‘nome’ => “Luiz Fernando”, ‘profissao’ => “Professor”];
$bulk->update($filter, $doc, [‘multi’ => false, ‘upsert’ => false]);

$mongo->executeBulkWrite(‘banco.clientes’, $bulk);

Atenção às partes em negrito, que são as alterações que fiz para representar a atualização de um cliente, ao invés de inserção. Basicamente foram duas alterações:

  1. o $filter é o filtro a ser utilizado para encontrar o(s) documento(s) que vai(vão) ser afetado(s). Neste caso o _id dá conta do recado.
  2. o $doc é uma cópia do documento original (incluindo _id) mas com o nome alterado (é a atualização que quero fazer). Nesse exemplo eu vou sobrescrever o documento inteiro, embora pudesse aplicar os operadores do Mongo ($set, $inc, etc) pra alterar somente os campos que eu desejasse.
  3. o método usado para adicionar esse comando no $bulk é update ao invés de insert (pois esse documento será atualizado no banco, e não inserido) e ele possui um terceiro parâmetro opcional que são as updateOptions:
    1. multi: se mais de um documento será atualizado
    2. upsert: se o Mongo deve criar esse documento se ele não existir

Agora se quisermos excluir um documento (o mesmo acima, por exemplo), as modificações são bem simples também:

$mongo = new MongoDB\Driver\Manager( ‘string de conexao’ );

$bulk = new MongoDB\Driver\BulkWrite;    

$filter = [‘_id’ => “abc-123-def-456”];
$bulk->delete($filter);

$mongo->executeBulkWrite(‘banco.clientes’, $bulk);

Note que agora só temos o $filter que só contém o _id, porque é a única informação que importa em uma deleção, certo?

E com isso concluímos nosso tutorial de PHP + MongoDB!

Claro, foi uma visão bem superficial sobre as reais capacidades de uso das duas tecnologias em conjunto, mas acredito que tenha sido suficiente para sentir o ‘gostinho’ do potencial que essa combinação pode trazer em seus projetos, não é mesmo?!

Ficou com alguma dúvida? Deixa aí nos comentários ou entre em contato comigo no [luiz at umbler dot com] ou no meu blog pessoal luiztools.com.br. Te juro que respondo todos emails recebidos.

Um abraço e até a próxima!

 


Sobre o autor


Autor convidado:

A imagem pode conter: 1 pessoa

Luiz Duarte

Evangelista tecnológico na empresa Umbler

Diretor na empresa Busca Acelerada e Escritor na empresa LuizTools

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *