Обработка нескольких загрузок файлов в Sonata Admin Bundle

Итак, после исследований много и не получаю результатов (может быть, я плохой искатель), я исхожу из этих тем: Ошибка загрузки файла SonataAdmin и SonataMediaBundle – как загрузить изображения? Я не могу найти решение проблемы. У меня есть Company Entity, и каждая компания может иметь несколько файлов: PDF, DOC, XLS и некоторые другие mime / types. Я думаю, что использовать VichUploaderBundle, но снова документирует только пример для отношений один к одному, так что мой вопрос в том, что любой может дать мне несколько примеров или способов сделать это? Я имею в виду загружать файлы и прикреплять их к компании?

EDIT1 работает и тестируется

Как я уже говорил, я пытаюсь интегрировать SonataMediaBundle в другой модуль администрирования, который у меня есть, но я не могу заставить его работать. Что я делал до сих пор?

Конечно, установите и настройте все пакеты: SonataAdminBundle и SonataMediaBundle работают нормально

Изменено \Application\Sonata\MediaBundle\Entity\Media.php чтобы добавить необходимую функциональность, добавив отношение ManyToMany

 namespace Application\Sonata\MediaBundle\Entity; use Sonata\MediaBundle\Entity\BaseMedia as BaseMedia; use Doctrine\ORM\Mapping as ORM; class Media extends BaseMedia { /** * @var integer $id */ protected $id; /** * @ORM\ManyToMany(targetEntity="PL\OrderBundle\Entity\Order", inversedBy="medias") * @ORM\JoinTable(name="order_has_media__media", * joinColumns={@ORM\JoinColumn(name="media__media_id", referencedColumnName="id")}, * inverseJoinColumns={@ORM\JoinColumn(name="order_no_order", referencedColumnName="no_order")} * ) */ protected $orders; public function __construct() { $this->orders = new \Doctrine\Common\Collections\ArrayCollection(); } /** * Get id * * @return integer $id */ public function getId() { return $this->id; } public function setOrders(\PL\OrderBundle\Entity\Order $order) { $this->orders[] = $order; } public function getOrders() { return $this->orders; } } 

Добавление полей необходимости в PL \ OrderBundle \ Entity \ Order.php следующим образом:

 namespace PL\OrderBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity * @ORM\Table(name="tb_order") */ class Order { /** * @ORM\Id * @ORM\Column(type="string", length=15, unique=true, nullable=false) */ protected $no_order; /** * @ORM\ManyToOne(targetEntity="PL\CompanyBundle\Entity\Company", inversedBy="id") */ protected $company; /** * @ORM\Column(type="string", length=15, unique=true) */ protected $business_case; /** * @ORM\Column(type="integer", length=1) */ protected $charge_status; /** * @ORM\Column(type="datetime") */ protected $eta; /** * @ORM\Column(type="datetime") */ protected $etd; /** * @ORM\Column(type="integer", length=1) */ protected $transport_media; /** * @ORM\Column(type="integer", length=1) */ protected $incoterm; /** * @ORM\Column(type="string", length=250) */ protected $comments; /** * @ORM\ManyToMany(targetEntity="Application\Sonata\MediaBundle\Entity\Media", mappedBy="orders") */ protected $medias; public function __construct() { $this->medias = new \Doctrine\Common\Collections\ArrayCollection(); } public function setNoOrder($no_order) { $this->no_order = $no_order; } public function getNoOrder() { return $this->no_order; } public function setCompany(\PL\CompanyBundle\Entity\Company $company) { $this->company = $company; } public function getCompany() { return $this->company; } public function setBusinessCase($business_case) { $this->business_case = $business_case; } public function getBusinessCase() { return $this->business_case; } public function setChargeStatus($charge_status) { $this->charge_status = $charge_status; } public function getChargeStatus() { return $this->charge_status; } public function setETA($eta) { $this->eta = $eta; } public function getETA() { return $this->eta; } public function setETD($etd) { $this->etd = $etd; } public function getETD() { return $this->etd; } public function setTransportMedia($transport_media) { $this->transport_media = $transport_media; } public function getTransportMedia() { return $this->transport_media; } public function setIncoterm($incoterm) { $this->incoterm = $incoterm; } public function getIncoterm() { return $this->incoterm; } public function setComments($comments) { $this->comments = $comments; } public function getComments() { return $this->comments; } public function setMedias(\Application\Sonata\MediaBundle\Entity\Media $media) { $this->medias[] = $media; } public function addMedia(\Application\Sonata\MediaBundle\Entity\Media $media) { $this->medias[] = $media; } public function getMedias() { return $this->medias; } } 

