【Laravel】入門してみたまとめ✍🏻

# LaravelではMVCモデルを採用している

**Model**・・・データベースとやりとり
**View**・・・見た目
**Controller**・・処理
Routing・・・アクセスの振り分け
Migration・・・DBテーブルの履歴管理

## Laravelビュー、ルート

resources/views/配下に`任意のファイル名.blade.php`でviewファイルを作成します。
routes/web.phpにアクセス振り分けを記述することで指定したurlにアクセスした際に指定のファイルを表示させます。
下記の例では`/`にアクセスされた際には、welcome.blade.phpを表示させています。

```routes/web.php
Route::get('/', function () {
    return view('welcome');
});
```

## Laravelモデル

DBとのやりとりをPHPで書けます。
DBをSQLではなく、他の言語で書けることをORM/ORマッパー(オブジェクト関係マッピング)といいます。
下記コマンドで app/Models/Test.php というモデルファイルを作成できます。
任意のファイル名で生成できますが、先頭は大文字で書くのが一般的です。

`php artisan make:model Test`

## マイグレーション

DBテーブルの履歴管理ができる仕組みで、テーブルの設定をPHPで書けます。
モデルは単数形で、マイグレーションを複数形で書くとLaravel側で紐付けを自動判定してくれます。
下記コマンドで、database/migrations/配下に作成日付のマイグレーションファイルが生成されます。
このマイグレーションファイルで、テーブルに追加したいカラムの設定を追記していく形です。

`php artisan make:migration create_tests_table`

モデルファイルでTestというものを作成していた場合、create_tests_tableと、複数形のtestsでファイルを作成すればLaravel側でTestモデルではtestsテーブルを使用するということを、自動判定して紐付かせてくれます。

