Banco de Dados no Laravel

Banco de Dados no Laravel

O Laravel 4, assim como qualquer programa de computador, só é capaz de lembrar o que o usuário fez enquanto está sendo executado. Por isso precisamos de uma forma de persistir dados inseridos por nossos usuários. Para isso podem ser utilizados arquivos texto ou um sistema de banco de dados. Entre as diversas opções uma das mais comuns é o MySQL. Neste artigo vou mostrar o básico sobre a interação do Laravel com o MySQL.

Para ser bem objetivo e fácil de entender, vamos construir um CMS (Content Management System – Sistema de Gestão de Conteúdo). Neste sistema vamos ser capazes de cadastrar posts e os usuários serão capazes de comentar estes posts. No artigo de hoje vou apenas explicar a parte do banco de dados, criando a tabela e o modelo dos artigos, sem relacionamentos, rotas, controller ou design. Estas coisas ficarão para outros artigos.

Se você não acompanhou o último artigo da série, você pode baixar o código que vamos utilizar no Github. Lembre-se de fazer o composer install  para obter as dependências (mais informações).

Migrações

Vamos começar falando sobre as migrações. Quando trabalhamos com bancos de dados precisamos definir a estrutura do nosso banco de dados através de scripts SQL. Podemos criar estes scripts através de ferramentas como o MySQL Workbench e depois compartilhar com nossos colegas de equipe. Isso cria um problema que é organizar a ordem com que estes scripts devem ser executados. A cada nova instalação do aplicativo, todos os scripts tem que ser executados corretamente.

Para solucionar este problema, foi criado o conceito de migrações. Basicamente as migrações são arquivos PHP que executam os scrips de banco corretamente. No caso do Laravel, cada migração recebe a data/hora do sistema, garantindo assim a ordem dos scripts.

Antes de criarmos nossa migração, você deve instalar a tabela de migrações do Laravel. Esta tabela vai controlar qual migração foi executada. O nome da tabela você pode definir em app/config/database.php na chave migrations.

Nós vamos manter esta tabela mesmo. Para instalar a tabela execute o comando:

Criando uma Migration

Para criar nossa primeira “migration”, vamos usar o artisan. Se você olhar na raiz do nosso projeto, vai encontrar este arquivo. Ele é uma aplicação PHP que executa diversas funções, entre elas criar as migrações.

Este comando vai criar um arquivo de migração no diretório app/database/migrations com o nome 2014_03_09_212855_criar_artigos.php (depende da data/hora que você executar o comando). Abrindo o arquivo, você verá o seguinte conteúdo:

Existem dois métodos nesta classe: up() e down().

  • O método up() será executado quando você fizer esta migração (comando php artisan migrate);
  • O método down() será executado quando você desfizer esta migração (comando php artisan migrate:rollback)

Você também pode usar php artisan migrate:reset para dar um rollback em todas as migrações e php artisan migrate:refresh para dar um rollback e executar todas as migrações novamente. Agora vamos finalizar nossa migração utilizando o Schema Builder.

Schema Builder

Além disso o Laravel possui um Schema Builder (construtor de esquema), que permite definir as tabelas e campos do banco de dados através de um código limpo e claro, utilizando métodos PHP. Primeiro vamos definir como seria a nossa tabela.

Vamos chamar a tabela de artigos, seguindo a nomenclatura que já usamos ao criar a migração. Os campos que precisamos são:

  • id: chave para identificar o artigo
  • titulo: string de título
  • conteudo: texto do artigo
  • created_at: data/hora de criação
  • updated_at: data/hora de atualização

Para este post é apenas isso, mas não se preocupe que mais adiante vamos aprimorar. Agora vamos ver como ficará nosso arquivo de migração 2014_03_09_212855_criar_artigos.php. Depois do código vou explicar cada parte.

No método up() estamos criando nossa tabela. Utilizamos o método Schema::create para informar o Laravel que vamos criar a tabela artigos. Como o segundo parâmetro desta função, passamos uma função com o seguintes comandos:

  • $table->increments(‘id’): este comando define um campo id do tipo inteiro com o auto-increment definido, que também será nossa chave primária. O Laravel faz tudo isto apenas neste comando.
  • $table->string(‘titulo’, 100): agora definimos um campo string (no caso do MySQL será um VARCHAR) com tamanho de 100 caracteres.
  • $table->text(‘conteudo’): campo texto para colocarmos o conteúdo do nosso artigo.
  • $table->timestamps(): este comando cria dois campos data/hora, created_at e updated_at.

Como você deve ter imaginado, existem diversos métodos para criar campos, definir índices, modificar a estrutura da tabela, etc. Eu não vou reproduzir todos os comandos aqui, então você pode se aprofundar vendo a documentação oficial aqui. Ao longo desta série de artigos vamos usar outros métodos e vou tentar explicar sempre que for relevante.

