laravel 入門

# 環境構築
1. 以下コマンドを実行しlaravelコマンドを使えるようにする

```cmd:cmd
composer global require laravel/installer laravel --version
```

2.この辺入れとく

```cmd:cmd
yum install php php-mbstring
yum -y install php-zip
yum install php-xml 
```

3.プロジェクト作成

```cmd:cmd
 laravel new projectA 
```

4.書き込み権限が必要なので以下実行

```cmd:cmd
chmod -R  777 bootstrap/cache
chmod -R 777 storage
```

5.bootstrap入れるなら

```cmd:cmd
composer require twbs/bootstrap
```

6.composer.json内を環境に合わせて修正

#laravelを使用する

1.table名は複数形(modelを使う場合、後からphpでテーブルを指定しないけない)

2.関数名

- 登録 = create
- 削除 = delete

#artisan
1. 一覧確認

```cmd:cmd
php artisan list
```

2. model作成

```cmd:cmd
 php artisan make:model Test
```

3. controller作成

```cmd:cmd
php artisan make:controller UserController
```

4. service作成

```cmd:cmd
php artisan make:service TestService
```

#dbへ接続

1.artisanコマンドを使用しテーブル作成
テーブル名:tests(laravelの命名規則としてテーブル名は複数形)

```cmd:cmd
php artisan make:migration create_tests_table
```

2.database設定

 - database.phpファイル変更
 - .envファイル変更

3.認証方式変更

```sql:sql
SELECT user, host, plugin FROM mysql.user;

-- 認証方式をcaching_sha2_passwordからmysql_native_passwordに変更（caching_sha2_passwordはlaravelでエラーになるため）
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'verysecret';
```

4.テーブル作成

```cmd:cmd
php artisan migrate
```
5.laravelアプリからDBへ接続できるか確認

```cmd:cmd
php artisan tinker;
```

tinker実行によりphpがコマンドラインから使用できるようになるためmodelを使用しデータを取得してみる

```cmd:tinker
use App¥User;
User::first();
exit;
```

 - apiの関数の動きを軽く確認する場合
 
例：App\Http\Controllers\Api\User\commonディレクトリ内のUco01wController.php内のusername関数を呼び出す

```cmd:tinker
$uco01w = new App\Http\Controllers\Api\User\common\Uco01wController

$uco01w->username()
```


#model

1.model作成
以下コマンドでapp直下にTest.phpが作成される
命名規則としてはテーブル名が複数形のためモデルは単数形になる

```cmd:cmd
php artisan make:model Test
```

#controllerからdb接続
```php:TestController.php
use App\Test;  // Testモデルを呼び出す(classの上に記述)

$test = Test::first(); // 1件取得
```


#キャッシュクリア

```
php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear
```

#　デバッグバー表示

- デバッグツールダウンロード

```cmd:cmd
composer require barryvdh/laravel-debugbar
```
 
- 以下編集

```php:app.php
'debug' => env('APP_DEBUG', true),
```

```text:env
APP_DEBUG=true
```

-ブラウザ下に以下が出てくる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496171/34fc84e1-41a4-044c-1311-1e8d38994877.png)

#sassを使用

 - コンパイル先指定

```js.webpack.mix.js
mix.js('resources/js/app.js', 'public/js')
	.sass('resources/sass/app.scss', 'public/css')
	.sass('resources/sass/header.scss', 'public/css')
	.sass('resources/sass/pages/fr01u1.scss', 'public/css/pages');
```

# 既存DBからマイグレーションファイル作成

 - パッケージのインストール

```cmd:cmd
composer require --dev "xethron/migrations-generator"
```

 - 作成コマンド

```cmd:cmd
php artisan migrate:generate --ignore="users, password_resets"
```
Next Batch Number is: 3. We recommend using Batch Number 0 so that it becomes the "first" migration [Default: 0] は０を選択

参考サイト　https://qiita.com/yukibe/items/4160f6522cab8ec40f59

#既存テーブルからmodel作成

 - パッケージのインストール

```cmd:cmd
composer require krlove/eloquent-model-generator --dev
```

 - model作成コマンド

```cmd:cmd
例：
App¥Modelsの中に「table_tests」テーブルのモデル「TableTest」を作成する

php artisan krlove:generate:model TableTest --table-name=table_tests --output-path=Models --namespace=App¥Models --no-timestamps
```

