Symfony handson lesson-2

# データベースについて
SymfonyではDoctrine ORM（Object-Relational Mapping）を利用
- https://fadocodecamp.com/running-a-mysql-database-with-docker-compose-a-beginners-guide/
- ORMでありSQL不要
- オブジェクトのメソッドでDB操作
- オブジェクトとRDBを対応付け（マッピング）

# Docker
コンテナ型のアプリケーション実行環境
- 仮想環境を作成・配布・実行するプラットフォーム
    - アプリケーション管理・デプロイを容易に
    - ハードの環境やOSに関係無く開発可能
    - 環境のインストール等が不要

コンテナ型
- OSが一つのみ存在しており，OSの中にアプリケーション実行するための領域が複数存在
- 不要になったイメージ（コンテナ）をシステム等やOSに影響を与えず削除できる
    - 最小限のLinux環境で動作している
- 複数バージョンを切り替えたりできる

Dockerはアプリケーションを分離して実行できるようにする
- イメージ
    - MySQLやPostgresなど（クラスのようなもの）
- コンテナ
    - イメージを使用してコンテナを作成（インスタンスのようなもの）

Docker Compose
- マルチコンテナのDockerアプリケーションを実行するツール
- Yamlファイルでアプリケーション作成・管理

# SQLサーバを実行・DB作成
composer require symfony/orm-packを実行
- No を選択しないとエラーになった
    - service "database" has neither an image nor a build context specified: invalid compose project

docker-compose.yamlを記述し
```
$docker compose up
```
実行後，localhost:8080にアクセスできるようになる
- Docker Desktopを起動している必要あり

.envを編集
- DATABASE_URL="mysql://root:root@127.0.0.1:3306/symf6-handson?serverVersion=mariadb-10.8.3&charset=utf8mb4"
    - {service}://{user}:{password}@127.0.0.1:{port}(docker-compose.yml)/{server-name}?serverVersion={version}(docker-compose.yml)&charset={charset}
- https://symfony.com/doc/current/doctrine.html#configuring-the-database

config/packages/doctrine.yamlを編集
- server_version: '10.8.3'

symfony console list doctrine
- 一覧表示

DB作成
- symfony console doctrine:database:create
- localhost:8080に追加されているか確認


# エンティティ作成
symfony console list make
symfony console make:entity
- エンティティ名を入力しEntity・Repositoryを作成
- カラム名，データタイプ，文字数，Nullable等も入力していく
    - ?でヘルプ
```
Main Types
  * string
  * text
  * boolean
  * integer (or smallint, bigint)
  * float

Relationships/Associations
  * relation (a wizard 🧙 will help you build the relation)
  * ManyToOne
  * OneToMany
  * ManyToMany
  * OneToOne

Array/Object Types
  * array (or simple_array)
  * json
  * object
  * binary
  * blob

Date/Time Types
  * datetime (or datetime_immutable)
  * datetimetz (or datetimetz_immutable)
  * date (or date_immutable)
  * time (or time_immutable)
  * dateinterval

Other Types
  * ascii_string
  * decimal
  * guid
```

## Entity Class
アノテーションする必要あり
- リポジトリを指定

カラム列
- private定義
- ゲッタ・セッタ定義

ID（主キー）
- #[ORM/Id]

## Migration
symfony console make:migration
```
Next: Review the new migration "migrations/Version20230514045349.php"
 Then: Run the migration with php bin/console doctrine:migrations:migrate
 See https://symfony.com/doc/current/bundles/DoctrineMigrationsBundle/index.html

```

Versionxxxx.php
- AbstractMigrationを拡張
- getDescription()
    - 行った操作を記述：Ex. Create the micro_post table
- up()
    - テーブル作成
- down()
    - テーブル破棄

なぜMigrationを行うのか
- DB変更やテーブル追加等した後，アプリがサーバにデプロイする前に，DB変更を適用する
- SQLを手動で実行してログインする必要が発生
- Migrationがなければ，ローカル上で動作していてもサーバ上で手動でプルしたりしないと動作しない

doctorin_migrations.yaml
- https://symfony.com/bundles/DoctrineMigrationsBundle/current/index.html

Migration実行
- symfony console doctrine:migrations:status
    - 現在のMigrationの状態が閲覧可能
- symfony console doctrine:migration:migrate
- この状態でhttp://localhost:8080/で確認するとテーブルが反映されている
    - doctrine_migration_versionsも作成
        - どのMigrationが実行されたか確認

Migrationを戻すことも可能
- symfony console doctrine:migrations:migrate --help
- symfony console doctrine:migrations:migrate prev で戻す

## Repository Class
Fixtures
- データ追加したり任意の箇所にテスト用のデータ作成
- テスト用データやダミーデータ作成に便利

Fixtures 使い方
- composer require --dev orm-fixturesでインストール
    - https://symfony.com/bundles/DoctrineFixturesBundle/current/index.html
- src/DataFixturesの中ののFixturesファイル
    - ロードメソッドで作成，新しくEntityを作成しDB保存
    - FixturesBundleは特定コマンド実行時に以下のようなコード処理を行うことで新しいダミーデータ作成してDB保存等を行える
        - symfony console doctrine:fixtures:load
        - また，これは編集済みのデータをリセットも可能

```Fixtures.php ex
class AppFixtures extends Fixture
{
    public function load(ObjectManager $manager): void
    {
        // Entityインスタンス作成
        $product = new Product();
        // Entityでのクエリ実行宣言
        $product = setItemName('sample');
        $manager->persist($product);

        // クエリ実行
        $manager->flush();
    }
}

```

Doctrineでデータを扱う場合は
- Entity ManagerでPersist Flush
- でDBへ反映

リポジトリ
- データ取得のためのクエリ作成
- DBからデータをフェッチする方法を抽象化
    - すでに追加・削除は存在（add(save)/delete）
    - 複雑なクエリ例も存在

リポジトリ代表的メソッド
- findAll すべてのレコード取得
- find(1) ID=1のレコード取得
- findOneBy(['title' => 'xxx']) 条件合致レコードを一つ取得
- findBy(['title' => 'xxx']) 条件合致レコードをすべて取得
- 呼び出すとクエリとしてProfilerに記録されるので見てみると良い
    - クエリタイムも同様

# Auto Fetching Entity
https://symfony.com/doc/current/doctrine.html#fetch-automatically
composer require sensio/framework-extra-bundle

https://127.0.0.1:8000/micro-post/1にアクセス
- 単一のEntityをフェッチする，paramコンバーターで可能

```Controller
    #[Route('/micro-post/{post}', name: 'app_micro_post_show')]
    public function showOne(MicroPost $post): Response {
        dd($post);
    }
```