【Laravel】個人メモ

## マイグレーションコマンド

### 一括マイグレーション
```php5
php artisan migrate
```

### マイグレーションのロールバック
```php5
php artisan migrate:rollback
```

### 最後のマイグレーションをロールバック
```php5
php artisan migrate:rollback --step=1
```

:::note info
任意のマイグレーションを選んでロールバックしたい場合、DBのmigrationsテーブルから該当レコードを手動で削除し、その後`php artisan migrate`を実行する。
ただし、これは一般的には推奨されない方法。
:::




### マイグレーションのリフレッシュ
```php5
php artisan migrate:refresh
```


### マイグレーション状況を確認する
```php5
php artisan migrate:status
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943997/15e1497a-da25-c8d1-745f-1475978d8c62.png)


### 特定のテーブルのみマイグレーションする
```php5
php artisan migrate:refresh --path=/database/migrations/2024_12_21_072553_create_images_table.php
```


## シーダーコマンド
### まとめてシーダー実行
```php5
php artisan db:seed
```




## オブジェクトから特定のフィールドを削除
```php5
$flow = DB::table('flows')
->where('id', $id)
->select('title', 'url', 'first_question_id', 'x', 'y', 'zoom', 'category')
->first();
        
// categoryを取得し、flowオブジェクトから削除
$category = $flow->category;
unset($flow->category);
```


## 1ユーザの中で重複していないことをチェック
```php5
public function addFlow(Request $request){
    $user_id = Auth::id();
    $validatedData = $request->validate([
        'initialTitle' => ['required', 'string', 'max:50'],
        // 入力したURL名が既に登録済みか確認
        // 別ユーザが同一のURL名を使っている場合はOK。（同じユーザが既に同名のURLをつかっていないかチェック）
        'initialUrl' => [
            'required', 'string', 'max:15', 'alpha_num:ascii',
            Rule::unique('flows', 'url')
                ->where(function ($query) use ($user_id) {
                    return $query->where('user_id', $user_id); // user_id スコープを追加
                })],
    ]);
}
```

## トランザクション
```php5
public function addFlow(Request $request){

    // トランザクション開始
    DB::beginTransaction();

    try {
        $flow_id = DB::table('flows')->insertGetId([
            'title' => $validatedData['initialTitle'],
            'url' => $validatedData['initialUrl'],
            'user_id' => $user_id,
        ]);

        // 3つのテーブルに関連レコードを挿入
        foreach (['questions', 'results', 'edges'] as $table) {
            DB::table($table)->insert(['flow_id' => $flow_id]);
        }
        DB::commit();
        return to_route('flow.index', ['id' => $flow_id]);

    } catch (\Exception $e) {
        DB::rollBack();
        
        \Log::error($e->getMessage().'(errLine.'.$e->getLine().')');
        
        return redirect()->route('dashboard');
    }
}
```


## GroupByによる集約
```php5
public function getTotalling() {
    $user_id = Auth::user()->id;
    try {
        $flow_records = DB::table('flows')
        ->leftJoin('achievements', 'flows.id', '=', 'achievements.flow_id')
        ->select(
            'flows.id',
            'flows.title',
            'flows.category',
            DB::raw('COUNT(achievements.id) as total'))
        ->where('flows.user_id', $user_id)
        ->groupBy('flows.id', 'flows.title','flows.category' )
        ->get();

        $flows = $flow_records ?? [];        
    }
    catch (\Exception $e) {
        \Log::error($e->getMessage() . ' (errLine: ' . $e->getLine() . ')');
        $flows = []; // エラー時のデフォルト値
    }
    return Inertia::render('Owner/Totalling/Totalling', [
        'flows' => $flows
    ]);
}
```


## マイグレーションとモデルの作成コマンド
```
php artisan make:model Flow --migration
```
:::note info
model名はキャメルケースで単数形
:::




## マイグレーションファイルの記述の詰め合わせ

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

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('flows', function (Blueprint $table) {
            $table->id();
            $table->string('title', 50)->nullable();
            // Null許容
            $table->string('first_question_id')->nullable()->comment('最初の質問ID');
            $table->float('x', 8, 2)->default(0);
            $table->unsignedBigInteger('user_id');
            $table->timestamps();
            // 外部キー設定
            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
        });
    }

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