Symfony 4.x多数据库场景下,表单EntityType跨库加载Location问题
搞定Symfony 4.x多数据库下表单关联不同库实体的问题
嘿,我来帮你解决这个跨数据库的表单下拉框问题!因为你的Customer和Location实体分别在两个不同的数据库,默认的表单类型会用Customer所在的EntityManager,找不到Location的数据,所以咱们得做一些针对性配置。
第一步:确保Doctrine多数据库配置正确
首先得确认你的config/packages/doctrine.yaml里已经配置好了两个实体管理器,对应各自的数据库和实体目录,比如这样:
doctrine: dbal: default_connection: default connections: default: # Customer所在数据库的配置 url: '%env(DATABASE_URL)%' driver: 'pdo_mysql' server_version: '5.7' charset: utf8mb4 lobbytrack: # Location所在数据库的配置 url: '%env(DATABASE_LOBBYTRACK_URL)%' driver: 'pdo_mysql' server_version: '5.7' charset: utf8mb4 orm: default_entity_manager: default entity_managers: default: connection: default mappings: App: is_bundle: false type: annotation dir: '%kernel.project_dir%/src/Entity' prefix: 'App\Entity' alias: App lobbytrack: connection: lobbytrack mappings: Lobbytrack: is_bundle: false type: annotation dir: '%kernel.project_dir%/src/Entity/Lobbytrack' prefix: 'App\Entity\Lobbytrack' alias: Lobbytrack
第二步:编写完整的CustomerForm类
这里推荐直接注入LocationRepository的方式,更直观:
<?php namespace App\Form; use App\Entity\Customer; // 替换成你的Customer实体命名空间 use App\Entity\Lobbytrack\Location; use App\Repository\Lobbytrack\LocationRepository; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; class CustomerForm extends AbstractType { private $locationRepository; // 注入Location对应的Repository(自动关联到正确的EntityManager) public function __construct(LocationRepository $locationRepository) { $this->locationRepository = $locationRepository; } public function buildForm(FormBuilderInterface $builder, array $options) { $builder // 添加你的其他客户字段,比如姓名、邮箱等 ->add('name') ->add('email') // 关键的Location下拉选择框配置 ->add('location', EntityType::class, [ 'class' => Location::class, // 使用注入的Repository构建查询,保证数据来自正确的数据库 'query_builder' => function () { return $this->locationRepository->createQueryBuilder('l') ->orderBy('l.name', 'ASC'); // 按名称排序 }, // 设置下拉选项显示的内容,比如Location的name字段 'choice_label' => 'name', // 添加占位符提示 'placeholder' => '请选择一个地点', // 是否必填,根据你的需求调整 'required' => true, ]); } public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ 'data_class' => Customer::class, ]); } }
如果你更倾向于注入EntityManager,也可以这样写:
// 替换构造函数和字段配置 use Doctrine\ORM\EntityManagerInterface; private $locationEntityManager; public function __construct(EntityManagerInterface $locationEntityManager) { $this->locationEntityManager = $locationEntityManager; } // 在buildForm里的Location字段 ->add('location', EntityType::class, [ 'class' => Location::class, // 指定使用Location所在的EntityManager 'em' => $this->locationEntityManager, 'choice_label' => 'name', 'query_builder' => function ($repo) { return $repo->createQueryBuilder('l') ->orderBy('l.name', 'ASC'); }, 'placeholder' => '请选择一个地点', 'required' => true, ]);
第三步:配置依赖注入(可选)
Symfony 4.x默认的autowire已经可以自动注入Repository和EntityManager,但如果有特殊情况,你可以在config/services.yaml里手动配置:
services: App\Form\CustomerForm: autowire: true # 如果注入EntityManager,指定对应的服务ID # arguments: # $locationEntityManager: '@doctrine.orm.lobbytrack_entity_manager'
这样配置后,你的CustomerForm就能正确从另一个数据库拉取Location列表,显示成下拉选择框啦!
内容的提问来源于stack exchange,提问作者Geoff Maddock
相关产品推荐
相关产品推荐

