Laravelの使い方(View,Controller,Modelについて)

# laravelの使い方

## 1.プロジェクトを作成する。
①htdocsフォルダ内にプロジェクト用のフォルダを作成する。
②VSCodeで①で設定したフォルダを開く。
③ターミナル画面で以下を実行する。
```
composer create-project "laravel/laravel=バージョン" プロジェクト名
```
　例：composer create-project "laravel/laravel=9.*" プロジェクト名
④VSCodeで①のフォルダを開いた時に、Laravelプロジェクトのフォルダやファイルが表示されたらOK。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3323019/94f6b24d-3486-0749-f41c-44b9f501c60d.png)
⑤ブラウザで以下のパスを入力して表示されるか確認する。
localhost/フォルダ名/public/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3323019/98109304-58d2-0d6f-7cb7-d014993e247d.png)

## 2.タイムゾーンを変更する。
現在時間設定がUTCになっているので、日本時間に変更する。
ファイルの場所：config/app.php
```app.php
     'timezone' => 'UTC',             //変更前
     'timezone' => 'Asia/Tokyo',      //変更後
```

## 3.viewを作成する。
①resources/viewsの直下にフォルダを作成する。
②1で作成したフォルダ内にファイルを作成する。
　**※ファイル名は、"〇〇.blade.php"にする。**
（laravelはBladeというテンプレートエンジンを利用してビューを出力するため。）
　テンプレートエンジン...PHPなどのサーバーサイドの言語とHTMLを合体させてビューを出力する仕組み。
③2で作成したファイル内には通常通り、HTMLやPHPを記述する。
　@ifや@foreachのように、@をつけるだけでif文やforeach文などを使うことが可能。
　PHPのコードを{{}}で囲むことで変数の値などを表示することも可能。（例：{{ $get->name }}）

## 4.contollerを作成する。
①VSCodeでターミナルを開く。（コマンドプロンプトでも可能。）
②カレントディレクトリをlaravelのプロジェクトのディレクトリ（1.で作成したフォルダ）にする。
```
cd laravelのプロジェクトのディレクトリまでの相対パスか絶対パス
```
③ターミナルで以下のコマンドを実行する。
```PHP
php artisan make:controller 任意のコントローラー名
```
　**※コントローラー名は"〇〇Controller"にする。**
　〇〇の部分はモデル名に合わせる。
　コントローラは単数形（例：postController）と複数形（例：postsController）のどちらでもOK。
④以下のように表示されればok。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3323019/77c0c25b-c9e9-ec94-ab97-73a748e9a5d5.png)
**※作成したコントローラは、app/Http/Controllersフォルダ内に配置される。**
⑤app/Http/Controllersフォルダ内にできた、〇〇Controller.phpを開き、以下のコードを書く。
```〇〇Controller.php
class 〇〇Controller extends Controller {
     //
     // viewを表示するための処理
     public function 任意のメソッド名() {        
         return view('posts.index');
     }
}
```
　**・アクション（作成するメソッド）はページや機能ごとに作成する。**　
　・任意のメソッド名：ページ名や機能名を書く。
　・view('表示したいビュー')：
　　viewヘルパーと呼ばれる。（ヘルパー...Laravelで好きな場所から呼べる関数のこと。）
　　viewを表示する。
　・引数の書き方：
　　resources/viewsを省略し、'view直下のフォルダ名.表示するファイル名'と書く。.blande.phpは不要。
　　例：resources/views/posts/index.blade.php→ view('posts.index')

### コントローラを作成するコマンドのオプションについて
・`--resource`をつけることで、CRUD処理に必要なアクション（index、create、Storeなど）
　を自動で作成してくれる。
```
php artisan make:controller コントローラ名 --resource
```

・`--model:モデル名`をつけることで、コントローラに`Use App\Models\モデル名`
　が追加された状態で作成される。
```
php artisan make:controller コントローラ名 --model=モデル名
```

・オプションは複数つけて実行できる。
```
php artisan make:controller コントローラ名 --resource --model=モデル名
```

