Как в Symfony 5.1 подружить EasyAdmin 3, Entity и кастомную службу?
Моя задача: написать интернет-магазин, который будет продавать наборы фотографий. На продакшне фотографии будут храниться в Google Cloud Storage; на дев фотографии будут храниться локально.
Я решал задачу так:
- Создал doctrine entities Product и ImageFile (между ними есть связь 1 продукт ко многим файлам).
- Создал абстрактный класс FileStorage:
abstract class FileStorage
{
private string $tmpDir;
public static function factory(string $tmpDir, string $storageIdent)
{
switch ($storageIdent) {
case 'local': return new FileStorageLocal($tmpDir);
case 'google': return new FileStorageGoogle($tmpDir);
default: throw new \Exception("Wrong storage ident: '{$ident}'");
}
}
public function __construct(string $tmpDir)
{
$this->tmpDir = $tmpDir;
}
abstract public function upload(string $path);
abstract public function download(string $ident, string $downloadFileName);
abstract public function exists(string $ident): bool;
abstract public function getHtmlLink(string $ident): string;
protected function getIdent(string $path)
{
return md5_file($path) . '.' . pathinfo($path, PATHINFO_EXTENSION);
}
protected function getTmpDir()
{
return $this->tmpDir;
}
}
- Отнаследовал от базового класса FileStorageLocal и FileStorageGoogle.
- Создал в services.yaml службу, которая вызывает FileStorage::factory() и передаёт в фабрику параметры $tmpDir и $storageIdent, прописанные в файле .env (в будущем я сделаю разные параметры в .env.prod и .env.dev).
- Создал в ImageEntity метод:
public function getHtmlLink(FileStorage $fileStorage)
{
return $fileStorage->getHtmlLink($this->getIdent());
}
- В написанных мною контроллерах и шаблонах Twig я вызываю $imageFile->getHtmlLink() и передаю как параметр $fileStorage, полученный с помощью autowiring.
Всё было хорошо и всё работало, пока я не начал писать админку интернет-магазина. Для админки я решил использовать Easy Admin 3. Поэтому я создал ImageFileCrudController с таким методом:
public function configureFields(string $pageName): iterable
{
return [
ImageField::new('html_link')->hideOnForm(),
TextField::new('original_file_name')->hideOnForm(),
TextField::new('ident')->setFormTypeOption('disabled', 'disabled')->hideOnIndex(),
AssociationField::new('product')->setSortable(false),
];
}
В результате получаю ошибку "Too few arguments to function App\Entity\ImageFile::getHtmlLink(), 0 passed in /var/www/html/vendor/symfony/property-access/PropertyAccessor.php on line 405 and exactly 1 expected". Я понимаю откуда ошибка взялась, но не понимаю, как её лучше исправить. Поэтому прошу у уважаемого сообщества помощи и совета по таким вопросам:
- Правильно ли я спроектировал взаимодействие ImageField, FileStorage, services.yaml и .env? Не видите ли вы способа сделать это проще и лучше?
- Нет ли в EasyAdmin 3 способа как-то перегрузить получение значения поля? Я слышал о кастомных полях, для которых пишутся свои собственные шаблоны twig. Можно ли передать в них аргументы из сервис-контейнера Symfony?
- Правильным ли был выбор Easy Admin 3? Может быть, у вас есть на примете более простая и универсальная админка?