#php #exception #laravel-7 #laravel-artisan #laravel-migrations
#php #исключение #laravel-7 #laravel-artisan #laravel-миграции
Вопрос:
Я создаю команду в Laravel 7, которая создает некоторые миграции в папке внутри database / migrations и сеялки. Затем он запускает dumpAutoloads(), чтобы убедиться, что созданные миграции и сеялка зарегистрированы в автозагрузке classmap. Затем моя команда вызывает команду php artisan migrate и последовательно команду php artisan db:seed с флагом —class, чтобы заполнить только созданную сеялку.
Все работает нормально, пока не будет вызвана команда db:seed . Программа-сеялка действительно создана, но она продолжает выдавать мне следующее исключение:
IlluminateContractsContainerBindingResolutionException
Target class [StudentOperationTypesSeeder] does not exist
Очевидно, это всего лишь пример, но я проверил, что имя созданного сеялки точно такое же, как и то, которое показывает исключение, и оно совпадает. Кроме того, сразу после того, как мне выдается это исключение, я сам запускаю команду db:seed —class=StudentOperationTypesSeeder, и это работает!
Это заставляет меня думать, что, возможно, автозагрузка classmap не обновляется до тех пор, пока процесс выполнения команды не будет завершен или что-то в этом роде… Я действительно понятия не имею.
Мой код следующий:
TimeMachineGeneratorCommand.php
<?php
namespace AppConsoleCommands;
use IlluminateConsoleCommand;
use IlluminateSupportStr;
use IlluminateSupportFacadesSchema;
use IlluminateSupportFacadesDB;
class TimeMachineGeneratorCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'time-machine:generate {table_name}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Generates the tables and structure of a time machine for the given table.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
// Convierte a snake case singular el nombre de la entidad.
$entity = Str::singular(
Str::snake(class_basename($this->argument('table_name')))
);
// Revisa que el nombre del modelo esté en el formato adecuado.
$modelName = Str::singular(
Str::studly($this->argument('table_name'))
);
$seederClassName = "{$modelName}OperationTypesSeeder";
// Crea las migraciones para la estructura de la máquina del tiempo.
$this->createMigrations($entity);
// Genera el Seeder del los operation types básicos.
$this->createSeeder($seederClassName);
// Para asegurarse que las migrations y el seeder está registrada en
// los class loaders se ejecuta el dump-autoload.
$this->line("<fg=yellow>Dumping Autoloads...</>");
$this->laravel->composer->dumpAutoloads();
$this->info("Autoloads dumped.");
// Ejecuta las migraciones.
$this->call('migrate', [
'--path' => '/database/migrations/'.Str::plural(Str::snake($modelName)).'/'
]);
// Ejecuta el seeder recién creado.
$this->call('db:seed', [
'--class' => $seederClassName
]);
(...) // <-- Some other code that isn't executed because of the exception
}
/**
* Genera los archivos de código de las migraciones necesarias
* para la estructura de la máquina del tiempo.
*/
private function createMigrations($entity)
{
// Genera la migración para los tipos de operación de la entidad.
$this->call('time-machine:operation-type-migration', [
'entity' => $entity
]);
// Genera la migración para los logs de la entidad.
$this->call('time-machine:log-migration', [
'entity' => $entity
]);
// Genera la migración para los logs de la entidad.
$this->call('time-machine:required-fields-migration', [
'entity' => $entity
]);
}
/**
* Crea el seeder de operationt types basado en el
* template diseñado para la máquina del tiempo.
*
* @param string | $seederClassName | El nombre de la clase para el seeder.
* @return void.
*/
private function createSeeder($seederClassName)
{
$this->call('time-machine:seeder', [
'name' => $seederClassName
]);
// Agrega el seeder recién creado al DatabaseSeeder.php.
$this->updateDatabaseSeeder($seederClassName);
}
/**
* Agrega el seeder recién creado al DatabaseSeeder.php.
*
* @var $seederClassName.
* @return void.
*/
private function updateDatabaseSeeder($seederClassName)
{
$filePath = base_path().'\database\seeds\DatabaseSeeder.php';
// Lee el archivo del DataBaseSeeder.
$seeder = file_get_contents($filePath);
// Si el seeder no ha sido agregado ya al DatabaseSeeder.php...
if(preg_match('/$this->call('.$seederClassName.'::class);/', $seeder) == 0) {
// Agrega el seeder recién creado.
$newContent = preg_replace(
'/public function run()s*{/',
"public function run()
{
$this->call({$seederClassName}::class);",
$seeder, 1
);
// Guarda el contenido del archivo.
file_put_contents($filePath, $newContent);
$this->info('Seeder added to DatabaseSeeder.php.');
} else {
$this->error('Seeder is already in DataBaseSeeder.php.');
}
}
}
Кроме того, это раздел автозагрузки моего composer.json (я читал, что с этим может быть что-то или что-то в этом роде, я все равно не смог найти решение своей проблемы).
"autoload": {
"psr-4": {
"App\": "app/"
},
"classmap": [
"database/seeds",
"database/factories"
]
},
StudentOperationTypesSeeder.php
<?php
use IlluminateDatabaseSeeder;
class StudentOperationTypesSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
$studentOperationType = new AppStudentOperationType();
$studentOperationType->description = "Created";
$studentOperationType->save();
$studentOperationType = new AppStudentOperationType();
$studentOperationType->description = "Updated";
$studentOperationType->save();
$studentOperationType = new AppStudentOperationType();
$studentOperationType->description = "Deleted";
$studentOperationType->save();
}
}
Пожалуйста, помогите. Команда успешно генерирует миграции и средство просмотра, затем запускает миграции, и все работает точно так, как задумано, за исключением средства просмотра, и я не понимаю, почему.
Примечание: другие команды «машины времени«, которые я вызываю в функциях TimeMachineGeneratorCommand.php есть другие пользовательские команды, которые я создал, которые буквально только расширяют существующие команды миграции поставщика и меняют заглушку на пользовательскую.
Комментарии:
1. Ну, как выглядит файл seeder?
2. Я отредактирую его в
3. этот новый файл сеялки не будет частью classmap в этот момент (он не загружается автоматически PSR4), потенциально он может потребоваться в этот момент, хотя в PHP загружен класс, поскольку для этого класса нет сопоставления
4. как я могу это потребовать?
Ответ №1:
Я последовал подходу, предложенному lagbox, и нашел то, что работает.
Я включил сгенерированный файл, добавив следующую строку кода перед вызовом команды bd:seed, очевидно, после строки, которая генерирует средство просмотра.
include base_path()."\database\seeds\".$seederClassName.".php";
После выполнения этого сеялка выполняется правильно, и вся команда работает так, как ожидалось.
Окончательный метод обработки выглядит следующим образом.
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
// Convierte a snake case singular el nombre de la entidad.
$entity = Str::singular(
Str::snake(class_basename($this->argument('table_name')))
);
// Revisa que el nombre del modelo esté en el formato adecuado.
$modelName = Str::singular(
Str::studly($this->argument('table_name'))
);
$seederClassName = "{$modelName}OperationTypesSeeder";
// Crea las migraciones para la estructura de la máquina del tiempo.
$this->createMigrations($entity);
// Genera el Seeder del los operation types básicos.
$this->createSeeder($seederClassName);
// Para asegurarse que las migrations y el seeder está registrada en
// los class loaders se ejecuta el dump-autoload.
$this->line("<fg=yellow>Dumping Autoloads...</>");
$this->laravel->composer->dumpAutoloads();
$this->info("Autoloads dumped.");
// Ejecuta las migraciones.
$this->call('migrate', [
'--path' => '/database/migrations/'.Str::plural(Str::snake($modelName)).'/'
]);
include base_path()."\database\seeds\".$seederClassName.".php";
// Ejecuta el seeder recién creado.
$this->call('db:seed', [
'--class' => $seederClassName
]);
(...) // <-- Some other code that isn't executed because of the exception
}