## 5.ルーティングを設定する。
ルーティングのファイルは、routes/web.php　になる。
①web.php内に以下のコードを記述する。
```PHP
// ルーティングを設定するコントローラを宣言する
use App\Http\Controllers\〇〇Controller;

...

Route::HTTPリクエストメソッド名('アプリケーションンのルートURL', [コントローラ名::class, 'アクション名']);
例：Route::get('/posts', [〇〇Controller::class, 'index'])->name('posts.index');
```
　・HTTPリクエストメソッド名：getやpostのこと。Laravelは他のHTTPリクエストメソッドも指定できる。
　・アプリケーションのルートURL：
　　ローカル環境の場合...http://localhost/、https://localhost:8000など
　　本番環境の場合...http://www.test.comなど
　・name()メソッドを使用することで、ルートに名前を付けれる。
```PHP
Route::get('/posts', [PostController::class, 'index'])->name('posts.index');
```
※名前は'基準となるURL(localhost/htdocs直下のフォルダ名/Public/〇〇←これ).アクション名'
　とするとわかりやすい。
※名前付きルートを呼び出す時は、Laravelのroute()ヘルパーを使用する。
```PHP
<!-- 通常のリンク -->
<a href="/posts">通常のリンク</a>

<!-- 名前付きルート -->
<a href="{{ route('posts.index') }}">名前付きルート</a>
```
②ブラウザでリンクが正しく設定されているか確認する。
パス：localhost/htdocs直下のフォルダ名/Public/〇〇
※なぜ上記のパスでviewが表示されるか？
　・最初にアクセスしたときは、public/index.phpを通ってからルーティングされるから。
　・Laravelは**Publicフォルダがwebサーバーから直接アクセスできる唯一のフォルダ**。
　　=webサーバーが最初にリクエストを受けるディレクトリで、index.phpですべてのリクエストをアプリケーションにルーティングするから。
　参考サイト：
　https://codezine.jp/article/detail/11370
　https://qiita.com/minato-naka/items/f05b023950ce544a8bec

### ルーティングを制限する方法
コントローラの使わないアクションを削除した場合、ルーティングを制限することができる。
```web.php
Route:resource('/goals', GoalContoller::class)->only(['使用するアクション名','使用するアクション名']);
```
only()を使用する。
引数は、使用するアクション名を配列で記述する。

### 複数のモデルをコントローラに渡す方法
URLの部分でモデル名を`.`でつなげて記述する。（Route::resource()メソッドで一括設定する場合）
```web.php
Route:resource('goals.todos', GoalContoller::class);
```

コントローラにモデルを複数渡すと、URLは入れ子のようになる。
|  HTTPリクエストメソッド |  URL  |  アクション  |  ルート名  |
| ---- | ---- | ---- | ---- |
|  POST  |   goals/{goal}/todo  |  store  |  goals.todo.store  |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3323019/5a10c887-ed2a-06b9-d1fe-e9ea05dd2ce0.png)


## 6.データベースと接続する。
①.envファイルで接続するデータベース名などを設定する。
　場所：laravelのプロジェクトのフォルダ直下
②以下のように変更する。
```.env
DB_DATABASE=接続するデータベース名
DB_USERNAME=MySQLのユーザー名
DB_PASSWORD=MySQLのパスワード
```
補足：2で設定した環境変数は、config/database.phpで使用されている。(mysqlと検索すると出てくる。)
③VSCodeのターミナルで以下のコマンドを実行する。
```
php artisan migrate
```
④以下のように表示されればok。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3323019/3209412e-5efc-886d-4789-ce902cc55e2a.png)
⑤データベース内に新しくテーブルができていることを確認する。
　以下のようなテーブルができていればok。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3323019/e44018d0-2a0f-6af0-5bbb-109b03a8dd41.png)

## 7.モデルを作成する。
①VSCodeのターミナルで以下のコマンドを実行する。
```PHP
php artisan make:model モデル名
```
※モデル名はテーブル名を単数形にした形でつける。例：テーブル名...posts、モデル名...post
②以下のように表示されればok。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3323019/94ab6dd3-e031-7232-5084-82ea73a69b19.png)
③app/Models/ にモデル名.phpが作成されているか確認する。
　・HasFactory：テスト用のデータベースのダミーデータを大量に作成する関数が集まったもの。
　　以下のフォルダ内にソースファイルが置いてある。
　　vender/laravel/framework/src/Illuminate/Database/Eloquent/Factories

