Laravel 5.4: DBマイグレーション

What?

Why?

  • そもそもなぜDBマイグレーションが必要なのか?
    • MySQL Workbenchとかを使う
      • 問題:
        • .mwbファイルとかSQLファイルとかの管理対象が増える
        • DBのバージョンとソースコードのバージョンがずれたりして死ぬことがある(死んだことがある)

Migration

  • 保存場所
    • database/migrations/
$ php artisan migrate
Migration table created successfully.
Migrated: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_100000_create_password_resets_table
$ mysql --user=homestead --password=secret homestead
mysql> show tables;
+---------------------+
| Tables_in_homestead |
+---------------------+
| migrations          |
| password_resets     |
| users               |
+---------------------+
3 rows in set (0.00 sec)

mysql> desc migrations;
+-----------+------------------+------+-----+---------+----------------+
| Field     | Type             | Null | Key | Default | Extra          |
+-----------+------------------+------+-----+---------+----------------+
| id        | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| migration | varchar(255)     | NO   |     | NULL    |                |
| batch     | int(11)          | NO   |     | NULL    |                |
+-----------+------------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

mysql> desc users;
+----------------+------------------+------+-----+---------+----------------+
| Field          | Type             | Null | Key | Default | Extra          |
+----------------+------------------+------+-----+---------+----------------+
| id             | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| name           | varchar(255)     | NO   |     | NULL    |                |
| email          | varchar(255)     | NO   | UNI | NULL    |                |
| password       | varchar(255)     | NO   |     | NULL    |                |
| remember_token | varchar(100)     | YES  |     | NULL    |                |
| created_at     | timestamp        | YES  |     | NULL    |                |
| updated_at     | timestamp        | YES  |     | NULL    |                |
+----------------+------------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)

mysql> desc password_resets;
+------------+--------------+------+-----+---------+-------+
| Field      | Type         | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+-------+
| email      | varchar(255) | NO   | MUL | NULL    |       |
| token      | varchar(255) | NO   | MUL | NULL    |       |
| created_at | timestamp    | YES  |     | NULL    |       |
+------------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

Rollback

$ php artisan migrate:status
+------+------------------------------------------------+
| Ran? | Migration                                      |
+------+------------------------------------------------+
| Y    | 2014_10_12_000000_create_users_table           |
| Y    | 2014_10_12_100000_create_password_resets_table |
+------+------------------------------------------------+
$ php artisan migrate:rollback
Rolled back: 2014_10_12_100000_create_password_resets_table
Rolled back: 2014_10_12_000000_create_users_table
$ php artisan migrate:status
+------+------------------------------------------------+
| Ran? | Migration                                      |
+------+------------------------------------------------+
| N    | 2014_10_12_000000_create_users_table           |
| N    | 2014_10_12_100000_create_password_resets_table |
+------+------------------------------------------------+

Make migration

$ php artisan make:migration create_articles_table --create="articles"
Created Migration: 2017_02_14_184315_create_articles_table
$ less database/migrations/2017_02_14_184315_create_articles_table.php
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateArticlesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('articles', function (Blueprint $table) {
            // ここから
            $table->increments('id');
            $table->string('title');
            $table->text('body');
            $table->timestamps();
            $table->timestamp('published_at')->useCurrent();
            // ここまで追加
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('articles');
    }
}

Edit migration

php artisan migrate
mysql> desc articles;
+--------------+------------------+------+-----+-------------------+----------------+
| Field        | Type             | Null | Key | Default           | Extra          |
+--------------+------------------+------+-----+-------------------+----------------+
| id           | int(10) unsigned | NO   | PRI | NULL              | auto_increment |
| title        | varchar(255)     | NO   |     | NULL              |                |
| body         | text             | NO   |     | NULL              |                |
| created_at   | timestamp        | YES  |     | NULL              |                |
| updated_at   | timestamp        | YES  |     | NULL              |                |
| published_at | timestamp        | NO   |     | CURRENT_TIMESTAMP |                |
| exceprt      | text             | NO   |     | NULL              |                |
+--------------+------------------+------+-----+-------------------+----------------+
7 rows in set (0.00 sec)

参考

http://site.oganity.pw/232/

Laravel 5.4: DBマイグレーションでエラーになる

What?

このバージョンで

