Estilo de código para migrações Laravel

Olá pessoal.





Nos primeiros cinco anos da minha carreira de programação, trabalhei em um projeto interno, nos próximos sete anos trabalhei em várias startups, com uma equipe de no máximo cinco desenvolvedores.





Estou trabalhando há alguns meses em um projeto com mais de 20 desenvolvedores, o trabalho é realizado simultaneamente em cerca de 30 branches, há cinco ambientes para desenvolvimento de código (draft, dev, testing, hotfix, prod), cada ambiente tem seu próprio banco de dados (antes de lançar o kamit para stand / ambiente, um teste de rollout ocorre usando um banco de dados separado, ou seja, temos 10 bancos de dados separados para cinco ambientes).





Desenvolver em vários ramos não é novidade para mim, sempre fiz isso. A descoberta para mim foi que a versão do código e a versão do esquema do banco de dados não estão sincronizadas de forma alguma. Em um projeto pequeno, não é um problema largar o esquema inteiro e rolar por completo, leva alguns minutos, neste projeto, rolar um esquema do zero com semeadura leva cerca de uma hora.





Há um grande problema em como sincronizar a versão do código e a versão do esquema do banco de dados.





Abaixo, contarei a você as regras que aceitei para mim e ficarei feliz se você compartilhar suas técnicas e técnicas que o ajudam a lidar com este desastre.





Isenção de responsabilidade

O código apresentado a seguir é um código de combate ofuscado, não o depurei, pode ser necessário modificá-lo com um arquivo. Eu só compartilho ideias com você.





Descrição do problema

, , , - -. .





, - , , , , , ? , ?





, , . , , , . , .





.





: " "

, . , migrations, , , .





, .





:





#   
php artisan migrate --path="services/best-team-servise/database/migrations/2021_02_04_240000_alter_data_model_table_add_unique_index.php" --pretend
#  --pretend    SQL      ,  

#    
php artisan migrate:rollback --step=1
#    ,   
      
      



,





php artisan ide-helper:models "Project\Models\DataModel"
      
      



:





php artisan db:seed --class=DataModelSeeder
      
      



? up() down() , , .





, , , .





Builder :





        $conn = (new DataModel())->connection;
        $builder = Schema::connection($conn);
      
      



( ):





        $isExists = $builder->hasColumn(
            'data_model',
            'deleted_at'
        );
      
      



, :





        if (!$isExists) {
            $builder->table(
                'data_model',
                function (Blueprint $table) {
                    $table->softDeletesTz();
                }
            );
        }
      
      



- , - , , , :





        $alias = (new DataModel())->connection;
        $builder = Schema
            ::connection($alias)
            ->getConnection()
            ->getDoctrineSchemaManager();

$existingIndexes = $builder->listTableIndexes('data_model');
      
      



Laravel , :





Blueprint::unique('index_name');
      
      



:





Blueprint::dropUnique('index_name');
      
      



Laravel , , , SQL, Laravel ? , !





SQL, :





DROP TRIGGER IF EXISTS trigger_name
    ON public.data_model;
CREATE TRIGGER trigger_name
    BEFORE INSERT
    ON public.data_model
    FOR EACH ROW
    EXECUTE PROCEDURE public.function_name();
      
      



, :





DROP TRIGGER IF EXISTS trigger_name
    ON public.data_model;
      
      



: " "

, 1000+ . 1000 , .





, 50+ , "" .









, create, alter, , drop.





.





alter_data_model_add_property_column
alter_data_model_alter_property_column_to_text
alter_data_model_alter_property_column_set_default_value
alter_data_model_create_index_on_code_type_columns
alter_data_model_create_unique_index_on_code_column
      
      



, , MVP.





:





#     
php artisan make:migration create_profile_table --create=profile

#     
php artisan make:migration add_confirmed_to_profile --table=profile
      
      



database/migrations , .





: , nullable()

, NOT NULL, , , , .





, .





nullable(), , .





, , - :





            $columns = Schema
            ::connection((new DataModel())->connection)
            ->getConnection()
            ->getDoctrineSchemaManager()
            ->listTableColumns($(new DataModel())->getTable());

            $data = [];
            foreach ($columns as $column) {
                $name = $column->getName();
/* @var array[] $record    */
                $exists = key_exists($name, $record);
                if ($exists) {
                    $data[$name] = $record[$name];
                }
            }

            $isSuccess = DataModel
                ::withTrashed()
                ->updateOrCreate(
                    ['uniqe_index_column' => $data['uniqe_index_column'],],
                    $data
                )->exists;
      
      



: , null

, , , , , .





Ou você pode usar algum valor padrão no código, mas não gosto desse método, porque é um código rígido e isso mata a flexibilidade de nosso aplicativo. A operação do aplicativo deve ser configurada por meio de variáveis ​​de ambiente, arquivos de configuração ou registros de banco de dados.





Conclusão

Esse conjunto de regras certamente não é absoluto, em primeiro lugar ligamos a cabeça e usamos o bom senso.





Vamos discutir nos comentários. Por favor, compartilhe sua experiência.








All Articles