1. localdisk

    Posted

    localdisk
Changes in title
+Laravel で掲示板作りたくなった(2)
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,324 @@
+[前回](http://qiita.com/localdisk/items/915ab90606fcdd469458)の続き。
+
+インスパイヤ元: [インスパイヤされて掲示板を作りたくなった(2)](http://qiita.com/tadsan/items/adaade6b675ac344f373)
+
+# テーブルを作ろう
+
+テーブルについては [元ネタ](http://qiita.com/tadsan/items/adaade6b675ac344f373) を参照。以下のテーブルを作成しよう。
+
+- boards
+- threads
+- posts
+
+## いらないファイルを消そう
+
+`databases/migration` の `2014_10_12_000000_create_users_table.php` と `2014_10_12_100000_create_password_resets_table.php` を消しましょう。これは、Laravel の認証に使用するテーブルのマイグレーションファイルですが、今回は必要ないと思います(多分)。
+
+## boards テーブルを作ろう
+
+```shell-session
+$ php artisan make:migration create_boards_table --create=boards
+```
+
+とすると `boards` テーブルを作成するマイグレーションファイルが出来上がります。`--create` オプションが肝[^1]です。
+
+[^1]: `--create` オプションをつけるとテーブルを作る `Schema::create` メソッドが定義されたマイグレーションファイルが生成されます。
+
+生成されたマイグレーションファイルはこんな感じ。
+
+```php:database/migration/2016_03_01_120922_create_boards_table.php
+<?php
+
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class CreateBoardsTable extends Migration
+{
+ /**
+ * Run the migrations.
+ *
+ * @return void
+ */
+ public function up()
+ {
+ Schema::create('boards', function (Blueprint $table) {
+ $table->increments('id');
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('boards');
+ }
+}
+```
+
+マイグレーションファイルには `up` メソッドと `down` メソッドが定義されていて `up` メソッドは `migrate` コマンド(後述) を実行した時に呼び出されるメソッドで `down` メソッドは `migrate:rollback` コマンドを実行した時に呼び出されます。このままで `migrate` コマンドを実行するとこんな感じの SQL が発行されます。
+
+```shell-session
+$ php artisan migrate --pretend
+Migration table created successfully.
+CreateBoardsTable: create table "boards" ("id" varchar not null, "name" varchar not null, "txt" varchar not null, primary key ("id"))
+```
+
+`boards` テーブルにオートインクリメントされる `id` という名前のプライマリキーと `datetime` 型の `created_at` と `updated_at` というカラムが作成されるのがわかりますね。
+
+`id` カラムは `$table->increments('id')` 、 `created_at` と `updated_at` は `$table->timestamps()` に対応してます。今回はインスパイヤ元に従ってにいきます。そういったサンプルがあんまりないのでいいかな、と。
+
+ではテーブルを定義していきましょう。まずは `boards` テーブル。`up` メソッドだけ抜粋。
+
+```php:database/migration/2016_03_01_120922_create_boards_table.php
+<?php
+class CreateBoardsTable extends Migration
+{
+ public function up()
+ {
+ Schema::create('boards', function (Blueprint $table) {
+ $table->string('id')->primary();
+ $table->string('name');
+ $table->string('txt');
+ });
+ }
+}
+```
+
+次は `threads` テーブル。
+
+コマンド叩いて…
+
+```shell-session
+$ php artisan make:migration create_threads_table --create=threads
+```
+
+マイグレーションファイル作って…こう書く。
+
+```php:database/migration/2016_03_01_125931_create_threads_table.php
+<?php
+class CreateThreadsTable extends Migration
+{
+ public function up()
+ {
+ Schema::create('threads', function (Blueprint $table) {
+ $table->integer('timestamp');
+ $table->string('board_id');
+ $table->string('title');
+ $table->primary(['timestamp', 'board_id']);
+ });
+ }
+}
+```
+
+複合主キーも定義できます。とはいえ、前述した `Eloquent` は複合主キーをサポートしていないのでクエリービルダーという `Eloquent` の基盤になっている仕組みを使うことになります。
+
+最後に `posts` テーブル。
+
+```shell-session
+$ php artisan make:migration create_posts_table --create=posts
+```
+
+```php:database/migration/2016_03_01_130821_create_posts_table.php
+<?php
+class CreatePostsTable extends Migration
+{
+ public function up()
+ {
+ Schema::create('posts', function (Blueprint $table) {
+ $table->increments('id');
+ // 元エントリは INT ってなっているけど、多分 string
+ $table->string('board_id');
+ $table->integer('thread_timestamp');
+ $table->string('posted_at');
+ $table->string('name');
+ $table->string('email');
+ $table->string('author_hash');
+ $table->string('message');
+ $table->string('ip_addr');
+
+ $table->index(['board_id', 'thread_timestamp'], 'post_board_thread');
+ $table->index('author_hash', 'post_author_hash');
+ });
+ }
+}
+```
+
+こんな感じで index も定義できる。
+
+
+SQL を確認しよう。`--pretend` オプション便利。
+
+```shell-session
+$ php artisan migrate --pretend
+CreateBoardsTable: create table "boards" ("id" varchar not null, "name" varchar not null, "txt" varchar not null, primary key ("id"))
+CreateThreadsTable: create table "threads" ("timestamp" integer not null, "board_id" varchar not null, "title" varchar not null, primary key ("timestamp", "board_id"))
+CreatePostsTable: create table "posts" ("id" integer not null primary key autoincrement, "board_id" varchar not null, "thread_timestamp" integer not null, "posted_at" varchar not null, "name" varchar not null, "email" varchar not null, "author_hash" varchar not null, "message" varchar not null, "ip_addr" varchar not null)
+CreatePostsTable: create index post_board_thread on "posts" ("board_id", "thread_timestamp")
+CreatePostsTable: create index post_author_hash on "posts" ("author_hash")
+```
+
+うむ。よさげだ。では実行。
+
+```shell-session
+$ php artisan migrate
+Migrated: 2016_03_01_120922_create_boards_table
+Migrated: 2016_03_01_125931_create_threads_table
+Migrated: 2016_03_01_130821_create_posts_table
+```
+
+できた。楽ちん。
+
+# シードデータをつっこんでみる
+
+`php artisan make:seeder {name}` でシードクラス作れるんですが、量も少ないので `database/seeds/DatabaseSeeder.php` に直接書いちゃいましょう。
+
+```php:database/seeds/DatabaseSeeder.php
+<?php
+
+use Illuminate\Database\Seeder;
+
+class DatabaseSeeder extends Seeder
+{
+ /**
+ * Run the database seeds.
+ *
+ * @return void
+ */
+ public function run()
+ {
+ DB::table('boards')->insert([
+ 'id' => 'gline',
+ 'name' => 'ガイドライン@インスパイヤー',
+ 'txt' => 'ここがガ板ですよ。。。',
+ ]);
+ DB::table('threads')->insert([
+ 'timestamp' => 123456789,
+ 'board_id' => 'gline',
+ 'title' => 'インスパイヤのガイドライン',
+ ]);
+ $now = \Carbon\Carbon::now();
+ DB::table('posts')->insert([
+ [
+ 'board_id' => 'gline',
+ 'thread_timestamp' => 123456789,
+ 'posted_at' => $now,
+ 'name' => 'たっどさん',
+ 'email' => '#いんすぱいやー',
+ 'author_hash' => 'tW1nDri11',
+ 'message' => 'てすとです…',
+ 'ip_addr' => '127.0.0.1',
+ ],
+ [
+ 'board_id' => 'gline',
+ 'thread_timestamp' => 123456789,
+ 'posted_at' => $now,
+ 'name' => 'たっどさん',
+ 'email' => '#いんすぱいやー',
+ 'author_hash' => 'tW1nDri11',
+ 'message' => 'もういい加減ねるぽ',
+ 'ip_addr' => '127.0.0.1',
+ ],
+ ]);
+ }
+}
+```
+
+一目瞭然な簡潔なコードですね。`posts` テーブルの `posted_at` のために `Carbon` という日時を扱う便利なライブラリを使ってるのと `posts` テーブルのインサートで2レコード一気にいれてます。ちなみにこう書くとバルクインサートになるので、覚えておくのがよいです。
+
+# 画面を作ろう
+
+Laravel には `Blade` というテンプレートエンジンがあってですね、これがなかなか便利です。PhpStorm つかうともっと便利[^2]です。
+
+[^2]: PhpStorm の Laravel プラグインの `Blade` 構文のシンタックスハイライトとコード補完がめっちゃ便利。
+
+## 共通点プレートを作ろう
+
+Laravel の View は `resources/views` に作ります。`Blade` も `Twig` と同じようにテンプレートの継承ができるので、まずはテンプレートファイルから作りましょう。コマンドがないので手動でつくります。`Blade` を使う場合は `.blade.php` という拡張子(といっていいんだろうか)になります。
+
+
+```php:resources/views/layouts/default.blade.php
+<!doctype html>
+<html lang="ja">
+<head>
+ <title>@yield('title', 'いんすぱいやーBBS')</title>
+</head>
+<body>
+@yield('content')
+
+@section('footer')
+ <hr>
+ <footer>
+ <address>
+ &copy; Copyright 2016 localdisk<br>
+ <a href="https://github.com/localdisk/inspire-bbs">InspireBBS Laravel</a> is licenced under <a href="http://www.wtfpl.net/"><abbr title="Do What the Fuck You Want to Public License">WTFPL</abbr></a> and/or <a href="http://www.gnu.org/licenses/agpl-3.0.html"><abbr title="GNU Affero General Public License, Version 3">AGPLv3</abbr></a>
+ </address>
+ </footer>
+@show
+</body>
+</html>
+```
+
+`@yield` と `@section` というディレクティブに注目。`Twig` と大体考え方は一緒だと思います。多分。詳しくは[Bladeテンプレート 5.1 Laravel](http://readouble.com/laravel/5/1/ja/blade.html)を参照してください(疲れた)
+
+## 個別ページを作ろう
+
+先ほど作った `default.blade.php` を継承した `index.blade.php` を作ります。
+
+```php
+@extends('layouts.default')
+
+@section('title', 'いんすぱいやーBBSへようこそ')
+
+@section('content')
+ <h1>いんすぱいやーBBS</h1>
+
+ <p>ヾ(〃><)ノ゙< {{ $greeting }}</p>
+@stop
+```
+
+- `@extends('layouts.default')` と書くことで、`layouts/default.blade.php` を継承
+- `@section` の `title` と `content` に定義を書く
+- `{{ $greeting }}` で変数を出力
+
+## タイムゾーンの定義
+
+タイムゾーンを設定します。Laravel はデフォルトで `UTC` にタイムゾーンを設定しているので `Asia/Tokyo` に設定し直すには `config/app.php` を変更します。まぁ、実際のところは `UTC` のままで、表示の際に [Carbon](http://carbon.nesbot.com/docs/) 使ったり、[Moment Timezone ](http://momentjs.com/timezone/) あたりを使って `JST` に変換したりすると思います。
+
+```php:config/app.php
+<?php
+
+return [
+ 'timezone' => 'Asia/Tokyo',
+]
+```
+
+## 元気に挨拶をしつつ画面に表示しよう
+
+疲れたので巻きに入ります。Laravel は `app/Http/routes.php` にルート定義をします。その中で書くもよし、コントローラーを作るもよし。今回は `routes.php` に直接書いちゃいましょう。
+
+```php:app/Http/routes.php
+<?php
+
+Route::get('/', function () {
+ $hour = Carbon\Carbon::now()->hour;
+
+ $greeting = null;
+ if (4 <= $hour && $hour < 10) {
+ $greeting = "お早うございます";
+ } elseif (10 <= $hour && $hour < 17) {
+ $greeting = "こんにちは";
+ } else {
+ $greeting = "こんばんわ";
+ }
+
+ return view('index', compact('greeting'));
+});
+```
+
+# まとめ
+
+いろいろ説明を省略しすぎている感じがあるので[元記事](http://qiita.com/tadsan/items/adaade6b675ac344f373)を読んでからこっち読んでみてください。_(:3」∠)_