One place for hosting & domains

      Migrations

      How To Use Migrations to Create and Manage Database Tables in Laravel



      Part of the Series:
      How To Build a Links Landing Page in PHP with Laravel and Docker Compose

      Laravel is an open-source PHP framework that provides a set of tools and resources to build modern PHP applications. In this project-based tutorial series, you’ll build a Links Landing Page application with the Laravel framework, using a containerized PHP development environment managed by Docker Compose.

      At the end, you’ll have a one-page website built with Laravel and managed via Artisan commands where you can share relevant links to an audience on social channels and presentations.

      Laravel database migrations allow developers to quickly bootstrap, destroy, and recreate an application’s database, without the need to log into the database console or run any SQL queries.

      In this guide, you’ll create a database migration to set up the table where you’ll save the application links. In order to do that, you’ll use the Artisan command-line tool that comes with Laravel by default. At the end, you will be able to destroy and recreate your database tables as many times as you want, using only artisan commands.

      To get started, first make sure you’re in the application’s root directory and your Docker Compose development environment is up and running:

      • cd ~/landing-laravel
      • docker-compose up -d

      Output

      landing-laravel_app_1 is up-to-date landing-laravel_nginx_1 is up-to-date landing-laravel_db_1 is up-to-date

      Next, create a database migration to set up the links table. Laravel Migrations allow developers to programmatically create, update, and destroy database tables, working as a version control system for your database schema.

      To create a new migration, you can run the make:migration Artisan command and that will bootstrap a new class on your Laravel application, in the database/migrations folder. This class will contain a default boilerplate code.

      Remember to use docker-compose exec app to run the command on the app service container, where PHP is installed:

      • docker-compose exec app php artisan make:migration create_links_table

      Output

      Created Migration: 2020_11_18_165241_create_links_table

      Notice that the migration name is generated based on the current date and time, and the name provided as argument to the make:migration command. For that reason, your migration file name will differ slightly.

      Open the generated migration class using your editor of choice:

      • nano database/migrations/2020_11_18_165241_create_links_table

      Next, update the up method to include the table columns you’ll need to store the app data.

      Replace the current content of your migration class with the following code. The highlighted values are the only lines that need adding, so if you prefer, you can also only copy those highlighted lines and include them into your Schema::create definition:

      database/migrations/2020_10_12_171200_create_links_table.php

      <?php
      
      use IlluminateDatabaseMigrationsMigration;
      use IlluminateDatabaseSchemaBlueprint;
      use IlluminateSupportFacadesSchema;
      
      class CreateLinksTable extends Migration
      {
          /**
           * Run the migrations.
           *
           * @return void
           */
          public function up()
          {
              Schema::create('links', function (Blueprint $table) {
                  $table->id();
                  $table->string('url', 200);
                  $table->text('description');
                  $table->boolean('enabled')->default(true);
                  $table->timestamps();
              });
          }
      
          /**
           * Reverse the migrations.
           *
           * @return void
           */
          public function down()
          {
              Schema::dropIfExists('links');
          }
      }
      

      In addition to the default fields that are included in the table definition that is automatically generated with the Artisan command, you’re including three new fields in this table:

      • url : A string field to save the link URL.
      • description : A text field to save the link description.
      • enabled : A field to store the state of the link, whether it’s enabled or not. The boolean Schema type will generate a tinyint unsigned field to store a value of either 0 of 1.

      Save your migration file when you’re done adding these fields. Next, run the migration with:

      • docker-compose exec app php artisan migrate

      Output

      Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (152.46ms) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (131.12ms) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (101.06ms) Migrating: 2020_11_18_165241_create_links_table Migrated: 2020_11_18_165241_create_links_table (60.20ms)

      You’ll notice that other migrations were also executed along with the create_links_table. That is because the default Laravel installation comes with migrations for users (with a users table and a password_resets table) and for queued jobs (with a failed_jobs table). Because our demo application won’t use these features, it is safe to remove those migrations now; however, you may also opt to leave them in place if you are working on an application of your own and you plan on developing it further. All migration files are located at database/migrations in the app’s root folder.

      For more detailed information on database migrations, please refer to our guide on How To Use Database Migrations and Seeders to Abstract Database Setup in Laravel.

      In the next part of this series, you’ll create a custom Artisan command to list, insert, and delete entries in the app’s links table.



      Source link

      Como usar o Migrations de banco de dados e o Seeders para abstrair a configuração do banco de dados em Laravel


      Migrations [Migrações] e seeders [Propagadores] são utilitários de banco de dados eficazes, fornecidos pela framework do Laravel para PHP, que permite que os desenvolvedores façam a inicialização, destruição e recriação do banco de dados de um aplicativo rapidamente. Esses utilitários ajudam a minimizar problemas de inconsistência de banco de dados que podem surgir com vários desenvolvedores trabalhando no mesmo aplicativo: novos colaboradores precisam apenas executar alguns comandos do artisan para definir o banco de dados em uma nova instalação.

      Neste guia, vamos criar migrations (migrações) e seeders (propagadores) para preencher o banco de dados de um aplicativo de demonstração do Laravel com dados de amostra. No final, você poderá destruir e recriar as tabelas de seu banco de dados quantas vezes quiser, usando apenas comandos do artisan.

      Pré-requisitos

      Para seguir este guia, você vai precisar do seguinte:

      Nota: neste guia, utilizaremos um ambiente de desenvolvimento em contêiner, gerenciado pelo Docker Compose para executar o aplicativo, mas você também pode optar por executar o aplicativo em um servidor LEMP. Para configurar isso, siga nosso guia sobre Como instalar e configurar o Laravel com LEMP no Ubuntu 18.04.

      Passo 1 — Obtendo o aplicativo Demo

      Para começar, iremos buscar o aplicativo de demonstração do Laravel a partir de seu repositório do GitHub. Estamos interessados na ramificação do tutorial-02, que inclui uma Configuração do Docker Compose para executar o aplicativo em contêineres. Neste exemplo, baixaremos o aplicativo para nossa pasta base, mas também é possível usar qualquer diretório de sua escolha:

      • cd ~
      • curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-2.0.1.zip -o travellist.zip

      Como baixamos o código do aplicativo como um arquivo .zip, precisaremos do comando unzip para desempacotá-lo. Se não tiver feito isso recentemente, atualize o índice de pacotes local de sua máquina:

      Depois, instale o pacote unzip:

      Em seguida, descompacte o conteúdo do aplicativo:

      Em seguida, renomeie o diretório descompactado como travellist-demo para facilitar o acesso:

      • mv travellist-laravel-demo-tutorial-2.0.1 travellist-demo

      No próximo passo, vamos criar um arquivo de configuração .env para configurar o aplicativo.

      Passo 2 — Configurando o arquivo .env do aplicativo

      No Laravel, o arquivo .env é usado para configurar as configurações dependentes de ambiente, como credenciais e quaisquer informações que possam variar entre as implantações. Esse arquivo não está incluído no controle de revisão.

      Aviso: o arquivo de configuração de ambiente contém informações confidenciais sobre o seu servidor, incluindo credenciais para o banco de dados e chaves de segurança. Por esse motivo, nunca compartilhe esse arquivo publicamente.

      Os valores contidos no arquivo .env terão precedência sobre os valores definidos nos arquivos de configuração regulares, localizados no diretório config. Cada instalação em um novo ambiente exige um arquivo de ambiente personalizado para definir coisas como as configurações de conexão com o banco de dados, as opções de depuração, o URL do aplicativo, entre outros itens que possam variar, dependendo do ambiente em que o aplicativo esteja funcionando.

      Navegue até o diretório travellist-demo:

      Agora, vamos criar um novo arquivo .env para personalizar as opções de configuração do ambiente de desenvolvimento que estamos preparando. O Laravel vem com um exemplo de arquivo do .env que podemos copiar para criar o nosso:

      Abra este arquivo, usando o nano ou outro editor de texto de sua escolha:

      Esta é a aparência do seu arquivo .env agora:

      .env

      APP_NAME=Travellist
      APP_ENV=dev
      APP_KEY=
      APP_DEBUG=true
      APP_URL=http://localhost:8000
      
      LOG_CHANNEL=stack
      
      DB_CONNECTION=mysql
      DB_HOST=db
      DB_PORT=3306
      DB_DATABASE=travellist
      DB_USERNAME=travellist_user
      DB_PASSWORD=password

      O arquivo .env atual do aplicativo de demonstração travellist contém configurações para usar o ambiente em contêiner que criamos com o Docker Compose na última parte desta série. Você não precisa alterar nenhum desses valores, mas fique à vontade para modificar o DB_DATABASE, o DB_USERNAME e o DB_PASSWORD se quiser, uma vez que eles são puxados automaticamente pelo nosso arquivo docker-compose.yml para configurar o banco de dados de desenvolvimento. Certifique-se apenas de que a variável DB_HOST permaneça inalterada, uma vez que ela faz referência ao nome do nosso serviço de banco de dados dentro do ambiente do Docker Compose.

      Caso faça quaisquer alterações no arquivo, certifique-se de salvar e fechar ele pressionando CTRL + X, Y e, então, ENTER.

      Nota: caso tenha optado por executar o aplicativo em um servidor LEMP, será necessário alterar os valores destacados para refletir as configurações do seu próprio banco de dados, incluindo a variável DB_HOST.

      Agora, usaremos o Composer, uma ferramenta de gerenciamento de dependências do PHP, para instalar as dependências do aplicativo e garantir que possamos executar os comandos do artisan.

      Abra seu ambiente do Docker Compose com o comando a seguir. Isso compilará a imagem do travellist para o serviço do app e extrairá imagens adicionais do Docker – exigidas pelos serviços nginx e db, para criar o ambiente do aplicativo:

      Output

      Creating network "travellist-demo_travellist" with driver "bridge" Building app Step 1/11 : FROM php:7.4-fpm ---> fa37bd6db22a Step 2/11 : ARG user ---> Running in 9259bb2ac034 … Creating travellist-app ... done Creating travellist-nginx ... done Creating travellist-db ... done

      Esta operação pode levar alguns minutos para completar. Assim que o processo terminar, podemos executar o Composer para instalar as dependências do aplicativo.

      Para executar o composer e outros comandos no contêiner de serviço do app, utilizaremos o docker-compose exec. O comando exec permite que executemos qualquer comando de nossa escolha em contêineres gerenciados pelo Docker Compose. Ele usa a seguinte sintaxe: docker-compose exec service_name command.

      Nota: caso tenha optado por usar um servidor LEMP para executar o aplicativo de demonstração, ignore a parte do docker-compose exec app dos comandos listados durante todo este guia. Por exemplo, em vez de executar o seguinte comando como ele está escrito, você apenas executaria:

      Para executar o composer install no contêiner do app, execute:

      • docker-compose exec app composer install

      Output

      Loading composer repositories with package information Installing dependencies (including require-dev) from lock file Package operations: 85 installs, 0 updates, 0 removals - Installing doctrine/inflector (1.3.1): Downloading (100%) - Installing doctrine/lexer (1.2.0): Downloading (100%) - Installing dragonmantank/cron-expression (v2.3.0): Downloading (100%) …

      Quando o Composer terminar de instalar as dependências do aplicativo, você poderá executar os comandos do artisan. Para testar se o aplicativo consegue se conectar ao banco de dados, execute o seguinte comando que limpará quaisquer tabelas pré-existentes:

      • docker-compose exec app php artisan db:wipe

      Esse comando removerá quaisquer tabelas pré-existentes do banco de dados configurado. Se ele foi executado com sucesso e o aplicativo conseguiu se conectar ao banco de dados, você verá um resultado parecido com este:

      Output

      Dropped all tables successfully.

      Agora que você tem as dependências do aplicativo instaladas com o Composer, você pode utilizar a ferramenta artisan para criar migrations e seeders.

      Passo 4 — Criando migrations de banco de dados

      A ferramenta de linha de comando do artisan que vem com o Laravel contém uma série de comandos auxiliares que podem ser usados para gerenciar o aplicativo e inicializar novas classes. Para gerar uma nova classe de migration, podemos usar o comando make:migration como segue:

      • docker-compose exec app php artisan make:migration create_places_table

      O Laravel deduz a operação a ser executada (create), o nome da tabela (places) e se essa migration criará uma nova tabela ou não, com base no nome descritivo fornecido para o comando make:migration.

      Você verá um resultado semelhante a este:

      Output

      Created Migration: 2020_02_03_143622_create_places_table

      Isso gerará um novo arquivo no diretório database/migrations do aplicativo. O carimbo de data/hora no arquivo gerado automaticamente é utilizado pelo Laravel para determinar em qual ordem as migrations devem ser executadas.

      Utilize seu editor de texto preferido para abrir o arquivo migration gerado. Lembre-se de substituir o valor destacado pelo nome de arquivo de migration de sua escolha:

      • nano database/migrations/2020_02_03_143622_create_places_table.php

      O arquivo de migration gerado contém uma classe chamada CreatePlacesTable:

      database/migrations/2020_02_03_143622_create_places_table.php

      <?php
      
      use IlluminateDatabaseMigrationsMigration;
      use IlluminateDatabaseSchemaBlueprint;
      use IlluminateSupportFacadesSchema;
      
      class CreatePlacesTable extends Migration
      {
          /**
           * Run the migrations.
           *
           * @return void
           */
          public function up()
          {
              Schema::create('places', function (Blueprint $table) {
                  $table->bigIncrements('id');
                  $table->timestamps();
              });
          }
      
          /**
           * Reverse the migrations.
           *
           * @return void
           */
          public function down()
          {
              Schema::dropIfExists('places');
          }
      }
      
      

      Essa classe tem dois métodos: up e down. Ambos os métodos contêm o código de inicialização que podem ser estendidos para personalizar o que acontece quando essa migration for executada e também o que acontece quando ela for revertida.

      Vamos modificar o método up, de modo que a tabela places reflita a estrutura que já estamos usando na versão atual do aplicativo:

      • id: campo de chave primária.
      • name: nome do lugar.
      • visited: se este lugar já foi visitado ou não.

      O compilador de esquemas do Laravel expõe métodos para a criação, atualização e exclusão de tabelas em um banco de dados. A classe Blueprint define a estrutura da tabela e ela proporciona vários métodos para abstrair a definição de cada campo da tabela.

      O código gerado automaticamente define um campo de id primário chamado id. O método timestamps cria dois campos de datetime que são atualizados automaticamente pelas classes de banco de dados subjacentes, quando os dados são inseridos ou atualizados dentro dessa tabela. Além disso, precisaremos incluir um campo name e um visited.

      Nosso campo name será do tipo string e nosso campo visited será definido com o tipo boolean. Também vamos definir um valor padrão de 0 para o campo visited, de modo que se nenhum valor for transferido, significa que o lugar ainda não foi visitado. É assim que o método up se parecerá agora:

      database/migrations/2020_02_03_143622_create_places_table.php

      …
          public function up()
          {
              Schema::create('places', function (Blueprint $table) {
                  $table->bigIncrements('id');
                  $table->string('name', 100);
                  $table->boolean('visited')->default(0);
                  $table->timestamps();
              });
          }
      …
      

      Nota: você pode encontrar a lista completa dos tipos de coluna disponíveis na documentação do Laravel.

      Após incluir as duas linhas destacadas em seu próprio script de migration, salve e feche o arquivo.

      Agora, sua migration está pronta para ser executada através do artisan migrate. No entanto, isso criaria apenas uma tabela vazia; também precisamos conseguir inserir dados da amostra para o desenvolvimento e teste. No próximo passo, veremos como fazer isso usando os seeders de banco de dados.

      Passo 5 — Criando os Seeders de banco de dados

      Um seeder é uma classe especial utilizada para gerar e inserir dados de amostra (seeds) em um banco de dados. Essa é uma característica importante em ambientes de desenvolvimento, uma vez que permite que você recrie o aplicativo com um banco de dados novo, usando valores de amostra que, de qualquer forma você teria que inserir manualmente toda vez que o banco de dados fosse recriado.

      Agora, utilizaremos o comando artisan para gerar uma nova classe de seeders para nossa tabela de places chamada PlacesTableSeeder:

      • docker-compose exec app php artisan make:seeder PlacesTableSeeder

      O comando criará um novo arquivo chamado PlacesTableSeeder.php dentro do diretório database/seeds. Abra aquele arquivo usando seu editor de texto preferido:

      • nano database/seeds/PlacesTableSeeder.php

      É assim que o arquivo PlacesTableSeeder.php, gerado automaticamente, se parece:

      database/seeds/PlacesTableSeeder.php

      <?php
      
      use IlluminateDatabaseSeeder;
      
      class PlacesTableSeeder extends Seeder
      {
          /**
           * Run the database seeds.
           *
           * @return void
           */
          public function run()
          {
              //
          }
      }
      
      

      Nossa nova classe de seeder contém um método vazio chamado run. Esse método será chamado quando o comando db:seed do Artisan for executado.

      Precisamos editar o método run para incluir instruções para inserir dados de amostra no banco de dados. Vamos utilizar o compilador de consultas do Laravel para simplificar esse processo.

      O compilador de consultas do Laravel oferece uma interface fluente para as operações de banco de dados como a inserção, atualização e recuperação de dados. Ele também introduz proteções contra ataques de injeção de SQL. O compilador de consulta é exposto pela facade do DB – um proxy estático para as classes de banco de dados subjacentes no contêiner de serviço.

      Para começar, criaremos uma variável de classe estática para reter todos os locais das amostras que desejamos inserir no banco de dados como uma matriz. Isso nos permitirá usar um loop foreach para iterar em todos os valores, inserindo cada um no banco de dados utilizando o compilador de consulta.

      Chamaremos essa variável de $places:

      database/seeds/PlacesTableSeeder.php

      <?php
      
      use IlluminateDatabaseSeeder;
      
      class PlacesTableSeeder extends Seeder
      {
          static $places = [
              'Berlin',
              'Budapest',
              'Cincinnati',
              'Denver',
              'Helsinki',
              'Lisbon',
              'Moscow',
              'Nairobi',
              'Oslo',
              'Rio',
              'Tokyo'
          ];

      Em seguida, precisaremos incluir uma instrução use no topo de nossa classe PlacesTableSeeder para facilitar a referência da facade DB em todo o código:

      database/seeds/PlacesTableSeeder.php

      <?php
      
      use IlluminateDatabaseSeeder;
      use IlluminateSupportFacadesDB;
      
      class PlacesTableSeeder extends Seeder
      …
      

      Agora, podemos iterar através dos valores da matriz $places, usando um loop foreach e inserir cada um deles em nossa tabela places com o compilador de consultas:

      database/seeds/PlacesTableSeeder.php

      …
          public function run()
          {
              foreach (self::$places as $place) {
                  DB::table('places')->insert([
                      'name' => $place,
                      'visited' => rand(0,1) == 1
                  ]);
              }
          }
      
      

      O loop foreach itera através de cada valor da matriz estática $places. Em cada iteração, usamos a facade DB para inserir uma nova linha na tabela places. Definimos o campo name para o nome do lugar que acabamos de obter da matriz $places e definimos o campo visited para um valor aleatório de 0 ou 1.

      É assim que a classe PlacesTableSeeder completa se parecerá após todas as atualizações:

      database/seeds/PlacesTableSeeder.php

      <?php
      
      use IlluminateDatabaseSeeder;
      use IlluminateSupportFacadesDB;
      
      class PlacesTableSeeder extends Seeder
      {
          static $places = [
              'Berlin',
              'Budapest',
              'Cincinnati',
              'Denver',
              'Helsinki',
              'Lisbon',
              'Moscow',
              'Nairobi',
              'Oslo',
              'Rio',
              'Tokyo'
          ];
      
          /**
           * Run the database seeds.
           *
           * @return void
           */
          public function run()
          {
              foreach (self::$places as $place) {
                  DB::table('places')->insert([
                      'name' => $place,
                      'visited' => rand(0,1) == 1
                  ]);
              }
          }
      }
      

      Salve e feche o arquivo quando terminar de fazer essas alterações.

      As classes do seeder não são carregadas automaticamente no aplicativo. Precisamos editar a classe principal, DatabaseSeeder, para incluir uma chamada para o seeder que acabamos de criar.

      Abra o arquivo database/seeds/DatabaseSeeder.php com o nano ou com o seu editor favorito:

      • nano database/seeds/DatabaseSeeder.php

      A classe DatabaseSeeder se parece com qualquer outro seeder: ela se estende a partir da classe Seeder e tem um método run. Atualizaremos esse método para incluir uma chamada para o PlacesTableSeeder.

      Atualize o método run atual, dentro da classe DatabaseSeeder, excluindo a linha comentada e substituindo-a pelo código destacado a seguir:

      database/seeds/DatabaseSeeder.php

      …
          public function run()
          {
              $this->call(PlacesTableSeeder::class);
          }
      ...
      

      É assim que a classe DatabaseSeeder completa se parecerá após a atualização:

      database/seeds/DatabaseSeeder.php

      <?php
      
      use IlluminateDatabaseSeeder;
      
      class DatabaseSeeder extends Seeder
      {
          /**
           * Seed the application's database.
           *
           * @return void
           */
          public function run()
          {
              $this->call(PlacesTableSeeder::class);
          }
      }
      
      
      

      Salve e feche o arquivo quando terminar de atualizar seu conteúdo.

      Agora, terminamos a configuração da migration e de um seeder para nossa tabela places. No próximo passo, veremos como executá-las.

      Passo 6 — Executando as migrations e os seeders do banco de dados

      Antes de prosseguir, precisamos garantir que seu aplicativo esteja em funcionamento. Vamos configurar a chave de criptografia do aplicativo e, depois, acessar o aplicativo a partir de um navegador para testar o servidor Web.

      Para gerar a chave de criptografia que o Laravel exige, utilize o comando artisan key:generate:

      • docker-compose exec app php artisan key:generate

      Assim que a chave tiver sido gerada, você poderá acessar o aplicativo, apontando seu navegador para o nome do host ou endereço IP do servidor na porta 8000:

      http://server_host_or_ip:8000
      

      Você verá uma página como esta:

      Erro do MySQL

      Isso significa que o aplicativo conseguiu conectar-se ao banco de dados, mas que não encontrou uma tabela chamada places. Vamos criar a tabela places agora, utilizando o comando do artisan migrate:

      • docker-compose exec app php artisan migrate

      Você obterá um resultado parecido com este:

      Output

      Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.06 seconds) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (0.06 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.03 seconds) Migrating: 2020_02_10_144134_create_places_table Migrated: 2020_02_10_144134_create_places_table (0.03 seconds)

      Você verá que algumas outras migrations foram executadas junto com a migration create_places_table que configuramos. Essas migrations são geradas automaticamente quando o Laravel é instalado. Embora não estejamos usando essas tabelas adicionais agora, elas serão necessárias no futuro quando expandirmos o aplicativo para ele ter usuários registrados e trabalhos agendados. Por enquanto, deixe-as como estão.

      Neste ponto, nossa tabela ainda está vazia. Precisamos executar o comando db:seed para propagar o banco de dados com nossas amostras de locais:

      • docker-compose exec app php artisan db:seed

      Isso executará nosso seeder e irá inserir os valores da amostra que definimos dentro da nossa classe PlacesTableSeeder. Você verá um resultado semelhante a este:

      Output

      Seeding: PlacesTableSeeder Seeded: PlacesTableSeeder (0.06 seconds) Database seeding completed successfully.

      Agora, recarregue a página do aplicativo no seu navegador. Você verá uma página parecida com esta:

      Demo do aplicativo Laravel

      Sempre que precisar começar do zero, você poderá remover todas as tabelas de banco de dados com:

      • docker-compose exec app php artisan db:wipe

      Output

      Dropped all tables successfully.

      Para executar o aplicativo migrations e propagar as tabelas em um único comando, utilize:

      • docker-compose exec app php artisan migrate --seed

      Output

      Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.06 seconds) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (0.07 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.03 seconds) Migrating: 2020_02_10_144134_create_places_table Migrated: 2020_02_10_144134_create_places_table (0.03 seconds) Seeding: PlacesTableSeeder Seeded: PlacesTableSeeder (0.06 seconds) Database seeding completed successfully.

      Se quiser reverter uma migration, você pode executar:

      • docker-compose exec app php artisan migrate:rollback

      Isso acionará o método down para cada classe de migration dentro da pasta migrations. Normalmente, ele removerá todas as tabelas que foram criadas através das classes de migration, deixando sozinha quaisquer outras tabelas que possam ter sido criadas manualmente. Você verá um resultado como este:

      Output

      Rolling back: 2020_02_10_144134_create_places_table Rolled back: 2020_02_10_144134_create_places_table (0.02 seconds) Rolling back: 2019_08_19_000000_create_failed_jobs_table Rolled back: 2019_08_19_000000_create_failed_jobs_table (0.02 seconds) Rolling back: 2014_10_12_100000_create_password_resets_table Rolled back: 2014_10_12_100000_create_password_resets_table (0.02 seconds) Rolling back: 2014_10_12_000000_create_users_table Rolled back: 2014_10_12_000000_create_users_table (0.02 seconds)

      O comando de reversão é especialmente útil quando estiver fazendo alterações nos modelos do aplicativo e um comando db:wipe não puder ser usado – por exemplo, caso vários sistemas dependerem de um mesmo banco de dados.

      Conclusão

      Neste guia, vimos como usar as migrations e os seeders de banco de dados para facilitar a configuração de bancos de dados para desenvolvimento e teste para um aplicativo Laravel 6.

      Como um passo seguinte, talvez você queira conferir a documentação do Laravel para obter mais informações sobre como usar o compilador de consultas e como usar os Modelos eloquentes para se concentrar ainda mais no esquema do banco de dados do seu aplicativo.



      Source link

      How To Use Database Migrations and Seeders to Abstract Database Setup in Laravel


      Migrations and seeders are powerful database utilities provided by the Laravel PHP framework to allow developers to quickly bootstrap, destroy and recreate an application’s database. These utilities help to minimize database inconsistency problems that can arise with multiple developers working on the same application: new contributors need only to run a couple artisan commands to set the database up on a fresh install.

      In this guide, we’ll create migrations and seeders to populate a Laravel demo application’s database with sample data. At the end, you will be able to destroy and recreate your database tables as many times as you want, using only artisan commands.

      Prerequisites

      In order to follow this guide, you’ll need:

      Note: In this guide, we’ll use a containerized development environment managed by Docker Compose to run the application, but you may also opt to run the application on a LEMP server. To set this up, you can follow our guide on How to Install and Configure Laravel with LEMP on Ubuntu 18.04.

      Step 1 — Obtaining the Demo Application

      To get started, we’ll fetch the demo Laravel application from its GitHub repository. We’re interested in the tutorial-02 branch, which includes a Docker Compose setup to run the application on containers. In this example, we’ll download the application to our home folder, but you can use any directory of your choice:

      • cd ~
      • curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-2.0.1.zip -o travellist.zip

      Because we downloaded the application code as a .zip file, we’ll need the unzip command to unpack it. If you haven’t done so recently, update your machine’s local package index:

      Then install the unzip package:

      Following that, unzip the contents of the application:

      Then rename the unpacked directory to travellist-demo for easier access:

      • mv travellist-laravel-demo-tutorial-2.0.1 travellist-demo

      In the next step, we’ll create a .env configuration file to set up the application.

      Step 2 — Setting Up the Application’s .env File

      In Laravel, a .env file is used to set up environment-dependent configurations, such as credentials and any information that might vary between deployments. This file is not included in revision control.

      Warning: The environment configuration file contains sensitive information about your server, including database credentials and security keys. For that reason, you should never share this file publicly.

      The values contained in the .env file will take precedence over the values set in regular configuration files located in the config directory. Each installation on a new environment requires a tailored environment file to define things such as database connection settings, debug options, and the application URL, among other items that may vary depending on which environment the application is running.

      Navigate to the travellist-demo directory:

      We’ll now create a new .env file to customize the configuration options for the development environment we’re setting up. Laravel comes with an example.env file that we can copy to create our own:

      Open this file using nano or your text editor of choice:

      This is how your .env file looks like now:

      .env

      APP_NAME=Travellist
      APP_ENV=dev
      APP_KEY=
      APP_DEBUG=true
      APP_URL=http://localhost:8000 
      
      LOG_CHANNEL=stack
      
      DB_CONNECTION=mysql
      DB_HOST=db
      DB_PORT=3306
      DB_DATABASE=travellist
      DB_USERNAME=travellist_user
      DB_PASSWORD=password

      The current .env file from the travellist demo application contains settings to use the containerized environment we’ve created with Docker Compose in the last part of this series. You don’t need to change any of these values, but you are free to modify the DB_DATABASE, DB_USERNAME and DB_PASSWORD if you wish, since these are pulled by our docker-compose.yml file automatically to set up the development database. Just make sure the DB_HOST variable remains unchanged, since it references the name of our database service within the Docker Compose environment.

      If you make any changes to the file, make sure to save and close it by pressing CTRL + X, Y, then ENTER.

      Note: If you have opted to run the application on a LEMP server, you’ll need to change the highlighted values to reflect your own database settings, including the DB_HOST variable.

      Step 3 — Installing Application Dependencies with Composer

      We’ll now use Composer, PHP’s dependency management tool, to install the application’s dependencies and make sure we’re able to execute artisan commands.

      Bring up your Docker Compose environment with the following command.
      This will build the travellist image for the app service and pull in the additional Docker images required by the nginx and db services, in order to create the application environment:

      Output

      Creating network "travellist-demo_travellist" with driver "bridge" Building app Step 1/11 : FROM php:7.4-fpm ---> fa37bd6db22a Step 2/11 : ARG user ---> Running in 9259bb2ac034 … Creating travellist-app ... done Creating travellist-nginx ... done Creating travellist-db ... done

      This operation might take a few minutes to complete. Once the process is finished, we can run Composer to install the application’s dependencies.

      To execute composer and other commands in the app service container, we’ll use docker-compose exec. The exec command allows us to execute any command of our choice on containers managed by Docker Compose. It uses the following syntax: docker-compose exec service_name command.

      Note: In case you have opted to use a LEMP server to run the demo application, you should ignore the docker-compose exec app portion of the commands listed throughout this guide. For example, instead of running the following command as it’s written, you would just run:

      To execute composer install in the app container, run:

      • docker-compose exec app composer install

      Output

      Loading composer repositories with package information Installing dependencies (including require-dev) from lock file Package operations: 85 installs, 0 updates, 0 removals - Installing doctrine/inflector (1.3.1): Downloading (100%) - Installing doctrine/lexer (1.2.0): Downloading (100%) - Installing dragonmantank/cron-expression (v2.3.0): Downloading (100%) …

      When Composer is finished installing the application’s dependencies, you’ll be able to execute artisan commands. To test that the application is able to connect to the database, run the following command which will clean up any pre-existing tables:

      • docker-compose exec app php artisan db:wipe

      This command will drop any pre-existing tables on the configured database. If it ran successfully and the application is able to connect to the database, you’ll see output like this:

      Output

      Dropped all tables successfully.

      Now that you have installed the application dependencies with Composer, you can use the artisan tool to create migrations and seeders.

      Step 4 — Creating Database Migrations

      The artisan command line tool that ships with Laravel contains a series of helper commands that can be used to manage the application and bootstrap new classes. To generate a new migration class, we can use the make:migration command as follows:

      • docker-compose exec app php artisan make:migration create_places_table

      Laravel infers the operation to be executed (create), the name of the table (places), and whether this migration will create a new table or not, based on the descriptive name provided to the make:migration command.

      You’ll see output similar to this:

      Output

      Created Migration: 2020_02_03_143622_create_places_table

      This will generate a new file in the application’s database/migrations directory. The timestamp included in the auto-generated file is used by Laravel to determine in which order migrations should be executed.

      Use your text editor of choice to open the generated migration file. Remember to replace the highlighted value with your own migration file name:

      • nano database/migrations/2020_02_03_143622_create_places_table.php

      The generated migration file contains a class called CreatePlacesTable:

      database/migrations/2020_02_03_143622_create_places_table.php

      <?php
      
      use IlluminateDatabaseMigrationsMigration;
      use IlluminateDatabaseSchemaBlueprint;
      use IlluminateSupportFacadesSchema;
      
      class CreatePlacesTable extends Migration
      {
          /**
           * Run the migrations.
           *
           * @return void
           */
          public function up()
          {
              Schema::create('places', function (Blueprint $table) {
                  $table->bigIncrements('id');
                  $table->timestamps();
              });
          }
      
          /**
           * Reverse the migrations.
           *
           * @return void
           */
          public function down()
          {
              Schema::dropIfExists('places');
          }
      }
      
      

      This class has two methods: up and down. Both methods contain bootstrap code that you can extend to customize what happens when that migration is executed and also what happens when it is rolled back.

      We’ll modify the up method so that the places table reflects the structure we’re already using in the current application’s version:

      • id: primary key field.
      • name: name of the place.
      • visited: whether or not this place was already visited.

      The Laravel schema builder exposes methods for creating, updating and deleting tables in a database. The Blueprint class defines the table’s structure and it provides several methods to abstract the definition of each table field.

      The auto-generated code sets up a primary id field called id. The timestamps method creates two datetime fields that are automatically updated by the underlying database classes when data is inserted or updated within that table. In addition to these, we’ll need to include a name and a visited field.

      Our name field will be of type string, and our visited field will be set with the boolean type. We’ll also set a default value of 0 for the visited field, so that if no value is passed, it means the place was not visited yet. This is how the up method will look like now:

      database/migrations/2020_02_03_143622_create_places_table.php

      …
          public function up()
          {
              Schema::create('places', function (Blueprint $table) {
                  $table->bigIncrements('id');
                  $table->string('name', 100);
                  $table->boolean('visited')->default(0);
                  $table->timestamps();
              });
          }
      …
      

      Note: You can find the full list of available column types in the Laravel documentation.

      After including the two highlighted lines on your own migration script, save and close the file.

      Your migration is now ready to be executed via artisan migrate. However, that would only create an empty table; we also need to be able to insert sample data for development and testing. In the next step, we’ll see how to do that using database seeders.

      Step 5 — Creating Database Seeders

      A seeder is a special class used to generate and insert sample data (seeds) in a database. This is an important feature in development environments, since it allows you to recreate the application with a fresh database, using sample values that you’d otherwise have to manually insert each time the database is recreated.

      We’ll now use the artisan command to generate a new seeder class for our places table called PlacesTableSeeder:

      • docker-compose exec app php artisan make:seeder PlacesTableSeeder

      The command will create a new file called PlacesTableSeeder.php inside the database/seeds directory. Open that file using your text editor of choice:

      • nano database/seeds/PlacesTableSeeder.php

      This is what the auto-generated PlacesTableSeeder.php file looks like:

      database/seeds/PlacesTableSeeder.php

      <?php
      
      use IlluminateDatabaseSeeder;
      
      class PlacesTableSeeder extends Seeder
      {
          /**
           * Run the database seeds.
           *
           * @return void
           */
          public function run()
          {
              //
          }
      }
      
      

      Our new seeder class contains an empty method named run. This method will be called when the db:seed Artisan command is executed.

      We need to edit the run method in order to include instructions to insert sample data in the database. We’ll use the Laravel query builder to streamline this process.

      The Laravel query builder offers a fluent interface for database operations such as inserting, updating, deleting, and retrieving data. It also introduces safeguards against SQL injection attacks. The query builder is exposed by the DB facade - a static proxy to underlying database classes in the service container.

      To get started, we’ll create a static class variable to hold all the sample places we want to insert into the database as an array. This will allow us to use a foreach loop to iterate through all values, inserting each one in the database using the query builder.

      We’ll call this variable $places:

      database/seeds/PlacesTableSeeder.php

      <?php
      
      use IlluminateDatabaseSeeder;
      
      class PlacesTableSeeder extends Seeder
      {
          static $places = [
              'Berlin',
              'Budapest',
              'Cincinnati',
              'Denver',
              'Helsinki',
              'Lisbon',
              'Moscow',
              'Nairobi',
              'Oslo',
              'Rio',
              'Tokyo'
          ];

      Next, we’ll need to include a use statement at the top of our PlacesTableSeeder class to facilitate referencing the DB facade throughout the code:

      database/seeds/PlacesTableSeeder.php

      <?php
      
      use IlluminateDatabaseSeeder;
      use IlluminateSupportFacadesDB;
      
      class PlacesTableSeeder extends Seeder
      …
      

      We can now iterate through the $places array values using a foreach loop, and insert each one in our places table using the query builder:

      database/seeds/PlacesTableSeeder.php

      …
          public function run()
          {
              foreach (self::$places as $place) {
                  DB::table('places')->insert([
                      'name' => $place,
                      'visited' => rand(0,1) == 1
                  ]);
              }
          }
      
      

      The foreach loop iterates through each value of the $places static array. At each iteration, we use the DB facade to insert a new row at the places table. We set the name field to the name of the place we just obtained from the $places array, and we set the visited field to a random value of either 0 or 1.

      This is what the full PlacesTableSeeder class will look like after all the updates:

      database/seeds/PlacesTableSeeder.php

      <?php
      
      use IlluminateDatabaseSeeder;
      use IlluminateSupportFacadesDB;
      
      class PlacesTableSeeder extends Seeder
      {
          static $places = [
              'Berlin',
              'Budapest',
              'Cincinnati',
              'Denver',
              'Helsinki',
              'Lisbon',
              'Moscow',
              'Nairobi',
              'Oslo',
              'Rio',
              'Tokyo'
          ];
      
          /**
           * Run the database seeds.
           *
           * @return void
           */
          public function run()
          {
              foreach (self::$places as $place) {
                  DB::table('places')->insert([
                      'name' => $place,
                      'visited' => rand(0,1) == 1
                  ]);
              }
          }
      }
      

      Save and close the file when you’re done making these changes.

      Seeder classes aren’t automatically loaded in the application. We need to edit the main DatabaseSeeder class to include a call to the seeder we’ve just created.

      Open the database/seeds/DatabaseSeeder.php file using nano or your favorite editor:

      • nano database/seeds/DatabaseSeeder.php

      The DatabaseSeeder class looks like any other seeder: it extends from the Seeder class and has a run method. We’ll update this method to include a call to PlacesTableSeeder.

      Update the current run method inside your DatabaseSeeder class by deleting the commented-out line and replacing it with the following highlighted code:

      database/seeds/DatabaseSeeder.php

      …
          public function run()
          {
              $this->call(PlacesTableSeeder::class);
          }
      ...
      

      This is how the full DatabaseSeeder class will look like after the update:

      database/seeds/DatabaseSeeder.php

      <?php
      
      use IlluminateDatabaseSeeder;
      
      class DatabaseSeeder extends Seeder
      {
          /**
           * Seed the application's database.
           *
           * @return void
           */
          public function run()
          {
              $this->call(PlacesTableSeeder::class);
          }
      }
      
      
      

      Save and close the file when you’re done updating its content.

      We have now finished setting up both a migration and a seeder for our places table. In the next step, we’ll see how to execute them.

      Step 6 — Running Database Migrations and Seeders

      Before proceeding, we need to make sure your application is up and running. We’ll set up the application encryption key and then access the application from a browser to test the web server.

      To generate the encryption key required by Laravel, you can use the artisan key:generate command:

      • docker-compose exec app php artisan key:generate

      Once the key has been generated, you’ll be able to access the application by pointing your browser to your server hostname or IP address on port 8000:

      http://server_host_or_ip:8000
      

      You’ll see a page like this:

      MySQL error

      That means the application is able to connect to the database, but it couldn’t find a table called places. We’ll create the places table now, using the following migrate artisan command:

      • docker-compose exec app php artisan migrate

      You’ll get output similar to this:

      Output

      Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.06 seconds) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (0.06 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.03 seconds) Migrating: 2020_02_10_144134_create_places_table Migrated: 2020_02_10_144134_create_places_table (0.03 seconds)

      You’ll notice that a few other migrations were executed along with the create_places_table migration we’ve set up. These migrations are auto generated when Laravel is installed. Although we won’t be using these additional tables now, they will be needed in the future when we expand the application to have registered users and scheduled jobs. For now, you can just leave them as is.

      At this point our table is still empty. We need to run the db:seed command to seed the database with our sample places:

      • docker-compose exec app php artisan db:seed

      This will run our seeder and insert the sample values we defined within our PlacesTableSeeder class. You’ll see output similar to this:

      Output

      Seeding: PlacesTableSeeder Seeded: PlacesTableSeeder (0.06 seconds) Database seeding completed successfully.

      Now, reload the application page on your browser. You’ll see a page similar to this:

      Demo Laravel Application

      Whenever you need to start from scratch, you can drop all your database tables with:

      • docker-compose exec app php artisan db:wipe

      Output

      Dropped all tables successfully.

      To run the app migrations and seed the tables in a single command, you can use:

      • docker-compose exec app php artisan migrate --seed

      Output

      Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.06 seconds) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (0.07 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.03 seconds) Migrating: 2020_02_10_144134_create_places_table Migrated: 2020_02_10_144134_create_places_table (0.03 seconds) Seeding: PlacesTableSeeder Seeded: PlacesTableSeeder (0.06 seconds) Database seeding completed successfully.

      If you want to roll back a migration, you can run:

      • docker-compose exec app php artisan migrate:rollback

      This will trigger the down method for each migration class inside the migrations folder. Typically, it will remove all the tables that were created through migration classes, leaving alone any other tables that might have been manually created. You’ll see output like this:

      Output

      Rolling back: 2020_02_10_144134_create_places_table Rolled back: 2020_02_10_144134_create_places_table (0.02 seconds) Rolling back: 2019_08_19_000000_create_failed_jobs_table Rolled back: 2019_08_19_000000_create_failed_jobs_table (0.02 seconds) Rolling back: 2014_10_12_100000_create_password_resets_table Rolled back: 2014_10_12_100000_create_password_resets_table (0.02 seconds) Rolling back: 2014_10_12_000000_create_users_table Rolled back: 2014_10_12_000000_create_users_table (0.02 seconds)

      The rollback command is especially useful when you’re making changes to application models and a db:wipe command can’t be used - for instance, if multiple systems depend on the same database.

      Conclusion

      In this guide, we’ve seen how to use database migrations and seeders to facilitate setting up development and testing databases for a Laravel 6 application.

      As a next step, you might want to check the Laravel documentation for more details on how to use the query builder, and how to use Eloquent models to abstract your application’s database schema even further.



      Source link