Laravelでモデル作成

Laravel初見なので個人的メモです。

LaravelディレクトリメモでDB設定をした続き

##1.モデルの作成

Postモデルを作成
バージョン管理するためのマイグレーションファイルも作成するため　--migrationオプションをつける

```php
php artisan make:model Post --migration 実行
```
マイグレーションファイルの中身を確認

```database/migrations
<?php

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

class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
      // postsという複数形のテーブルが作成されており、
      // Railsのようにidとtimestampsが作成されている
            $table->increments('id');
            $table->timestamps();
        });
    }

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

```

コード内にup()とdown()というメソッドがあるのだが、
up()がこのマイグレーションで行いたい処理
down()がそれを巻きもどすための処理 になります。
 
Railsのようにidとtimestampsが自動生成されており、ここに追加することでカラムを追加できる

```database/migrations/XXXXX.php
カラムの追加
$table->increments('id');
$table->string('title');  #string型のtitleカラムを追加
$table->text('body');  #text型のbodyカラムを追加
$table->timestamps();
```

では、migrationファイルを実行していく

```ターミナル
php artisan migrate
```

上手くいってなかったり、間違えて１つ前のマイグレーションへ戻す場合はこちらを実行

```
php artisan migrate:rollback 
```

```成功結果
$ php artisan migrate
Migration table created successfully.
Migrating: 2018_05_13_135622_create_posts_table
Migrated:  2018_05_13_135622_create_posts_table
```

この時点で作成した、database.sqliteファイルが更新されている

今回はDBにsqliteを使うので
sqliteでアクセスしてテーブルが作成されているか確認.

sqlite3 database/作成したdbファイル名.sqliteを実行
(mysqlの場合はｍysqlのファイル名を入れてあげる)

```ターミナル
今回作成したのは、database.sqliteなので下記コードを実行:

sqlite3 database/database.sqlite
```

```sqlite
sqlite> .schema posts 実行

CREATE TABLE IF NOT EXISTS "posts" ("id" integer not null primary key autoincrement, "title" varchar not null, "body" text not null, "created_at" datetime null, "updated_at" datetime null);
```

正しくtitleとbodyカラムが作成されていることを確認!

一旦sqliteから抜ける

```sqlite
.exit
```

##2.インタラクティブにModelを操作（コンソール操作）
まずは「php artisan tinker」でコンソールを立ち上げる
（Railsでのrails consoleと同じイメージ）

```
$ php artisan tinker

Psy Shell v0.9.3 (PHP 7.2.5 — cli) by Justin Hileman
>>> 

```

###・レコードに挿入してみる
まずはインスタンスを作成し、saveメソッドを使ってみます。
名前空間がデフォルトでAppになっているのでApp\Post();としてあげる

```インスタンス作成
>>> $post = new App\Post();
=> App\Post {#2283}
>>> 

インスタンスの作成完了！
```

postのtitleを「title 1」bodyを「body 1」という様に保存してみる

```
>>> $post->title = 'title 1'; #title 1を格納
=> "title 1" 
>>> $post->body = 'body 1';  #body 1を格納
=> "body 1"
>>> $post->save(); #これらの変更を保存
=> true #成功
>>> 

```

保存したデータを確認

```tinker
App\Post::all();

実行結果
=> Illuminate\Database\Eloquent\Collection {#2291
     all: [
       App\Post {#2292
         id: "1",
         title: "title 1",
         body: "body 1",
         created_at: "2018-05-13 14:52:59",
         updated_at: "2018-05-13 14:52:59",
       },
     ],
   }
```
Railsでいう　Model名.allと同じと解釈
(User.all, Post.all等)

【配列で取り出したい場合】
また配列で取り出したい場合は->ToArray();を指定してあげれば良い
これでスッキリとした構造で返ってくる

```tinker
>>> App\Post::all()->ToArray();

実行結果
=> [
     [
       "id" => 1,
       "title" => "title 1",
       "body" => "body 1",
       "created_at" => "2018-05-13 14:52:59",
       "updated_at" => "2018-05-13 14:52:59",
     ],
   ]

```

一旦tinkerを抜けてsqliteでも確認してみる

```tinker
exit
```

```ターミナル
$ sqlite3 database/database.sqlite
```

```sqlite
sqlite> select * from posts;

実行結果：
1|title 1|body 1|2018-05-13 14:52:59|2018-05-13 14:52:59
```

正しく保存されていることを確認できた！

確認だけなので.exitで抜けておく

とりあえずこれでモデルの作成とデータの操作は問題なさそう




###・追加（create）
newでは無く、createすることで一発で作成と保存も可能
これもRailsと同じ

```tinker
App\Post::create(['title' => 'title 2', 'body' => 'body 2']);
```
ただLaravelの場合このままcreateしようとするとマスアサイメントエラー？になってしまう為、一手間必要。
(MassAssignment: MassAssignmentは意図しないリクエストによって悪意のあるデータが挿入されてしまう脆弱性のこと)という事らしい。

モデルの設定を追加する必要があるのでapp/Post.phpを開く

protected $fillable とした後に、この column にはデータを挿入してもいいよという設定を追加します。

```app/Post.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    //
    protected $fillable = ['title', 'body']; ←この部分を追加
}

```
これでtitleとbodyにデータの挿入ができる様になりました.

tinkerを再起動してcreateしてみる

```tinker
>>> App\Post::create(['title' => 'title 2', 'body' => 'body 2']);

=> App\Post {#2281
     title: "title 2",
     body: "body 2",
     updated_at: "2018-05-13 15:35:28",
     created_at: "2018-05-13 15:35:28",
     id: 2,
   }
   
   create成功！！
```
App\Post::all();してみる

```tinker
>>> App\Post::all();
=> Illuminate\Database\Eloquent\Collection {#2293
     all: [
       App\Post {#2294
         id: "1",
         title: "title 1",
         body: "body 1",
         created_at: "2018-05-13 14:52:59",
         updated_at: "2018-05-13 14:52:59",
       },
       App\Post {#2295
         id: "2",
         title: "title 2",
         body: "body 2",
         created_at: "2018-05-13 15:35:28",
         updated_at: "2018-05-13 15:35:28"
```
はい、OK