laravel vagrant master %$ php artisan --version
Laravel Framework 5.4.10
laravel vagrant master %$ mysql --version
mysql  Ver 14.14 Distrib 5.7.17, for Linux (x86_64) using  EditLine wrapper
laravel vagrant master %$ php -v
PHP 7.1.1-1+deb.sury.org~xenial+1 (cli) (built: Jan 20 2017 09:20:20) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
    with Zend OPcache v7.1.1-1+deb.sury.org~xenial+1, Copyright (c) 1999-2017, by Zend Technologies
    with blackfire v1.14.3~linux-x64-non_zts71, https://blackfire.io, by Blackfireio Inc.

このmigrationファイルを

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('articles', function (Blueprint $table) {
            // ここから
            $table->increments('id');
            $table->string('title');
            $table->text('body');
            $table->timestamps();
            $table->timestamp('published_at');
            // ここまで追加
        });
    }

migrateすると、エラーになる

$ php artisan migrate


  [Illuminate\Database\QueryException]
  SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for 'published_at' (SQL: create table `articles` (`id
  ` int unsigned not null auto_increment primary key, `title` varchar(255) not null, `body` text not null, `created_at` timestamp nul
  l, `updated_at` timestamp null, `published_at` timestamp not null) default character set utf8mb4 collate utf8mb4_unicode_ci)



  [PDOException]
  SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for 'published_at'

Solution

このmigrationファイルをちょっと書き換え、

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('articles', function (Blueprint $table) {
            // ここから
            $table->increments('id');
            $table->string('title');
            $table->text('body');
            $table->timestamps();
            $table->timestamp('published_at')->useCurrent(); // ここ追加
            // ここまで追加
        });
    }

こうする

$ php artisan migrate:refresh --seed
Rolled back: 2014_10_12_100000_create_password_resets_table
Rolled back: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_100000_create_password_resets_table
Migrated: 2017_02_14_184315_create_articles_table
Migrated: 2017_02_23_172823_add_excerpt_to_articles_table

Why?

  • マイグレーションを全部ロールバックし、再度実行する力技コマンド php artisan migrate:refresh --seed を使って、強制帳消し
  • published_atnot nullなのに値が入ってなかったので、useCurrent()を使って突っ込んだ

失敗例

published_atだけ触ればいいのに、その前のtimestampも色々いじってしまった結果。

laravel vagrant master %$ php artisan migrate


  [Symfony\Component\Debug\Exception\FatalThrowableError]
  Call to a member function useCurrent() on null


laravel vagrant master *%$ php artisan migrate


  [Symfony\Component\Debug\Exception\FatalThrowableError]
  Call to a member function default() on null


laravel vagrant master *%$ php artisan migrate


  [Symfony\Component\Debug\Exception\FatalThrowableError]
  Call to a member function nullable() on null

config/database.phpの確認したけど、ちゃんとstrictになってた

'strict' => true,

参考

https://github.com/laravel/framework/issues/3602

Laravel 5.4: メンテナンスモードの使い方、仕組み

メンテナンスモードの使い方

  • 開始
$ php artisan down
  • 復帰
    • Be right back.と表示される
php artisan up

メンテナンスモードの仕組み

  • storage/framework/down が存在していたらメンテナンスモードになっている
$ ls -la storage/framework/down
ls: cannot access 'storage/framework/down': No such file or directory

$ php artisan down
Application is now in maintenance mode.
$ ls -la storage/framework/down
-rw-r--r-- 1 vagrant vagrant 66 Feb 14 03:44 storage/framework/down

$ php artisan up
Application is now live.
$ ls -la storage/framework/down
ls: cannot access 'storage/framework/down': No such file or directory
  • メンテナンスページのテンプレート
    • vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/views/503.blade.php にある

TODO

  • 部分的にメンテナンスモードにできる?
  • あるIPだけ限定でアクセスさせることができる?

参照

Laravel 5 メンテナンスモード IP制限

Laravel 5.4: 環境設定

DotEnvライブラリ

設定ファイル

  • .env: 各環境で使う設定ファイル
    • git管理対象外
  • .env.example: サンプルファイル
    • git管理対象
$ diff .env.example .env
2c2
< APP_KEY=
---
> APP_KEY=base64key...