No método down() temos apenas uma linha. Com o método Schema::drop, vamos remover a tabela. Portanto se fizermos a migração vamos criar a tabela. Se quisermos voltar atrás, vamos remover a mesma tabela. Finalizando esta parte, execute o comando:

Você verá a seguinte mensagem de sucesso:

Se você conectar ao banco usando um aplicativo como o MySQL Workbench, verá que a tabela foi criada de acordo com a imagem abaixo:

Tabela artigos

Eloquent ORM

Agora que temos nossa tabela criada, vamos ao nosso modelo. Para isto vamos utilizar o Eloquent ORM. ORM significa Object Relational Model, que em português significa Modelo Objeto Relacional. Basicamente é um mapeamento entre o registro no banco de dados relacional e o objeto definido através de uma classe.

Vou dar um exemplo para explicar melhor. Se você tem no seu código uma classe desse tipo:

Você consegue instanciar este objeto e trabalhar com ele em memória, criando um novo objeto pessoa ou alterando um objeto existente. Mas como você salva isso no banco? Normalmente você veria as pessoas escreverem no PHP uma string com uma query para ser executado no banco:

Não seria melhor termos um método save(), que persistisse os dados no banco para nós? Você pode criar um método assim diretamente na classe. Mas seria necessário replicar o código para todas as tabelas do seu banco de dados. Neste momento que entra o Eloquent ORM. O Eloquent é uma implementação do pattern Active Record. Basicamente é uma classe que possui diversos métodos para interação com o banco, sendo necessário apenas estender a classe Eloquent.

Pronto, este é o nosso model para a tabela artigos. É só isso mesmo. Isso já vai nos permitir trabalhar com nosso banco de dados. Salve este arquivo no diretório app/models/Artigo.php.

É claro que existem uma série de coisas que podem ser necessárias dependendo do caso. Por exemplo, como o Eloquent sabe qual o nome da nossa tabela se não está definido em nenhum lugar? Simplesmente adotando alguns padrões. O nome da tabela será o nome da classe, mais um ‘S’. No nosso caso artigos. Se você precisa definir um nome diferente adicione o parâmetro:

Se você não criou campos created_at e updated_at na sua tabela, deve adicionar mais um parâmetro: protected $timestamps = false;. Desta maneira o Laravel saberá que não deve atualizar estes campos. Nós não precisamos disso pois utilizamos estes campos.

Testando

Nesta última parte do artigo, vamos criar o código necessário para visualizar os posts cadastrados e criar registros. Vamos fazer diretamente nas rotas. As rotas são a primeira coisa que o Laravel vai procurar quando um usuário acessar nosso sistema. Basicamente é a descrição do que vai acontecer quando o usuário acessar uma URL. Essas rotas são definidas no arquivo app/routes.php. Atualmente temos a seguinte rota definida:

Para testar nosso model e a interação com o banco de dados vamos trabalhar diretamente neste arquivo (não faça isso em um aplicativo real!). Adicione as seguintes rotas no final do arquivo:

Na primeira rota estamos buscando todos os acessos feitos na URL /artigos/, buscando os artigos utilizando nosso model Artigo e o método get(), e enviando todos os artigos encontrados para a view artigos. Esta view deve ser ciada dentro de app/views/artigos.php com o conteúdo:

Se você acessar a URL http://desenvolvendo_com_laravel.localhost/artigos (substitua pelo endereço que você usou), você verá o título Artigos, com a mensagem Nenhum artigo encontrado.

Continuando nas outras duas rotas, uma delas é utilizada quando acontece o GET da URL /artigos/inserir/. Neste caso será apenas exibido a view artigos_inserir.php, que contém o form de inserção:

Quando você acessar o endereço http://<seu-localhost>/artigos/inserir, você verá o form de inserção como aparece a seguir:

Inserir artigo