## 8.テーブルを作成する。
①マイグレーションファイルを作成する。　
　VSCodeのターミナルで以下のコマンドを実行する。
```PHP
php artisan make:migration マイグレーションファイル名 --create=作成するテーブル名 
```
　※マイグレーションファイル名：
　　マイグレーションファイルで何をするかわかるような名前をつける。（例：create_posts_table）
②以下のように表示されればok。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3323019/eb33c637-87a6-378b-c70d-2df3a9697cb0.png)
③1で作成したマイグレーションファイルを編集してカラムを設定する。
　マイグレーションファイルは以下にある。
　database/migrations/****_**_**_******_create_posts_table.php
　（****は作成した日の日付が命名される。）
④以下のコードにてカラムを追加する。
```PHP
    public function up()
    {
        Schema::create('テーブル名', function (Blueprint $table) {
            $table->id();                      // id(デフォルト)
            $table->string('列名');            // 追加例
            $table->text('列名');              // 追加例
            $table->timestamps();              // created_atとupdated_at(デフォルト)
        });
    }
```
⑤マイグレーションを行う。
　**※コマンドを実行する前に、XAMPPでMySQLを起動しているか確認する。**
　VSCodeのターミナルで以下のコマンドを実行する。
```PHP
php artisan migrate
```
⑥以下のように表示されればok。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3323019/15e0cfc0-aa13-34de-5ab5-42bc7b0558a9.png)
⑦PHPMyAdminで列が追加されているか確認する。

### モデルを作成する時のコマンドについて
・`-m`をつけることでモデルとマイグレーションファイルを一緒に作成してくれる。
```
php artisan make:model -m モデル名
```

### カラムに外部キーを設定する場合
マイグレーションファイルに以下のように追加する。
パス：database/migrations/...table.php
```
$table->foreignId('カラム名')->constrained()->cascadeOnDelete();
```
・`foreignID('カラム名')->constrained()`：外部キーを設定する
・`cascadeOnDelete()`：特定のデータを消すと、他のテーブルでそのデータを持っているレコードも自動で消える。
　例：以下のようなテーブルがあった場合、
　Usersテーブルのid：1のレコードを消すと、OrderDetailテーブルのUser_id：1のレコードも自動で消える。
![侍テーブル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3323019/bbae5be4-c97e-b0f9-a898-ce9aa5d21f45.png)

```...table.php
// ↓例
public function up()
	{
		Schema::create('goals', function (Blueprint $table) {
			$table->id();
			$table->foreignId('user_id')->constrained()->cascadeOnDelete();	// これ
			$table->timestamps();
		});
	}
```

### 1対多のリレーションシップを設定する
テーブルに外部キーを設定しただけでは、リレーションシップが設定できていない。

①1対多 の `1` のモデルに以下を追加する。パス：app/Models/モデル名.php
```1モデル名.php
public function 多モデル名() {
    return $this->hasMany(多モデルクラス名::class);
}
```
```user.php
// 例：1→userテーブル　多→orderDetailテーブル
     public function orderDetails() {
         return $this->hasMany(OrderDetail::class);
     }
```
・`hasMany()`を使用することで、Userは複数のOrderDetailを持っていることを設定できる。
・`$user->orderDetails()`と記述するだけで、特定のユーザーの**すべて**の
　orderDetailを取得できる。

②1対多 の `多` のモデルに以下を追加する。パス：app/Models/モデル名.php
```多モデル名.php
public function 1モデル名() {
    return $this->belongsTo(1モデルクラス名::class);
}
```
```oderDetail.php
// 例：1→userテーブル　多→orderDetailテーブル
     public function user() {
         return $this->belongsTo(User::class);
     }
```
・`belongsTo()`を使用することで、1つのorderDetailが1つのuserに属することを設定できる。
・`$orderDetail->user->name`と記述するだけで、orderDetailが属するuserの名前を取得できる。


## 参考サイト
Laravel：Route::resourceの「only」と「except」でリクエストを制限するLaravel：Route::resourceの「only」と「except」でリクエストを制限する
http://raining.bear-life.com/laravel/routeresource%E3%81%AE%E3%80%8Conly%E3%80%8D%E3%81%A8%E3%80%8Cexcept%E3%80%8D%E3%81%A7%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%82%92%E5%88%B6%E9%99%90%E3%81%99%E3%82%8B