Изменен файл configureFormFields в файле OrderAdmin.php следующим образом:

 protected function configureFormFields(FormMapper $form) { $form ->add('no_order', null, array('label' => 'No. Order')) ->add('company', 'entity', array('class' => 'PL\CompanyBundle\Entity\Company', 'label' => 'Cliente')) ->add('business_case', null, array('label' => 'BC')) ->add('charge_status', 'choice', array('choices' => array( "empty_value" => "Seleccione una opción", "0" => "Ninguno", "1" => "Proceso de Fabricacion", "2" => "Pickup en destino", "3" => "A la espera de recojo por cliente", "4" => "Carga en transito", "5" => "Carga arribada", "6" => "En proceso de aduana", "7" => "Entregado a cliente", "8" => "En bodega" ), "required" => true, 'label' => 'Estado de la carga')) ->add('eta', null, array('label' => 'ETD')) ->add('etd', null, array('label' => 'ETA')) ->add('transport_media', 'choice', array('choices' => array("empty_value" => "Seleccione una opción", "0" => "EXW", "1" => "Maritimo", "2" => "Aereo"), "required" => true, 'label' => 'Via de Transporte')) ->add('incoterm', 'choice', array('choices' => array( "empty_value" => "Seleccione una opción", "0" => "Ninguno", "1" => "EWX", "2" => "FOB", "3" => "CIF", "4" => "DDP" ), "required" => true, 'label' => 'Incoterm')) ->add('comments', null, array('label' => 'Comentarios')) ->add('medias', 'sonata_type_collection', array( 'label' => 'Documentos', 'type_options' => array('delete' => true)), array( 'edit' => 'inline', 'inline' => 'table', 'sortable' => 'position') ); } 

Но это не сработает, так как я не могу загрузить какой-либо файл, и это то, что я хочу загрузить много файлов из той же формы и прикрепить их к заказу, который я создаю. См. Прикрепленные изображения для визуального получения, когда я получаю доступ к действию create:

введите описание изображения здесьвведите описание изображения здесь

Что мне не хватает?

Solutions Collecting From Web of "Обработка нескольких загрузок файлов в Sonata Admin Bundle"

Чтобы ваше решение имело несколько изображений для администратора вашей компании, вы должны организовать свое отношение, так как будет существовать один объект соединения, который будет указывать на медиа-объект сонаты в отношении ManyToOne, а также на ваш товарный объект в отношении ManyToOne, а также я создал этот тип коллекции для одного из потребностей виджета нижнего колонтитула, который может иметь несколько изображений, чтобы вы могли также сопоставить его для изображений ваших продуктов аналогичным образом.

Footer Entity содержит свойство, называемое ссылками, которое указывает на объект соединения FooterWidgetsHasMedia в способе OneToMany, объект соединения (FooterWidgetsHasMedia) содержит отношение к сонатным носителям, кроме того, мне нужно несколько изображений для каждого моего нижнего объекта, а также для каждого изображения, нуждающегося в hover image, так что мой объект соединения в основном имеет два свойства, которые указывают на медиану сонаты

FooterWidgets

 /** * @Assert\NotBlank() * @ORM\OneToMany(targetEntity="Traffic\WidgetsBundle\Entity\FooterWidgetsHasMedia", mappedBy="footerWidget",cascade={"persist","remove"} ) */ protected $links; /** * Remove widgetImages * * @param \Application\Sonata\MediaBundle\Entity\Media $widgetImages */ public function removeLinks(\Traffic\WidgetsBundle\Entity\FooterWidgetsHasMedia $links) { $this->links->removeElement($links); } /** * Get widgetImages * * @return \Doctrine\Common\Collections\Collection */ public function getLinks() { return $this->links; } /** * {@inheritdoc} */ public function setLinks($links) { $this->links = new ArrayCollection(); foreach ($links as $footerWidget) { $this->addLinks($footerWidget); } } /** * {@inheritdoc} */ public function addLinks(\Traffic\WidgetsBundle\Entity\FooterWidgetsHasMedia $links) { $links->setFooterWidget($this); $this->links[] = $links; } 