Preenchendo estes campos e clicando em salvar, executará um POST no mesmo endereço. Sabe qual rota será executada? Será a rota Route::post(‘/artigos/inserir’. É exatamente a mesma URL, a diferença está que uma rota funciona com o método get(), atendendo pedidos GET, e a outra usa o método post(), atendendo pedidos POST.

Na rota do POST vamos instanciar um novo objeto do nosso modelo Artigo. Depois vamos atribuir os valores enviados do nosso form. O legal é que o nosso model não tem nenhuma propriedade, mesmo assim conseguimos acessar os campos do banco como se fossem atributos do nosso objeto, sem complicação. Logo depois salvamos o registro no banco de dados com o comando $artigo->save(). Depois do save redirecionamos a página para a lista de artigos, e você poderá ver que agora existe um registro salvo. Executando algumas vezes você terá algo assim:

Lista artigos

Conclusão

Neste artigo vimos como criar uma migração e interagir com o banco de dados através do Eloquent ORM. Eu conto com a paciência de vocês nos pontos onde fui mais superficial. No decorrer dos artigos vamos aprimorar esta aplicação e vou explicando um pouco mais sobre cada coisa. Se eu fosse explicando tudo acabaria com um artigo interminável, pois um assunto conecta com o outro e assim por diante. De qualquer maneira, se você tem alguma dúvida sobre migrações ou sobre o Eloquent ORM, mesmo que não tenha sido comentado neste artigo, pode perguntar que eu farei o meu melhor para responder.

Este post é parte da série Desenvolvendo com Laravel.

18 respostas para “Banco de Dados no Laravel”

  1. Dúvida:
    Já tenho um banco de dados pronto, preciso necessariamente criar as migrations ou posso partir direto para as ORMs?

    Tem alguma ferramenta que gere as ORMs com base no banco de dados?
    Procurei no Google mas nenhuma me pareceu solida o bastante, embora o JeffreyWay tenha me chamado a atenção.

    1. Se você já tem o banco de dados pode ir direto para as ORMs/models.

      Com relação a ferramente para gerar eu não conheço nenhuma que gere a partir de um banco pronto. Os geradores do Jeffrey Way são bem legais para acelerar todo o processo, criando a as migrations, models, controllers, etc usando o generate:resource. Mas ele não vai ler o teu banco e buscar as tabelas, campos e relacionamentos.

      Se você quer apenas montar os models, pode fazer manualmente mesmo pois eles são bem simples de construir. O que acaba levando mais tempo é a construção da lógica e views.

  2. Oscar,

    Neste artigo vai trabalhar com MySQL, mas ele trabalharia com o Oracle? Estou tentando conexao com o yajra/laravel-oci8, mas mesmo seguindo o manual existente tenho ‘ERRO DE CONEXAO’

  3. Bom, esse exemplo você demostrou como utilizar com tabela. Gostaria de saber a respeito de procedures/functions do PostgreSQL como eu deveria trabalhar no laravel de uma forma correta. Gostaria também de saber a opinião de você se o ideal é utilizar querys ou procedures no laravel, pois estou habituado a usar procedures.

    1. Eu ainda não usei PostgreSQL com o Laravel, mas acredito que as chamadas para stored procedures devem seguir o mesmo estilo de chamadas SQL puras, ou seja:

      $result = DB::select('select sua_funcao(?)', array($sua_var));

      Com relação ao que seria a melhor prática, acho que depende :). Se você está acostumado a trabalhar com procedures, se já tem uma prática em planejar o banco com as procedures, recomendo que mantenha elas. Até pela performance melhor.
      Acho que fazer as queries direto no Laravel vale a pena se você tem um ambiente muito dinâmico, sempre alterando tabelas e modificando o sistema. É uma coisa a menos para sua equipe modificar, as alterações ficam todas no Laravel, migrações, queries, etc.

  4. Olha eu tive um problema já no começo com o install do migrate me dava o erro 1045 dizendo que meu usuário e senha estavam errados, ai acabei pesquisando e achei, tal vez sirva de dica pra outras pessoas, mais dentro da pasta app\config\local encontra-se outro arquivo database.php editem ele também já que as vezes ele não muda sozinho.

    Por sinal estou amando teu tutorial muito obrigado pelas ensinanças!!

  5. Olá Oscar!

    Gostaria de compartilhar algumas dificuldades que tive, pois estou usando o laravel 5.2.

    Demorei muito para me achar com as rotas, pois a estrutura no laravel 5.2 é diferente.
    Nesta versão as rotas estão no diretório app/http.
    Algo que me ajudou a entender, foi o comando para listar as rotas.
    php artisan route:list

    Também tive dificuldade como caminho da view e model.
    O que me ajudou a entender, foi criá-las através de linha de comando.
    php artisan make:model artigo

    Parabéns pelos posts, estou iniciando com Laravel e tem ajudado muito!

    1. Valeu pelas dicas Cleber. Eu não tenho conseguido escrever, por isso ainda não atualizei essas questões da versão. Fiz um artigo de migração, mas os posts antigos ainda fazem referência a versão antiga do Laravel.

  6. Bom dia Sr. Oscar Dias!
    estou iniciando estudo de programação e agora com a laravel 5. só que quando entro com a URL ( artigo ) me retorna que a class Artigo não foi encontrada, o formulario estar abrindo direitinho mais quando preencho e executo também traz a mesma resposta. te envio o modelo do model se vc poder me da uma dica te agradeço muito, desde ja obrigado…..

    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class Artigo extends Model
    {
    class Artigo extends Eloquent
    {

    }
    }

    1. Parece que você fez uma declaração de classe dentro da outra… Você deve fazer apenas uma:

      < ?php namespace App; use Illuminate\Database\Eloquent\Model; class Artigo extends Model { // código do model }

      Outra coisa que você tem que cuidar é com o namespace e o nome do arquivo. Se o namespace não estiver correto, ou o nome do arquivo for diferente, também pode dar esse erro.

  7. Ótimo artigo Oscar!

    Me ajudou bastante, precisei realizar alguns ajustes na versão 5.3 do Laravel, mas ainda assim ele foi muito útil e explicativo! 😀

    Muito obrigado! Sucesso!

Deixe uma resposta

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