設定の適用

  • 設定ファイルの記述
    • .env
DB_DATABASE=homestead
  • 設定の適用
    • .envから値が取れないとき第二引数の値が入る
env('DB_DATABASE', 'foo')
  • 設定の更新
    • storage/framework/config.phpが更新
$ php artisan config:cache

環境名の取得

use App;
$environment = App::environment(); // get "local"
if (App::environment('local'))
{
    // The environment is local
}
 
if (App::environment('local', 'staging'))
{
    // The environment is either local OR staging...
}

TODO

  • 各環境名の設定方法
  • 実際に各環境を立てる

参照

【Laravel5】実行環境と設定ファイルの関係 - Bloq4Developer

Laravel 5.4: Blade テンプレートを使う

if

@if (count($people))

@endif

foreach

@foreach ($people as $person)
  {{ $person }}
@endforeach

Template

  • テンプレート側: @yield('bar')
  • テンプレート利用側:
    • Fooテンプレートの継承: @extends('foo')
    • セクション書き換え: @section('bar'), @stop

  • テンプレート: resources/views/app.blade.php
<body>
    <div class="container">
        @yield('content')
    </div>
 
    @yield('footer')
 
</body>
  • テンプレート利用: resources/views/pages/about.blade.php
@extends('app')
 
@section('content')
 
<h1>About {{$name}}</h1>
 
@if (count($people))
<h3>People I Like:</h3>
 
<ul>
    @foreach ($people as $person)
        <li>{{ $person }}</li>
    @endforeach
</ul>
@endif
 
@stop

参照

http://site.oganity.pw/177/

Laravel 5.4: Viewへデータを引き渡す

Summary

  • テンプレートはBladeファイル: foo.blade.php
  • withを使ってControllerからViewへ渡す

  • Controller側:

    • view('pages.about')->with('name', $name)
  • View側:
    • エスケープ: {{$bar}}
    • 非エスケープ: {!! $bar !!}

How to basic

  • app/Http/routes.php
Route::get('about', 'PagesController@about');
  • コントローラ作成
$ php artisan make:controller PagesController
  • aboutメソッド作成
    • app/Http/Controllers/PagesController.php
class PagesController extends Controller {
 
    public function about() {
        $name = 'Jeffery Way';
        return view('pages.about')->with('name', $name);
    }
 
}
  • テンプレート作成
    • resources/views/pages/about.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <h1>About {{$name}}</h1>
</body>
</html>

How to advance

  • エスケープ

    • エスケープ: {{$bar}}
    • 非エスケープ: {!! $bar !!}
  • データ渡しにwithを使う

    • 単数:
      • Controller: view('pages.about')->with('name', $name)
      • Template: {{$name}}
    • 複数(配列):
      • Controller: view('pages.about')->with(['first' => 'Jeffery', 'last' => Way'])
      • Template: {{$first}} {{$last}}
  • データ渡しにwithを使わない
    • 単数:
      • Controller: view('pages.about', $data)
      • Template: {{$first}} {{$last}}
    • 複数(連想配列):
      • Controller: view('pages.about', $data)
      • Template: {{$name['first']}} {{$name['last']}}
    • 複数(別変数):
      • Controller: view('pages.about', compact('first', 'last'))
      • Template: {{$first}} {{$last}}

参考

http://site.oganity.pw/160/

Laravel 5.4: Routing, Controller, Viewの流れを触る

What?

  • ざっくり最小のRouting, Controller, Viewの流れを確認する

Why?

  • ざっくり最小のものを作りたい

Routing

  • routes/: ルーティングディレクト
    • ver 5.3 から app/Http/routes.php は廃止
$ less routes/
api.php       channels.php  console.php   web.php
Route::get('/', 'welcome');

or

Route::get('/', function () {
    return view('welcome');
});

Controller

  • app/Http/Controllers/以下にある
    • app/Http/Controllers/WelcomeController.php
<?php

namespace App\Http\Controllers;

class WelcomeController extends Controller {
  public function index()
  {
    return view('welcome');
  }
}

View

  • blade テンプレートエンジンを使用
  • resources/views/以下にある
    • resources/views/welcome.blade.php

参考

Laravel5 入門 インストールからMVCの基本機能をさっと眺める | hrendoh's memo http://site.oganity.pw/154/