Specifications
Symfony > 4.4.2 (Not working) Symfony 4.4.1 (Working)
I got a problem with my Translations because on every action that includes translations, symfony is throwing a error like "no mapping field 'sprache_id' was found on class 'AnredeTranslation'"
This makes no sense for me, because the field is there and was working until i go to symfony 4.4 - What the heck did they change from 4.3 to 4.4 that this error is shown constantly? Every Entity with Translation is included in this problem, so my whole project is broken except this entities, which has no translations.
Btw - Anrede is the entity, which throws at $form->handleRequest other entities throw error on createForm.
Did someone get this problem too or are i'm alone with it?
UPDATE:
I can update to Symfony 4.4.1 - from Symfony 4.4.2 this error (no mapping for field sprache_id ...) will be thrown on create/mod entities with translations and i dont know why. Only the error confuses me, because form/request handler search for sprache_id field but the field is only sprache.
EXAMPLE
I'll publish here now an entity (shortest one) to show my definitions
Anrede Entity
<?php
namespace App\Entity\Core\Kontakt;
use App\Entity\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity(repositoryClass="App\Repository\Core\Benutzer\AnredeRepository")
*/
class Anrede extends Entity
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="boolean")
*/
private $aktiv;
/**
* @ORM\OneToMany(targetEntity="App\Entity\Core\Kontakt\AnredeTranslation", mappedBy="anrede", orphanRemoval=true, cascade={"persist","remove","merge"}, fetch="EAGER", indexBy="sprache_id")
* @ORM\OrderBy({"sprache" = "ASC"})
* @Assert\Valid()
*/
private $translations;
/**
* @ORM\Column(type="boolean", options={"default":0})
*/
private $standard;
public function __construct()
{
$this->translations = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getAktiv(): ?bool
{
return $this->aktiv;
}
public function setAktiv(bool $aktiv): self
{
$this->aktiv = $aktiv;
return $this;
}
/**
* @return Collection|AnredeTranslation[]
*/
public function getTranslations(): Collection
{
return $this->translations;
}
public function addTranslation(AnredeTranslation $translation): self
{
if (!$this->translations->contains($translation)) {
$this->translations[] = $translation;
$translation->setAnrede($this);
}
return $this;
}
public function removeTranslation(AnredeTranslation $translation): self
{
if ($this->translations->contains($translation)) {
$this->translations->removeElement($translation);
// set the owning side to null (unless already changed)
if ($translation->getAnrede() === $this) {
$translation->setAnrede(null);
}
}
return $this;
}
public function getStandard(): ?bool
{
return $this->standard;
}
public function setStandard(bool $standard): self
{
$this->standard = $standard;
return $this;
}
}
AnredeTranslation Entity
<?php
namespace App\Entity\Core\Kontakt;
use App\Entity\Core\Sprache\Sprache;
use App\Entity\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity(repositoryClass="App\Repository\Core\Benutzer\AnredeTranslationRepository")
* @UniqueEntity(
* fields={"sprache","anrede"},
* errorPath="sprache",
* message="error.bereits_vorhanden"
* )
*/
class AnredeTranslation extends Entity
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Core\Kontakt\Anrede", inversedBy="translations")
* @ORM\JoinColumn(nullable=false)
*/
private $anrede;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Core\Sprache\Sprache")
* @ORM\JoinColumn(nullable=false)
* @Assert\NotNull()
*/
private $sprache;
/**
* @ORM\Column(type="string", length=255)
* @Assert\NotBlank()
*/
private $name;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $anredetext;
public function getId(): ?int
{
return $this->id;
}
public function getAnrede(): ?Anrede
{
return $this->anrede;
}
public function setAnrede(?Anrede $anrede): self
{
$this->anrede = $anrede;
return $this;
}
public function getSprache(): ?Sprache
{
return $this->sprache;
}
public function setSprache(?Sprache $sprache): self
{
$this->sprache = $sprache;
return $this;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(?string $name): self
{
$this->name = $name;
return $this;
}
public function getAnredetext(): ?string
{
return $this->anredetext;
}
public function setAnredetext(?string $anredetext): self
{
$this->anredetext = $anredetext;
return $this;
}
}
AnredeType
<?php
namespace App\Form\Core\Kontakte;
use App\Entity\Core\Kontakt\Anrede;
use App\Form\Type\SwitchType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class AnredeType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('aktiv', SwitchType::class, [
'label' => 'aktiv.name',
'help'=> 'aktiv.help'
])
->add('standard', SwitchType::class, [
'label' => 'standard.name',
'help'=> 'standard.help'
])
->add('translations', CollectionType::class, [
'label' => 'sprachen.name',
'entry_type' => AnredeTranslationType::class,
'error_bubbling' => true,
'prototype' => true,
'allow_add' => true,
'allow_delete' => true,
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Anrede::class,
]);
}
}
AnredeTranslationType
<?php
namespace App\Form\Core\Kontakte;
use App\Entity\Core\Kontakt\Anrede;
use App\Entity\Core\Kontakt\AnredeTranslation;
use App\Entity\Core\Navigation\Navigation;
use App\Entity\Core\Navigation\NavigationTranslation;
use App\Entity\Core\Sprache\Sprache;
use App\Form\Transform\HiddenTransformer;
use App\Form\Type\SprachenType;
use App\Services\LocaleService;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\TranslatorInterface;
class AnredeTranslationType extends AbstractType
{
/**
* @var EntityManagerInterface
*/
private $manager;
/**
* @var Translator
*/
private $translator;
/**
* @var LocaleService
*/
private $localeService;
public function __construct(EntityManagerInterface $manager, TranslatorInterface $translator, LocaleService $localeService)
{
$this->manager = $manager;
$this->translator = $translator;
$this->localeService = $localeService;
}
private $options;
public function buildForm(FormBuilderInterface $builder, array $options)
{
$this->options = $options;
$builder
->add('sprache', SprachenType::class, [
'required' => true,
])
->add('name', TextType::class, [
'required' => true,
'label' => 'label.name',
'help' => 'help.name'
])
->add('anredetext', TextType::class, [
'required' => false,
'label' => 'anredetext.name',
'help' => 'anredetext.help',
])
->add('anrede', HiddenType::class)
;
$builder->get('anrede')->addModelTransformer(new HiddenTransformer($this->manager, Anrede::class));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => AnredeTranslation::class,
]);
}
}