Я работаю над этим уже целую неделю и просто не знаю, как это сделать. Надеюсь, вы можете дать мне несколько советов.
На рисунке ниже показано, как я могу загрузить файл и добавить в него столько тегов, сколько захочу. Поле «MainMedia tags» объекта имеет отношение «многие ко многим» с объектом «Tag».
MainMedia юридическое лицо:
класс MainMedia
{
/ **
* @var int
*
* @ORM \ Column (name = «id», type = «integer»)
* @ORM \ Id
* @ORM \ GeneratedValue (стратегии = «АВТО»)
* /
приватный $ id;
/**
* @var string
*
* @ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* @var string
*
* @ORM\Column(name="fileName", type="string", length=255)
*/
private $fileName;
/**
* @var Tag[]|ArrayCollection
*
* @ORM\ManyToMany(targetEntity="Tag", cascade={"persist"})
* @ORM\JoinTable(name="tags")
* @ORM\Column(name="tags")
*
*/
private $tags;
/**
* @var bool
*
* @ORM\Column(name="public", type="boolean")
*/
private $public;
/**
* @var string
*
* @ORM\Column(name="country", type="string", length=255)
*/
private $country;
/**
* @var string
*
* @ORM\Column(name="publicationNumber", type="decimal", scale=1, nullable=true)
*/
private $publicationNumber;
/**
* @var int
*
* @ORM\Column(name="leafletCode", type="integer", nullable=true)
*/
private $leafletCode;
/**
* @var \MyThorluxBundle\Entity\MediaType
*
* @ORM\ManyToOne(targetEntity="MyThorluxBundle\Entity\MediaType")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="type", referencedColumnName="id")
* })
*/
private $type;
/**
* @var \DateTime
*
* @ORM\Column(name="dateCreated", type="datetime")
*/
private $dateCreated;
/**
* @var \DateTime
*
* @ORM\Column(name="dateModified", type="datetime")
*/
private $dateModified;
// ...
/**
* @ORM\Column(type="string")
*
* @Assert\NotBlank(message="Please, upload the file")
* @Assert\File(mimeTypes = {"application/pdf", "image/png", "jpeg", "image/bmp", "application/msword", "video/mp4", "text/csv"})
* maxSize = "1024k",
*
*/
private $file;
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* @param string $title
*
* @return MainMedia
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}/**
* Get title
*
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set fileName
*
* @param string $fileName
*
* @return MainMedia
*/
public function setFileName($fileName)
{
$this->fileName = $fileName;
return $this;
}
/**
* Get fileName
*
* @return string
*/
public function getFileName()
{
return $this->fileName;
}
/**
* Set public
*
* @param boolean $public
*
* @return MainMedia
*/
public function setPublic($public)
{
$this->public = $public;
return $this;
}
/**
* Get public
*
* @return bool
*/
public function getPublic()
{
return $this->public;
}
/**
* Set country
*
* @param string $country
*
* @return MainMedia
*/
public function setCountry($country)
{
$this->country = $country;
return $this;
}
/**
* Get country
*
* @return string
*/
public function getCountry()
{
return $this->country;
}
/**
* Set publicationNumber
*
* @param string $publicationNumber
*
* @return MainMedia
*/
public function setPublicationNumber($publicationNumber)
{
$this->publicationNumber = $publicationNumber;
return $this;
}
/**
* Get publicationNumber
*
* @return string
*/
public function getPublicationNumber()
{
return $this->publicationNumber;
}
/**
* Set leafletCode
*
* @param integer $leafletCode
*
* @return MainMedia
*/
public function setLeafletCode($leafletCode)
{
$this->leafletCode = $leafletCode;
return $this;
}
/**
* Get leafletCode
*
* @return int
*/
public function getLeafletCode()
{
return $this->leafletCode;
}
/**
* Set type
*
* @param string $type
*
* @return MainMedia
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* Get type
*
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* Set dateCreated
*
* @param \DateTime $dateCreated
* @ORM\PrePersist
* @return MainMedia
*/
public function setCreatedAt()
{
if(!$this->dateCreated){
$this->dateCreated = new \DateTime();
}
return $this;
}
/**
* Get dateCreated
*
* @return \DateTime
*/
public function getDateCreated()
{
return $this->dateCreated;
}
/**
* Set dateModified
*
* @param \DateTime $dateModified
* @ORM\PrePersist
* @return MainMedia
*/
public function setUpdatedAt()
{
$this->dateModified = new \DateTime();
return $this;
}
/**
* Get dateModified
*
* @return \DateTime
*/
public function getDateModified()
{
return $this->dateModified;
}
public function __construct()
{
$this->types = new ArrayCollection();
$this->tags = new ArrayCollection();
}
public function addType(MediaType $mediaType)
{
$mediaType->setMediaType($this);
$this->types->add($mediaType);
return $this;
}
public function getFile()
{
return $this->file;
}
public function setFile($file)
{
$this->file = $file;
return $this;
}
public function addTags(Tag $tags)
{
$this->tags->add($tags);
}
public function removeTag(Tag $tags)
{
$this->tags->removeElement($tags);
}
public function getTags()
{
return $this->tags;
}
}
Тег сущности:
class Tag
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string")
*/
private $name;
/**
* @var \DateTime
*
* @ORM\Column(name="dateCreated", type="datetime")
*/
private $dateCreated;
/**
* @var \DateTime
*
* @ORM\Column(name="dateModified", type="datetime")
*/
private $dateModified;
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set name
*
* @param string $name
*
* @return Tag
*/
public function setName($name)
{
$this->name = $name;
}
У меня тогда есть 2 формы, TagType и AddMedia. Поле тегов формы AddMedia использует форму TagType. В форме TagType, как показано ниже, я использую преобразователь данных.
class AddMedia extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('file', FileType::class, array('label' => 'File Upload: ',
'data_class' => null))
->add('title')
->add('fileName')
->add('public')
->add('country')
->add('type', EntityType::class, array(
'class' => 'MyThorluxBundle\Entity\MediaType',
'choice_label' => function (MediaType $mediaType) {
return $mediaType->getMediaType();
}))
->add('publicationNumber')
->add('leafletCode')
->add('tags', CollectionType::class, array(
'entry_type' => TagType::class,
'allow_add' => true,
'by_reference' => false,
'allow_delete' => true,
'label' => false,
))
->add('Submit', SubmitType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => MainMedia::class,
));
}
}class TagType extends AbstractType
{
private $manager;
public function __construct(ObjectManager $manager)
{
$this->manager = $manager;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name', TextType::class, [
'label' => 'Tag: ',
]);
$builder->get('name')
->addModelTransformer(new CollectionToArrayTransformer(), true)
->addModelTransformer(new TagArrayToStringTransformer($this->manager), true);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Tag::class,
));
}
Трансформатор:
Я не могу использовать теги кода, он настолько сломан, он просто не публикует код с отступом.
/**
* Load media database add page
*
* @Route("/media-database-add", name="media_add_route")
* @Template()
* @return array
*/
public function mediaAddAction(Request $request)
{
$mediaType = new MediaType();
$media = new MainMedia();
$media->addType($mediaType);
$manager = $this->getDoctrine()->getManager();
$mediaForm = $this->createForm(AddMedia::class, $media);
$mediaForm->handleRequest($request);
if ($mediaForm->isSubmitted() && $mediaForm->isValid()) {
$file = $media->getFile();
$fileName = $this->get('file_uploader')->upload($file);
$media->setFile($fileName);
$em = $this->getDoctrine()->getManager();
$em->persist($media);
$em->flush();
$this->addFlash(
'success-upload',
'Successfully uploaded ' . $media->getTitle() . ' to the intranet'
);
return $this->redirectToRoute('media_add_route');
}
return [
'mediaForm' => $mediaForm->createView()
];
}
Вышеуказанный контроллер позволяет загружать файлы в базу данных. Это не то, где я получаю ошибку.
Я получаю сообщение об ошибке на странице, где я пытаюсь редактировать загруженный файл, поэтому я должен иметь возможность редактировать его теги.
контроллер:
` /**
* edit media database page
*
* @Route("/media-database-update/edit/{id}", name="media_update_route")
* @Template("MyThorluxBundle:Database:mediaUpdate.html.twig")
* @param Request $request
* @param MainMedia $media
* @return array
*/
public function updateAction(MainMedia $media,Request $request)
{
$editForm = $this->createForm(AddMedia::class, $media);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$em = $this->getDoctrine()->getManager();
$media->setUpdatedAt();
$em->persist($media);
$em->flush();
$this->addFlash(
'media-updated',
'Successfully updated ' . $media->getTitle()
);
return $this->redirectToRoute('media_database_route');
}
return ['editForm' => $editForm->createView()];
}`
Twig:
` <div class="content-padding">
<h1>Update Media</h1>
{% form_theme editForm 'MyThorluxBundle:Forms:fields.html.twig' %}
{{ form_start(editForm) }}
{{ form_start(editForm) }}
{{ form_row(editForm.file) }}
{{ form_row(editForm.title) }}
{{ form_row(editForm.fileName) }}
{{ form_row(editForm.public) }}
{{ form_row(editForm.country) }}
{{ form_row(editForm.type) }}
{{ form_row(editForm.publicationNumber) }}
{{ form_row(editForm.leafletCode) }}
{{ form_row(editForm.tags.name) }}
{{ form_end(editForm) }}
</div>`
Я знаю, что это много кода, но я просто пытаюсь объяснить все это. Итак, ошибка. Я не очень понимаю, почему мои файлы веток все еще получают массив, когда преобразователь должен превращать его в строку? Спасибо!
Я забыл добавить ошибку:
Expected argument of type "array or (\Traversable and \ArrayAccess)", "string" given
Как описано в документе Вот, Вы должны прикрепить преобразователь к полю формы, например, в своем пользовательском FormType:
class AddMedia extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
....
$builder->get('tag')
->addModelTransformer(new TagAttayToStringTransformer($this->manager));
}
Другая проблема может заключаться в том, что вам нужно пройти ObjectManager
экземпляр конструктора вашего трансформатора, вы также должны найти правильный метод для этого в документации
Читайте об этой функции:
prePersist
— Событие prePersist наступает для данного объекта перед выполнением соответствующей операции EntityManager для этого объекта.
preUpdate
— Событие preUpdate наступает перед операциями обновления базы данных до данных объекта. Он не вызывается для оператора DQL UPDATE.
Например ссылка на сайт