Laavel+Doctine에서 Proisma처럼 마이그레이션 및 DB 관리 자동화

개시하다


지금까지 ORM을 싫어했던 저는 업무상 프리시스마를 만나 어떤 언어든 ORM을 쓰고 싶은 사람이 되었습니다.(Eloquent를 좋아하지 않아서 그런지 웃음)
ORM이라지만 특히 감동적인 기능은 마이그레이션용 SQL을 패턴에서 차별화해 생성할 수 있는 기능이다.
Laavel+Eloquent 개발에서는 모델 측 파일을 업데이트할 때 마이그레이션 파일을 자동으로 생성하는 기능이 없는 것으로 알고 있습니다.(있으시면 댓글로 남겨주세요.🙏)
그래서 PHP도 자동으로 ORM을 생성할 수 있을 것 같아서 Doctine라는 ORM을 찾아봤는데 정의 파일과 DB 검사 후 차별화된 기능이 있습니다.
이 글은 Laavel의 프로젝트에서 Doctine을 가져오고 Doctine을 통해 DB 관리를 하는 방법을 소개한다.

이 기사를 통해서 알게 된 것들.

  • Laavel에 Doctine 도입
  • Doctine을 Laavel로 이동할 때의 해피 점
  • 마이그레이션 자동 생성 및 DB 업데이트
  • 전제 조건


    Laravel 7.x ← LTS 지원 종료!!너무 낡아서m
    laravel-doctrine/migrations: "^2.3"
    laravel-doctrine/orm: "^1.6"
    Mysql 5 ~
    이 글에서 나는 가능한 한 기존 프로젝트를 도입하는 방법을 의식하지만 기존 프로젝트의 환경과 버전에 따라 다양한 문제가 발생할 수 있다.만약 열성적인 일이 있다면 제 평론을 꼭 들어주세요. 제가 아는 범위 내에서 최선을 다해 대답하겠습니다.

    Doctine 정보


    Doctine에 대해서는 다음 링크 등을 참조하십시오.
    https://www.doctrine-project.org/
    https://engineering.otobank.co.jp/entry/2017/01/31/151121
    Synfony 기본 ORM과 같습니다.물론 프레임과 상관없이 PHP도 가져올 수 있다.
    매우 큰 특징으로 Doctrine의 구조는 PHP에 대한 클래스 정의 모델을 모방할 수 있다는 것이다.

    laavel-doctrine


    Laavel에서 Doctrine을 가져올 때 Laavel의 다른 기능, 디렉터리, 파일의 구조가 일치하도록 composier의 패키지로 준비한 laavel-doctrine을 추천합니다.설정 등을 Laavel 스타일로 설정할 수 있습니다.

    사과할 일


    많이 노력했지만 시뮬레이션 이외의 방법으로는 패턴을 정의하지 못했다.이 글에서는 의성의태에 근거한 모델만 소개하였으니 양해해 주십시오🙏

    Ⅰ. ravel-doctrine 설치


    먼저 Laavel 프로젝트에 laavel-doctrine을 설치합니다.
    프로젝트의 루트 디렉터리에서 다음 명령을 실행하십시오
    프로젝트 루트 디렉토리
    composer require laravel-doctrine/orm:"^1.6" laravel-doctrine/migrations
    
    이 버전은 Laavel 7로 지정됩니다.x계 버전을 지정합니다.자신의 환경에 맞는 버전으로 설치하세요.

    가장 적합한 곳


    의존 관계의 문제로 인해 나는 줄곧 아래의 잘못에 시달렸다.
    composier입니다.lock를 삭제하여 설치를 진행하여 문제를 해결했습니다.
    하지만 다른 의존 관계에 영향을 미칠 수도 있으니 스스로 책임지세요.
    어려운 사람이 있으면 한번 해 보세요.
    삽입 오류
    Your requirements could not be resolved to an installable set of packages.
    
      Problem 1
        - Conclusion: don't install laravel-doctrine/orm 1.6.1 (conflict analysis result)
        - doctrine/orm[v2.7.0, ..., v2.7.2] require doctrine/common ^2.11 -> satisfiable by doctrine/common[v2.11.0, ..., 2.13.x-dev].
        - doctrine/common[v2.11.0, ..., 2.13.x-dev] require doctrine/inflector ^1.0 -> found doctrine/inflector[v1.0, ..., 1.4.x-dev] but the package is fixed to 2.0.3 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
        - doctrine/orm[v2.7.3, ..., 2.7.x-dev] require doctrine/inflector ^1.0 -> found doctrine/inflector[v1.0, ..., 1.4.x-dev] but the package is fixed to 2.0.3 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
        - doctrine/orm[v2.6.0, ..., 2.6.x-dev] require symfony/console ~3.0|~4.0 -> found symfony/console[v3.0.0-BETA1, ..., 3.4.x-dev, v4.0.0-BETA1, ..., 4.4.x-dev] but the package is fixed to v5.2.4 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
        - doctrine/orm[2.10.0, ..., 2.11.x-dev] require symfony/polyfill-php72 ^1.23 -> found symfony/polyfill-php72[dev-main, v1.23.0, 1.23.x-dev (alias of dev-main)] but the package is fixed to v1.22.1 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
        - laravel-doctrine/orm[1.6.2, ..., 1.6.x-dev] require doctrine/inflector ^1.4 -> found doctrine/inflector[1.4.0, ..., 1.4.x-dev] but the package is fixed to 2.0.3 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
        - laravel-doctrine/orm[1.7.0, ..., 1.7.x-dev] require illuminate/auth ^8.0 -> found illuminate/auth[v8.0.0, ..., 8.x-dev] but these were not loaded, likely because it conflicts with another require.
        - Root composer.json requires laravel-doctrine/orm ^1.6 -> satisfiable by laravel-doctrine/orm[1.6.0, ..., 1.7.x-dev].
        - Conclusion: don't install doctrine/persistence[2.2.1] | install one of doctrine/persistence[1.3.7, 1.3.8] (conflict analysis result)
        - Conclusion: don't install doctrine/persistence[2.2.0] | install one of doctrine/persistence[1.3.7, 1.3.8] (conflict analysis result)
        - Conclusion: don't install doctrine/persistence[2.3.x-dev] | install one of doctrine/persistence[1.3.7, 1.3.8] (conflict analysis result)
        - Conclusion: don't install doctrine/persistence[2.2.x-dev] | install one of doctrine/persistence[1.3.7, 1.3.8] (conflict analysis result)
        - Conclusion: don't install doctrine/persistence 1.3.7 (conflict analysis result)
        - Conclusion: don't install one of doctrine/orm[2.8.x-dev], doctrine/persistence[1.3.8] | install doctrine/persistence[2.2.3] (conflict analysis result)
        - Conclusion: don't install doctrine/persistence 2.2.3 (conflict analysis result)
        - laravel-doctrine/orm 1.6.0 requires doctrine/orm ^2.6|^2.7 -> satisfiable by doctrine/orm[v2.6.0, ..., 2.11.x-dev].
        - Conclusion: don't install doctrine/orm 2.9.x-dev (conflict analysis result)
        - Conclusion: don't install doctrine/orm 2.8.0 (conflict analysis result)
        - Conclusion: don't install doctrine/orm 2.8.1 (conflict analysis result)
        - Conclusion: don't install doctrine/orm 2.8.2 (conflict analysis result)
        - Conclusion: don't install doctrine/orm 2.8.3 (conflict analysis result)
        - Conclusion: don't install doctrine/orm 2.8.4 (conflict analysis result)
        - Conclusion: don't install doctrine/orm 2.8.5 (conflict analysis result)
        - Conclusion: don't install doctrine/orm 2.9.0 (conflict analysis result)
        - Conclusion: don't install doctrine/orm 2.9.1 (conflict analysis result)
        - Conclusion: don't install doctrine/orm 2.9.2 (conflict analysis result)
        - Conclusion: don't install doctrine/orm 2.9.3 (conflict analysis result)
        - Conclusion: don't install doctrine/orm 2.9.4 (conflict analysis result)
        - Conclusion: don't install doctrine/orm 2.9.5 (conflict analysis result)
        - Conclusion: don't install doctrine/orm 2.9.6 (conflict analysis result)
        - doctrine/orm 2.8.x-dev requires doctrine/persistence ^2.2 -> satisfiable by doctrine/persistence[2.2.0, ..., 2.3.x-dev].
        - Conclusion: don't install doctrine/persistence[2.2.2] | install one of doctrine/persistence[1.3.7, 1.3.8] (conflict analysis result)
        
    Installation failed, reverting ./composer.json and ./composer.lock to their original content.
    

    Ⅱ. laavel-doctrine 프로필 만들기


    여기에 doctrine을 직접 넣는 것이 아니라 lavel-doctrine을 사용하는 장점 중 하나입니다.
    다음 명령을 사용하여 Laavel의 설정 파일 디렉토리에 laavel-doctrine용 설정 파일을 생성합니다.
    프로젝트 카탈로그
    php artisan vendor:publish --tag="config" --provider="LaravelDoctrine\ORM\DoctrineServiceProvider"
    
    초대장을 통해 엔티티를 정의하려면 다음과 같이 설정을 편집합니다.
    doctrine.php
    ︙
    ︙
    'default' => [
                'dev'           => env('APP_DEBUG', false),
                'meta'          => env('DOCTRINE_METADATA', 'annotations'),
                'connection'    => env('DB_CONNECTION', 'mysql'),
                'namespaces'    => [
                ],
                'paths'         => [
                    base_path('app/Entities')
                ],
                'repository'    => Doctrine\ORM\EntityRepository::class,
                'proxies'       => [
                    'namespace'     => false,
                    'path'          => storage_path('proxies'),
                    'auto_generate' => env('DOCTRINE_PROXY_AUTOGENERATE', false)
                ],
    ︙
    ︙
    
    'paths' => [base_path('app/Entities')] 엔티티 파일의 위치를 지정합니다.같은 이름의 디렉터리가 있는 항목이 있다면 entities 이외의 디렉터리를 지정할 수 있습니다.
    예) 이미 존재Entities하기 때문에 입력Entity 등등...

    Ⅲ. 솔리드 만들기(솔리드=모드)


    여기서부터 실체 제작에 들어간다.
    이 글은 실체를 만드는 동시에 모델을 정의해야 하기 때문에 실체를 만드는 동시에 모델을 만드는 기초이다.
    또 각자의 프로젝트 상황에 따라 실체의 제작 방법은 크게 두 가지로 나뉜다.

    1. 데이터베이스가 이미 존재하는 경우


    Doctrine을 이미 존재하는 테이블의 프로젝트에 도입하면 기존 DB에서 테이블 단위로 초대장을 정의한 엔티티 파일을 생성할 수 있습니다.
    여기도 적당한 곳이 있다.
    프로젝트 카탈로그
    # app/Entitiesディレクトリが存在しない場合
    mkdir app/Entities
    
    # DBからXMLファイルにスキーマを生成
    php artisan doctrine:convert:mapping xml "app/Entities/" --from-database --namespace="App/Entities/"
    
    # XMLファイルからアノテーション付きエンティティファイルを生成
    php artisan doctrine:convert:mapping annotation "app/Entities/"  --namespace="App/Entities/"
    
    # app/Entities/App/Entities に作成されたXMLファイルは不要なので削除
    rm app/Entities/App/Entities/*.xml
    
    # ディレクトリ構成がおかしいので修正する
    mv app/Entities/App/Entities/* app/Entities/
    

    가장 적합한 곳


    ① DB에서 초대장이 있는 엔티티 파일을 직접 생성할 수 없음
    직접 생성하려면namespace 오류가 발생합니다.따라서 먼저 비모방 모드 파일을 만들고 이를 모방된 실체 파일로 변환할 필요가 있다.
    ③ 생성된 디렉터리에 문제가 있음
    namespace와 디렉터리를 지정하고 octrine:convert:mapping 실행하면 지정한 디렉터리의 더 아래에서namespace의 구성으로 디렉터리를 만들고 파일을 생성합니다.이는 라벨 특유의 카탈로그 구성에 따른 장애일 수 있다.각 파일을 생성한 후에는 파일의 위치를 직접 수정해야 합니다.

    2. DB가 존재하지 않는 경우


    테이블이 존재하지 않으면 자체적으로 실체 파일을 만들고 파생을 기술해야 한다.기본적으로 아래의 공식 문서에 따라 기술하면 되지만 얻기 어려운 기회는 기술 예를 먼저 열거해야 한다.
    app/Entities/User.php
    <?php
    
    namespace App\Entities;
    
    use Doctrine\ORM\Mapping as ORM;
    
    /**
     * User
     *
     * @ORM\Table(name="user")
     * @ORM\Entity
     */
    class User
    {
        /**
         * @var int
         *
         * @ORM\Column(name="user_id", type="integer", nullable=false, options={"comment"="ユーザID"})
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="IDENTITY")
         */
        private $userId;
    
        /**
         * @var string
         *
         * @ORM\Column(name="user_number", type="string", length=15, nullable=false, options={"fixed"=true,"comment"="会員番号"})
         */
        private $userNumber;
    
        /**
         * @var string
         *
         * @ORM\Column(name="user_name", type="string", length=255, nullable=false, options={"comment"="ユーザ名"})
         */
        private $userName;
    
        /**
         * @var \DateTime
         *
         * @ORM\Column(name="created_at", type="datetime", nullable=false, options={"comment"="作成日"})
         */
        private $createdAt;
    
        /**
         * @var \DateTime
         *
         * @ORM\Column(name="updated_at", type="datetime", nullable=false, options={"comment"="更新日"})
         */
        private $updatedAt;
    }
    
    
    지정"fixed"=true을 통해 Mysql에서char를 지정합니다.반대로 지정되지 않은 "type"="string"은varchar가 지정합니다.

    Ⅳ. 모드에서 마이그레이션 생성 및 실행


    마지막으로, 이전을 만들고 실행하기 시작합니다.이렇게 많은 시간을 들여 만든 실체 문서는 매우 활발하다.
    루트 디렉토리
    # エンティティファイルとDBの差分からマイグレーション生成
    php artisan doctrine:migrations:diff
    # 結果例
    Generated new migration class to "Versionhogehoge" from schema differences.
    
    # マイグレーション実行!!
    php artisan doctrine:migrations:migrate
    
    이전은 데이터베이스/migrations 디렉터리의 바로 아래에 생성됩니다.
    생성된 마이그레이션은 다음과 같습니다.
    Versionhogehoge.php
    <?php
    
    namespace Database\Migrations;
    
    use Doctrine\Migrations\AbstractMigration;
    use Doctrine\DBAL\Schema\Schema as Schema;
    
    class Version20211103183613 extends AbstractMigration
    {
        /**
         * @param Schema $schema
         */
        public function up(Schema $schema): void
        {
            $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');
    	︙
    	︙
    	// このブロック内に、マイグレーションバージョンアップ時に実行する操作が記述されます。
    	︙
    	︙
        }
    
        /**
         * @param Schema $schema
         */
        public function down(Schema $schema): void
        {
            $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');
    	︙
    	︙
    	// このブロック内に、マイグレーションバージョンダウン時に実行する操作が記述されます。
    	︙
    	︙
        }
    }
    
    
    자동 생성 이동 후에 직접 수정하는 것도 카노입니다. 하지만 앞으로 자동 생성을 활용할 것을 고려하면 가능한 한 Doctine의sukima기술로 수키마 정의를 열심히 하는 것이 좋을 것 같습니다.
    이렇게 되면 엔티티 파일의 패턴 등을 수정하면 DB를 다양하게 변경할 수 있습니다!

    총결산


    생각보다 내용이 많지만 라벨 7.x+Doctine에서는 DB를 관리하는 방법에 대해 설명합니다.
    Prisma를 터치하면 Laavel이라도 자동으로 생성됩니다!기존 프로젝트를 가져오기 전에는 일본어 문서가 상당히 적고 힘들었다.
    나는 반드시 모두의 도움을 받을 수 있기를 바란다.그리고 Laavel+Doctine 구성이 유행했으면 좋겠어요.
    끝까지 읽어주셔서 감사합니다 m()m

    좋은 웹페이지 즐겨찾기