在Sonata Admin Bundle中处理多个文件上传

时间:2014-02-11 20:35:27

标签: php symfony sonata-admin sonata sonata-media-bundle

所以,经过大量的研究并没有得到任何结果(也许我是一个不好的搜索者)我来自这个主题:SonataAdmin Bundle File Upload ErrorSonataMediaBundle - how to upload images?我无法找到解决问题的方法。我有一个实体Company,每个公司可以有多个文件:PDF,DOC,XLS和其他一些mime /类型。我想使用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;
    }

}

在OrderAdmin.php文件中更改了configureFormFields,如下所示:

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')
        );
    }

但这不起作用,因为我无法上传任何文件,这就是我想要从同一表单上传许多文件并将它们附加到我正在创建的订单。请参阅附图,了解我在访问创建操作时获得的视觉效果:

enter image description here enter image description here

我缺少什么?

1 个答案:

答案 0 :(得分:9)

对于您的公司管理员拥有多个图像的解决方案,您必须组织您的关系,就像将有一个联结实体,它将指向ManyToOne关系中的奏鸣曲媒体实体,也指向ManyToOne关系中的您的产品实体我已经创建了这种类型的集合,以满足页脚小部件的需求,这些小部件可以有多个图像,因此您也可以以类似的方式为产品图像映射它。

页脚实体包含一个名为链接的属性,以OneToMany方式指向联结实体FooterWidgetsHasMedia,联结实体(FooterWidgetsHasMedia)保存与奏鸣曲媒体的关系,此外我需要为每个页脚对象和每个图像提供多个图像需要一个悬停图像,所以我的连接实体基本上拥有两个指向奏鸣曲媒体的属性

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;

为上述属性生成getter和setter

现在你必须为你的集合创建一个新的管理员,它引用了交汇点实体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]]

演示拍摄

enter image description here

你可以在这里找到完整的代码演示Git Hub希望它有意义