Теперь мой объект соединения будет ссылаться на FooterWidgets и сонатный медиа-объект

FooterWidgetsHasMedia

Определения свойств

 /** * @var \Application\Sonata\MediaBundle\Entity\Media * @Assert\NotBlank() * @ORM\ManyToOne(targetEntity="Application\Sonata\MediaBundle\Entity\Media", cascade={"persist"}, fetch="LAZY") * @ORM\JoinColumn(name="media_id", referencedColumnName="id") */ protected $media; /** * @var \Application\Sonata\MediaBundle\Entity\Media * @Assert\NotBlank() * @ORM\ManyToOne(targetEntity="Application\Sonata\MediaBundle\Entity\Media", cascade={"persist"}, fetch="LAZY") * @ORM\JoinColumn(name="media_hover_id", referencedColumnName="id") */ protected $mediaHover; /** * @var \Traffic\WidgetsBundle\Entity\FooterWidgets * @Assert\NotBlank() * @ORM\ManyToOne(targetEntity="Traffic\WidgetsBundle\Entity\FooterWidgets", cascade={"persist","remove"} ,inversedBy="links", fetch="LAZY" ) * @ORM\JoinColumn(name="footer_widget_id", referencedColumnName="id",nullable=true) */ protected $footerWidget; /** * @var integer * @ORM\Column(name="position", type="integer") */ protected $position; /** * @var boolean * @ORM\Column(name="enable", type="boolean") */ protected $enabled; 

Генерировать геттеры и сеттеры для вышеуказанных свойств

Теперь вам нужно создать новый администратор для вашей коллекции, который ссылается на объект соединения FooterWidgetsHasMedia и configureFormFields будет выглядеть примерно так:

FooterWidgetsHasMediaAdmin

 protected function configureFormFields(FormMapper $formMapper) { $link_parameters = array(); if ($this->hasParentFieldDescription()) { $link_parameters = $this->getParentFieldDescription()->getOption('link_parameters', array()); } if ($this->hasRequest()) { $context = $this->getRequest()->get('context', null); if (null !== $context) { $link_parameters['context'] = $context; } } $formMapper ->add('media', 'sonata_type_model_list', array('required' => false), array( 'link_parameters' => $link_parameters )) ->add('mediaHover', 'sonata_type_model_list', array('required' => false), array( 'link_parameters' => $link_parameters )) ->add('enabled', null, array('required' => false)) ->add('link', 'text', array('required' => false)) ->add('position', 'hidden') ; } 

И ваш администратор вашей компании будет иметь новое поле в configureFormFields

FooterWidgetsAdmin

  ->add('links', 'sonata_type_collection', array( 'cascade_validation' => false, 'type_options' => array('delete' => false), ), array( 'edit' => 'inline', 'inline' => 'table', 'sortable' => 'position', 'link_parameters' => array('context' => 'widgets'), 'admin_code' => 'sonata.admin.footer_widgets_has_media' /*here provide service name for junction admin */ ) ) 

Зарегистрируйте администраторский сервис для своего нового администратора как

 sonata.admin.footer_widgets_has_media: class: Traffic\WidgetsBundle\Admin\FooterWidgetsHasMediaAdmin tags: - { name: sonata.admin, manager_type: orm, group: "Widgets", label: "Footer Widgets Section Media" , show_in_dashboard: false } arguments: - ~ - Traffic\WidgetsBundle\Entity\FooterWidgetsHasMedia - ~ calls: - [ setTranslationDomain, [TrafficWidgetsBundle]] 

Демонстрационный снимок

введите описание изображения здесь

Вы можете найти полную демо-версию здесь Git Hub надеются, что это имеет смысл