参考資料：
日本語手順
https://oki2a24.com/2019/06/06/generate-model-from-existing-database-in-laravel-5-5/

公式(github)
https://github.com/krlove/eloquent-model-generator


#シーダーの作成

1.シーダーファイルの作成

```cmd:cmd
# 複数形
php artisan make:seed TestsTableSeeder
```

```php:TestsTableSeeder.php
use Illuminate\Support\Facades\DB;

public function run()
    {
        DB::table('tests')->insert([
			'name' => str_random(5),
		]);
    }
```
    
2.app/database/seeds/DatabaseSeeder.phpを編集

```php:DatabaseSeeder.php
$this->call(TestTableSeeder::class);
```

```cmd:cmd
php artisan db:seed
```

# ダミーデータの作成

 - fakerのインストール

```cmd:cmd
composer require fzaninotto/faker --dev
```

 - testsテーブルにダミーデータを作成（Testsのモデル作成必要）

```php:TestsTableSeeder

<?php

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Faker\Factory as Faker;
use App\Models\Test;

class TestsTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        //一括削除
        Test::truncate();

        // フェイクデータを生成するジェネレータを作成
        $faker = Faker::create('ja_JP');

        for ($i = 0; $i < 1000; $i++) {
            # code...
            DB::table('tests')->insert([
                // 'name' => str_random(5),
                // 'name' => $ramdomName,
                'name' => $faker->name,
            ]);
        }
    }

```

 - seeder実行

```cmd:cmd
php artisan db:seed;
```

# factoryを使用してダミーデータを作る

 - ダミーデータを日本語化
```php:app.php
'faker_locale' => 'ja_JP',
```

 - factoryを作成
 
```cmd:cmd
php artisan make:factory TestFactory
```

 - factoryを編集

```php:TestFactory.php

<?php

/** @var \Illuminate\Database\Eloquent\Factory $factory */

use Faker\Generator as Faker;

$factory->define(App\Models\Test::class, function (Faker $faker) {
    return [
        'name' => $faker->name,
    ];
});

```

modelでTestを使うように修正指定しています。

 - seederでfactoryを使用する
 
```TestsTableSeeder.php

//factoryを利用（Testsテーブルにダミーデータを1000件作成）
factory(Test::class, 1000)->create();

```

```cmd:cmd
php artisan db:seed
```

## FormRequest
- エラー発生時のレスポンス
```
protected function failedValidation(Validator $validator)
{
    throw new HttpResponseException(
        response()->json([
            'message' => $validator->errors()->toArray(),
        ], 403)
    );
}
```

## 複合プライマリキーのsave
- 以下の記述で複合主キーに対応できる
- increment=falseがない場合`local.ERROR: Illegal offset type`になるので注意
```php
trait HasMultipleKeysRelationships
{
    public function hasOneMultipleKeys($related, array $foreignKeys, array $localKeys, $relation = null): HasOneMultipleKeys
    {
        // If no relation name was given, we will use this debug backtrace to extract
        // the calling method's name and use that as the relationship name as most
        // of the time this will be what we desire to use for the relationships.
        if (is_null($relation)) {
            $relation = $this->guessHasOneOrManyRelation();
        }

        $instance = $this->newRelatedInstance($related);

        return $this->newHasOneMultipleKeys(
            $instance->newQuery(),
            $this,
            $foreignKeys,
            $localKeys,
            $relation
        );
    }

    public function hasManyMultipleKeys($related, array $foreignKeys, array $localKeys, $relation = null): HasManyMultipleKeys
    {
        // If no relation name was given, we will use this debug backtrace to extract
        // the calling method's name and use that as the relationship name as most
        // of the time this will be what we desire to use for the relationships.
        if (is_null($relation)) {
            $relation = $this->guessHasOneOrManyRelation();
        }

        $instance = $this->newRelatedInstance($related);

        return $this->newHasManyMultipleKeys(
            $instance->newQuery(),
            $this,
            $foreignKeys,
            $localKeys,
            $relation
        );
    }
}

##################### 使用側のクラス 上記のtraitクラスをクラス内でuseして使用

    public function userAddress(): HasOneMultipleKeys
    {
        return $this->hasOneMultipleKeys(
            Address::class,
            ['user_id', 'post_id'],
            ['user_id', 'post_id'],
        );
    }
```

- 参考：https://qiita.com/derasado/items/ff692411ef50f222af32