Sylius自定义Slider资源编辑页翻译值无法显示求助
Sylius自定义Slider实体翻译字段(link)编辑页无法显示值的排查方案
我在Sylius框架中开发了自定义实体Slider及其对应的Translation,两者均已注册为Resource,但在管理后台进入Slider编辑页面时,翻译字段(link)的值无法显示。相关代码如下:
Slider实体代码
<?php namespace App\Entity\Slider; use ApiPlatform\Metadata\ApiResource; use App\Entity\Trait\StatusTrait; use App\Repository\SliderRepository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\PersistentCollection; use Sylius\Component\Core\Model\ImageInterface; use Sylius\Resource\Model\TranslatableTrait; use Sylius\Resource\Model\TranslationInterface; use Webmozart\Assert\Assert; #[ORM\Entity(repositoryClass: SliderRepository::class)] #[ORM\Table(name: 'app_slider')] #[ApiResource] class Slider implements SliderInterface { use StatusTrait, TranslatableTrait { __construct as private initializeTranslationsCollection; getTranslation as private doGetTranslation; } /** @var Collection<array-key, ImageInterface> */ #[ORM\OneToMany(mappedBy: 'owner', targetEntity: SliderImage::class, cascade: ['persist', 'remove'], orphanRemoval: true)] protected Collection $images; /** @var ArrayCollection|PersistentCollection|TranslationInterface[] */ #[ORM\OneToMany(mappedBy: 'translatable', targetEntity: SliderTranslation::class, cascade: ['all'], orphanRemoval: true)] protected $translations; #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column] private ?int $id = null; #[ORM\Column] private ?int $position = null; private string|null $mediaImages = null; public function __construct() { $this->initializeTranslationsCollection(); $this->images = new ArrayCollection(); } public function getId(): ?int { return $this->id; } public function getPosition(): ?int { return $this->position; } public function setPosition(int $position): static { $this->position = $position; return $this; } public function getMediaImages(): ?string { return $this->mediaImages; } public function setMediaImages(?string $mediaImages): void { $this->mediaImages = $mediaImages; } public function getImages(): Collection { return $this->images; } public function getImagesByType(string $type): Collection { return $this->images->filter(function (ImageInterface $image) use ($type): bool { return $type === $image->getType(); }); } public function hasImages(): bool { return !$this->images->isEmpty(); } public function hasImage(ImageInterface $image): bool { return $this->images->contains($image); } public function addImage(ImageInterface $image): void { $image->setOwner($this); $this->images->add($image); } public function removeImage(ImageInterface $image): void { if ($this->hasImage($image)) { $image->setOwner(null); $this->images->removeElement($image); } } public function getTranslation(?string $locale = null): TranslationInterface { /** @var SliderTranslationInterface $translation */ $translation = $this->doGetTranslation($locale); return $translation; } public function setLink(null|string $link): void { $this->getTranslation()->setLink($link); } public function getLink(): ?string { return $this->getTranslation()->getLink(); } protected function createTranslation(): SliderTranslationInterface { return new SliderTranslation(); } }
SliderTranslation实体代码
<?php namespace App\Entity\Slider; use App\Repository\SliderTranslationRepository; use Doctrine\ORM\Mapping as ORM; use Sylius\Resource\Model\AbstractTranslation; use Sylius\Resource\Model\TranslatableInterface; #[ORM\Entity(repositoryClass: SliderTranslationRepository::class)] #[ORM\Table(name: 'app_slider_translation')] class SliderTranslation extends AbstractTranslation implements SliderTranslationInterface { #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column] private ?int $id = null; #[ORM\Column(length: 255)] protected null|string $link = null; public function getId(): ?int { return $this->id; } public function getLink(): null|string { return $this->link; } public function setLink(string $link): void { $this->link = $link; } }
SliderTranslationType表单代码
<?php declare(strict_types=1); namespace App\Form\Type\Slider; use App\Entity\Slider\SliderTranslationInterface; use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; class SliderTranslationType extends AbstractResourceType { public function __construct( string $dataClass, ) { parent::__construct($dataClass); } public function buildForm(FormBuilderInterface $builder, array $options): void { $builder ->add('link', TextType::class, [ 'required' => true, 'label' => 'Link', ]) ; } public function getBlockPrefix(): string { return 'app_slider_translation'; } }
SliderType表单代码
<?php declare(strict_types=1); namespace App\Form\Type\Slider; use App\Repository\SliderRepository; use Doctrine\ORM\NonUniqueResultException; use Doctrine\ORM\NoResultException; use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType; use Sylius\Bundle\ResourceBundle\Form\Type\ResourceTranslationsType; use Symfony\Component\Form\Extension\Core\Type\CollectionType; use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Symfony\Component\Form\FormBuilderInterface; class SliderType extends AbstractResourceType { public function __construct( string $dataClass, private readonly SliderRepository $sliderRepository, ) { parent::__construct($dataClass); } /** * @throws NonUniqueResultException */ public function buildForm(FormBuilderInterface $builder, array $options): void { $builder ->add('translations', ResourceTranslationsType::class, [ 'entry_type' => SliderTranslationType::class, 'label' => 'sylius.form.slider.translations', ]) ->add('position', HiddenType::class, [ 'data' => $this->getPosition(), ]) ; } public function getBlockPrefix(): string { return 'app_slider'; } /** * @throws NonUniqueResultException * @throws NoResultException */ private function getPosition(): int { $position = $this->sliderRepository->getLastPosition(); return $position !== null ? $position++ : 1; } }
sylius_resource.yaml配置
# @see https://github.com/Sylius/SyliusResourceBundle/blob/master/docs/index.md sylius_resource: # Override default settings #settings: # Configure the mapping for your resources mapping: paths: - '%kernel.project_dir%/src/Entity' # Configure your resources resources: app.slider: driver: doctrine/orm classes: model: App\Entity\Slider\Slider interface: App\Entity\Slider\SliderInterface form: App\Form\Type\Slider\SliderType translation: classes: model: App\Entity\Slider\SliderTranslation interface: App\Entity\Slider\SliderTranslationInterface form: App\Form\Type\Slider\SliderTranslationType controller: Sylius\Bundle\ResourceBundle\Controller\ResourceController
翻译模板Twig代码
{% import '@SyliusAdmin/shared/helper/translations.html.twig' as translations %} {% set form = hookable_metadata.context.form %} {% set prefixes = hookable_metadata.prefixes %} <div class="tab-pane {% if hookable_metadata.configuration.active|default(false) %}show active{% endif %}" id="slider-translations" role="tabpanel" tabindex="0"> <div class="card mb-3"> <div class="card-header"> <h2 class="card-title"> {{ 'sylius.ui.translations'|trans }} </h2> </div> <div> {{ translations.with_hook(form.translations, prefixes, null, {accordion_id: 'slider-translations', accordion_flush: true}) }} </div> </div> </div>
Link字段输入模板Twig代码
{% set form = hookable_metadata.context.form %} {% set locale = hookable_metadata.context.locale %} <div class="col-12"> {{ form_row(form.link) }} </div>
可能的原因及解决办法
- ORM映射关联冲突:SliderTranslation继承的
AbstractTranslation已自带translatable字段映射,无需手动在实体中定义关联。检查数据库表结构,确保app_slider_translation表的translatable_id和locale字段正确关联到app_slider表,且无重复映射导致的查询异常。 - 表单数据访问权限:Slider实体的
translations属性为protected,需确保Sylius的表单组件能通过TranslatableTrait提供的方法正确访问翻译集合。可临时将属性改为public测试,确认是否是权限问题。 - Locale上下文不匹配:编辑页面加载时,当前请求的locale需与数据库中存储的翻译locale一致。在
getTranslation方法中打印当前locale,确认是否获取到对应locale的翻译实体;同时检查后台用户的默认locale设置。 - 数据库数据缺失:直接查询
app_slider_translation表,确认对应Slider记录的link字段有值,且locale字段与当前请求locale匹配。若不存在对应locale的翻译记录,Sylius会自动创建空实体,导致link字段为空。 - 模板表单传递错误:在link字段模板中添加
{{ dump(form) }},确认hookable_metadata.context.form是SliderTranslation的表单实例,且表单数据中包含link的有效值。
内容的提问来源于stack exchange,提问作者Vladan Zivanovic
相关产品推荐
相关产品推荐