database/migrations/配下に生成されたマイグレーションファイルの初期状態から、[Laravel:マイグレーション](https://readouble.com/laravel/9.x/ja/migrations.html#column-method-string)を参考に`$table->string('text');`とカラムを追加しました。string型のtextというカラム名です。
```diff_php:2023_04_15_102845_create_tests_table.php
<?php

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

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('tests', function (Blueprint $table) {
            $table->id();
+           $table->string('text');
            $table->timestamps();
        });
    }

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

この修正したマイグレーションファイルを適応させるコマンドは下記です。
`php artisan migrate`

DBのphpMyAdminで下記のようにtestsテーブルに4つのカラムができています。
idの他に`$table->timestamps();`という初期設定を付けておいたままのため、作成日と更新日のカラムが追加されています。
![スクリーンショット 2023-04-15 10.53.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/cd714f85-0720-6f88-3f88-2c5331977acc.png)

## tinker

コマンド入力でデータ保存・閲覧できます。

`php artisan tinker`

対話型になるのでその状態でコマンド入力していきます。

下記コマンドでインスタンス化します。

`$test =  new App\Models\Test;`

インスタンス化したモデルはカラムをプロパティとして持っているため、その中から変更したいカラム名を指定し値を格納します。

`$test->text =  "aaa"`

下記コマンドで保存します。これでDBが更新されます。

`$test->save();`

![スクリーンショット 2023-04-15 12.51.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/09c3f248-cddd-0173-4374-6d7f7340848d.png)
![スクリーンショット 2023-04-15 12.52.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/14d8384d-6154-78cd-efd3-af2536e70767.png)

下記コマンドでもターミナル上でDBの確認ができます。
`App\Models\Test::all();`
![スクリーンショット 2023-04-15 12.54.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/a21fe2ce-74af-c050-4804-6c9f8819381b.png)

`exit`で対話型から脱却できます。

## Laravelコントローラー

### ルート、コントローラー、ビューで任意のページを表示する流れ

* コントローラーファイル作成
* web.php内で、`Route::get()`を使用し、urlとそのurlに対するコントローラーファイルを指定
* コントローラーファイル内で`view()`を使用し、表示させるviewファイルを指定

**上記を踏まえて実際に1ページ作成、表示してみる**

<br>

下記コマンドで、app/Http/Controllers/配下に、TestController.phpが生成されます。Test部分は任意の名前ですがControllerは付けるのが一般的なようです。

`php artisan make:controller TestController`

routes/web.phpにuse文で、使用するコントローラーを追記し、`Route::getメソッド`でアクセスを指定します。
今回は上記で作成したTestController.phpファイルを指定します。

```diff_php:routes/web.php
<?php

use Illuminate\Support\Facades\Route;
+ use App\Http\Controllers\TestController; 

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

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

+ Route::get('tests/test', [TestController::class, 'index']); 

```

:::note
Route::get()は第一引数にurl、第二引数に[コントローラー::class,'メソッド']を記述します。
:::

というわけで、web.phpで指定した通り、TestController.phpにindex()を追加して、viewファイルを指定します。
```diff_php:app/Http/Controllers/TestController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class TestController extends Controller
{
+    public function index()
+    {
+        return view('tests.test'); // view(フォルダ名.ファイル名)で表示させるviewファイルの指定
+    }
}
```

そして、`view()`で指定した通り、testsフォルダにtestファイルを作成します。
```resources/views/tests/test.blade.php
test
```

`php artisan serve`で簡易サーバーを立ち上げ、`http://127.0.0.1:8000/tests/test`にアクセスすると指定したviewファイルが表示されました！
![スクリーンショット 2023-04-15 14.28.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/9776c13d-9bbb-d163-054f-307d13fa505d.png)

### 続いて、コントローラーからモデルにアクセスして、モデルを使用しDBのデータを持ってくる流れ

* コントローラーファイル内で、モデルファイルを読み込んで、変数に値を格納
* コントローラーファイル内で`compact()`を使用し、viewファイルにその変数を渡す
* viewファイルでその変数を用いてDBのデータを表示

**上記を踏まえて実際にDBのデータを表示してみる**

コントローラーファイルでモデルファイルを読み込んで、DBの値を変数に格納

```diff_php:app/Http/Controllers/TestController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
+ use App\Models\Test;

class TestController extends Controller
{
    public function index()
    {
+       $values =  Test::all(); // データを全て変数に格納
+       // dd($values); phpのdieとvar_dumpを合わせたようなメソッド。デバッグに便利
-       return view('tests.test');
+       return view('tests.test', compact('values')); // compact()でviewファイルにデータを渡す
    }
}

```

viewファイルで、その変数を使用してDBのデータを表示
```diff_php:resources/views/tests/test.blade.php
test
+ <br>
+ @foreach($values as $value)
+ {{ $value->id }}<br>
+ {{ $value->text }}<br>
+ @endforeach
```

`http://127.0.0.1:8000/tests/test`にアクセスしてみるとデータが表示されました！
![スクリーンショット 2023-04-15 15.15.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/ae198bdb-8509-1ced-0e10-b78639d34c27.png)

<br>

##  LaravelでDBからデータを取得する方法は大きく2つ

1. エロクアント
`use App\Models\Test`でモデルファイルを読み込んで、`$tests = Test::all();`で変数に格納する方法。
**allやgetを使うことでコレクション型になります。**
`dd($tests);`で表示すればわかりますがコレクション型（配列を拡張した型）です。
このコレクション型には`all`や`get`以外にも利用可能なメソッドはたくさんあるので詳細は[ドキュメント](https://readouble.com/laravel/9.x/ja/collections.html)を参照して下さい。


1. クエリビルダ
`DB::table('tests')->get();` を使用する方法

### エロクアントで色々なデータを取ってくる

コントローラーファイルにコレクションのメソッドを使用して色んなデータを出力してみます。

```diff_php:app/Http/Controllers/TestController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Test;

class TestController extends Controller
{
    public function index()
    {
+       // Eloquent(エロクアントでDBからデータをとってきている)
        $values =  Test::all();
+       $count =  Test::count();
+       $first = Test::findOrFail(1);
+       $whereBBB = Test::where('text', '=', 'bbb')->get();
+       dd($values, $count, $first, $whereBBB);
        return view('tests.test', compact('values')); 
    }
}
```

この状態で簡易サーバーを見てみると`dd()`によって色々表示されているかと思います。
添付画像の青文字の`Illuminate\Database\Eloquent\Collection`などのようにコレクション型かどうか判断できます。一つ目に表示されている`$values`は`all()`で取得しているのでコレクション型になっているのに対し、二つ目は`count()`で取得しているのでコレクション型ではありません。
![スクリーンショット 2023-04-15 18.45.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/1783617d-7356-7623-ce93-07d0a1faa49e.png)

うまくデータが取得できない場合は上記のように`dd()`を使用し、データの型を確認しつつ進められます。

## クエリビルダ

PHPでクエリをかけます。
例)
```php
$queryBuilder = DB::table('tests')->where('text', '=', 'bbb')->select('id', 'text')->get();
```
基本的にはエロクアントでデータ取得した方がメリットが多いとのことです。

<br>


### リンクを作成して作成したページを表示させる流れ

#### リンクを作成

リンクを追加したいblade.phpファイルにリンクを追加します。
laravelでリンクを書きたい場合はヘルパー関数の`route()`を使います。引数にはディレクトリ.ファイルと記述することで遷移先を指定できます。

```html:resources/views/contacts/index.blade.php
<a href="{{ route('contacts.create')}}">新規登録</a>
```

#### ルートを追加

routes/web.phpでルートを追加します。
下記は色々まとめて書きたい場合の例です。
```diff_php:web.php
Route::prefix('contacts')->middleware(['auth'])
    ->controller(ContactFormController::class)
    ->name('contacts.')
    ->group(function () {
        Route::get('/', 'index')->name('index');
+       Route::get('/create', 'create')->name('create');
    });
```

下記コマンドでルートが生成されているか確認できます。
`php artisan route:list`

#### コントローラー追加

app/Http/Controllers/ContactFormController.phpでコントローラーを追加します。(謎)
web.phpで追記した通り、createメソッドを追加します。
createメソッドは、viewヘルパ関数で`contacts.create`のviewファイルを表示させています。

```ContactFormController.php
 public function create()
    {
        return view('contacts.create');
    }
```

#### ページ表示

そして対象のviewファイル`resources/views/contacts/create.blade.php`を作成すれば、作成したリンク`<a href="{{ route('contacts.create')}}">新規登録</a>`をクリックした際にこの対象viewファイルに遷移します。