在symfony 2中上传文件时出错

时间:2013-01-09 03:03:39

标签: php forms file-upload symfony doctrine-orm

尝试设置附加到Doctrine实体的文件上传表单,根据这个菜谱配方:

http://symfony.com/doc/2.0/cookbook/doctrine/file_uploads.html

这是我的实体/模型类:

<?php

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\UploadedFile;

/**
 * Invoice
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="TechPeople\InvoiceBundle\Entity\InvoiceRepository")
 * @ORM\HasLifecycleCallbacks
 */
class Invoice
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var integer
     *
     * @ORM\ManyToOne(targetEntity="User", inversedBy="user_invoices")
     * @ORM\JoinColumn(name="vendor_id", referencedColumnName="id")
     */
    private $vendor;

    /**
     * @var string
     *
     * @ORM\Column(name="month", type="string", length=255)
     */
    private $month;

    /**
     * @var integer
     *
     * @ORM\Column(name="year", type="smallint")
     */
    private $year;

    /**
     * @var boolean
     *
     * @ORM\Column(name="expenses", type="boolean")
     */
    private $expenses;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="due", type="date")
     */
    private $due;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="paid", type="date")
     */
    private $paid;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="created", type="datetime")
     */
    private $created;

    /**
     * @var float
     *
     * @ORM\Column(name="expense_amount", type="decimal")
     */
    private $expense_amount;

    /**
     * @var float
     *
     * @ORM\Column(name="total_amount", type="decimal")
     */
    private $total_amount;

    /**
     * @var UploadedFile
     *
     * @Assert\File(maxSize="6000000")
     */
    public $attachment;

    /**
     * @var string
     *
     * @ORM\Column(name="attachment_path", type="string", length=255)
     */
    private $attachment_path;

    /**
     * @ORM\OneToMany(targetEntity="InvoiceItem", mappedBy="invoice")
     */
    protected $invoice_items;


    /**
     * Constructor for Invoice Entity class
     */
    public function __construct()
    {
        $this->products = new ArrayCollection();
    }

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set month
     *
     * @param string $month
     * @return Invoice
     */
    public function setMonth($month)
    {
        $this->month = $month;

        return $this;
    }

    /**
     * Get month
     *
     * @return string 
     */
    public function getMonth()
    {
        return $this->month;
    }

    /**
     * Set year
     *
     * @param integer $year
     * @return Invoice
     */
    public function setYear($year)
    {
        $this->year = $year;

        return $this;
    }

    /**
     * Get year
     *
     * @return integer 
     */
    public function getYear()
    {
        return $this->year;
    }

    /**
     * Set expenses
     *
     * @param boolean $expenses
     * @return Invoice
     */
    public function setExpenses($expenses)
    {
        $this->expenses = $expenses;

        return $this;
    }

    /**
     * Get expenses
     *
     * @return boolean 
     */
    public function getExpenses()
    {
        return $this->expenses;
    }

    /**
     * Set due
     *
     * @param \DateTime $due
     * @return Invoice
     */
    public function setDue($due)
    {
        $this->due = $due;

        return $this;
    }

    /**
     * Get due
     *
     * @return \DateTime 
     */
    public function getDue()
    {
        return $this->due;
    }

    /**
     * Set paid
     *
     * @param \DateTime $paid
     * @return Invoice
     */
    public function setPaid($paid)
    {
        $this->paid = $paid;

        return $this;
    }

    /**
     * Get paid
     *
     * @return \DateTime 
     */
    public function getPaid()
    {
        return $this->paid;
    }

    /**
     * Set created
     *
     * @param \DateTime $created
     * @return Invoice
     */
    public function setCreated($created)
    {
        $this->created = $created;

        return $this;
    }

    /**
     * Get created
     *
     * @return \DateTime 
     */
    public function getCreated()
    {
        return $this->created;
    }

    /**
     * Set expense_amount
     *
     * @param float $expenseAmount
     * @return Invoice
     */
    public function setExpenseAmount($expenseAmount)
    {
        $this->expense_amount = $expenseAmount;

        return $this;
    }

    /**
     * Get expense_amount
     *
     * @return float 
     */
    public function getExpenseAmount()
    {
        return $this->expense_amount;
    }

    /**
     * Set total_amount
     *
     * @param float $totalAmount
     * @return Invoice
     */
    public function setTotalAmount($totalAmount)
    {
        $this->total_amount = $totalAmount;

        return $this;
    }

    /**
     * Get total_amount
     *
     * @return float 
     */
    public function getTotalAmount()
    {
        return $this->total_amount;
    }

    /**
     * Set attachment
     *
     * @param string $attachment
     * @return Invoice
     */
    public function setAttachment($attachment)
    {
        $this->attachment = $attachment;

        return $this;
    }

    /**
     * Get attachment
     *
     * @return string 
     */
    public function getAttachment()
    {
        return $this->attachment;
    }

    /**
     * Set vendor
     *
     * @param \TechPeople\InvoiceBundle\Entity\User $vendor
     * @return Invoice
     */
    public function setVendor(\TechPeople\InvoiceBundle\Entity\User $vendor = null)
    {
        $this->vendor = $vendor;

        return $this;
    }

    /**
     * Get vendor
     *
     * @return \TechPeople\InvoiceBundle\Entity\User 
     */
    public function getVendor()
    {
        return $this->vendor;
    }

    /**
     * Add invoice_items
     *
     * @param \TechPeople\InvoiceBundle\Entity\InvoiceItem $invoiceItems
     * @return Invoice
     */
    public function addInvoiceItem(\TechPeople\InvoiceBundle\Entity\InvoiceItem $invoiceItems)
    {
        $this->invoice_items[] = $invoiceItems;

        return $this;
    }

    /**
     * Remove invoice_items
     *
     * @param \TechPeople\InvoiceBundle\Entity\InvoiceItem $invoiceItems
     */
    public function removeInvoiceItem(\TechPeople\InvoiceBundle\Entity\InvoiceItem $invoiceItems)
    {
        $this->invoice_items->removeElement($invoiceItems);
    }

    /**
     * Get invoice_items
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getInvoiceItems()
    {
        return $this->invoice_items;
    }

    /**
     * Get path for attachment
     *
     * @param string $type Can return web path, or absolute path, web is default
     * @return null|string
     */
    public function getAttachmentPath($type='web')
    {
        if($type == 'absolute') {
            return null === $this->attachment_path
                ? null
                : $this->getUploadRootDir().'/'.$this->attachment_path;
        } else {
            return null === $this->attachment_path
                ? null
                : $this->getUploadDir().'/'.$this->attachment_path;
        }
    }

    protected function getUploadRootDir()
    {
        // the absolute directory path where uploaded
        // documents should be saved
        return __DIR__.'/../../../../web/'.$this->getUploadDir();
    }

    protected function getUploadDir()
    {
        // get rid of the __DIR__ so it doesn't screw up
        // when displaying uploaded doc/image in the view.
        return 'uploads/invoice/attachments';
    }

    /**
     * @ORM\PrePersist()
     * @ORM\PreUpdate()
     */
    public function preUpload()
    {
        if (null !== $this->attachment) {
            // do whatever you want to generate a unique name
            $filename = sha1(uniqid(mt_rand(), true));
            $this->attachment = $filename.'.'.$this->attachment->guessExtension();
        }
    }

    /**
     * @ORM\PostPersist()
     * @ORM\PostUpdate()
     */
    public function upload()
    {
        if (null === $this->attachment) {
            return;
        }

        // if there is an error when moving the file, an exception will
        // be automatically thrown by move(). This will properly prevent
        // the entity from being persisted to the database on error
        $this->attachment->move($this->getUploadRootDir(), $this->path);

        unset($this->attachment);
    }

    /**
     * @ORM\PostRemove()
     */
    public function removeUpload()
    {
        if ($file = $this->getAttachmentPath('absolute')) {
            unlink($file);
        }
    }
}

当我尝试提交编辑表单时,我收到以下错误(编辑表单由doctrine生成:generate:crud):

Fatal error: Call to a member function move() on a non-object

可能与以下相同:

Symfony forms. File upload

但这个问题没有得到解答。我希望发布第二个问题并不违反礼节。

我是Symfony2的新手,只是想学习我的方式,这让我很难过。我可以发布您需要的任何其他信息,让我知道是什么。

这是表单类:

<?php

namespace TechPeople\InvoiceBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class InvoiceType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('month')
            ->add('year')
            ->add('expenses')
            ->add('due')
            ->add('paid')
            ->add('created')
            ->add('expense_amount')
            ->add('total_amount')
            ->add('attachment')
            ->add('vendor')
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'TechPeople\InvoiceBundle\Entity\Invoice'
        ));
    }

    public function getName()
    {
        return 'techpeople_invoicebundle_invoicetype';
    }
}

这是控制器:

<?php

namespace TechPeople\InvoiceBundle\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

use TechPeople\InvoiceBundle\Entity\Invoice;
use TechPeople\InvoiceBundle\Form\InvoiceType;

/**
 * Invoice controller.
 *
 */
class InvoiceController extends Controller
{
    /**
     * Lists all Invoice entities.
     *
     */
    public function indexAction()
    {
        $em = $this->getDoctrine()->getManager();

        $entities = $em->getRepository('TechPeopleInvoiceBundle:Invoice')->findAll();

        return $this->render('TechPeopleInvoiceBundle:Invoice:index.html.twig', array(
            'entities' => $entities,
        ));
    }

    /**
     * Finds and displays a Invoice entity.
     *
     */
    public function showAction($id)
    {
        $em = $this->getDoctrine()->getManager();

        $entity = $em->getRepository('TechPeopleInvoiceBundle:Invoice')->find($id);

        if (!$entity) {
            throw $this->createNotFoundException('Unable to find Invoice entity.');
        }

        $deleteForm = $this->createDeleteForm($id);

        return $this->render('TechPeopleInvoiceBundle:Invoice:show.html.twig', array(
            'entity'      => $entity,
            'delete_form' => $deleteForm->createView(),        ));
    }

    /**
     * Displays a form to create a new Invoice entity.
     *
     */
    public function newAction()
    {
        $entity = new Invoice();
        $form   = $this->createForm(new InvoiceType(), $entity);

        return $this->render('TechPeopleInvoiceBundle:Invoice:new.html.twig', array(
            'entity' => $entity,
            'form'   => $form->createView(),
        ));
    }

    /**
     * Creates a new Invoice entity.
     *
     */
    public function createAction(Request $request)
    {
        $entity  = new Invoice();
        $form = $this->createForm(new InvoiceType(), $entity);
        $form->bind($request);

        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($entity);
            $em->flush();

            return $this->redirect($this->generateUrl('invoice_show', array('id' => $entity->getId())));
        }

        return $this->render('TechPeopleInvoiceBundle:Invoice:new.html.twig', array(
            'entity' => $entity,
            'form'   => $form->createView(),
        ));
    }

    /**
     * Displays a form to edit an existing Invoice entity.
     *
     */
    public function editAction($id)
    {
        $em = $this->getDoctrine()->getManager();

        $entity = $em->getRepository('TechPeopleInvoiceBundle:Invoice')->find($id);

        if (!$entity) {
            throw $this->createNotFoundException('Unable to find Invoice entity.');
        }

        $editForm = $this->createForm(new InvoiceType(), $entity);
        $deleteForm = $this->createDeleteForm($id);

        return $this->render('TechPeopleInvoiceBundle:Invoice:edit.html.twig', array(
            'entity'      => $entity,
            'edit_form'   => $editForm->createView(),
            'delete_form' => $deleteForm->createView(),
        ));
    }

    /**
     * Edits an existing Invoice entity.
     *
     */
    public function updateAction(Request $request, $id)
    {
        $em = $this->getDoctrine()->getManager();

        $entity = $em->getRepository('TechPeopleInvoiceBundle:Invoice')->find($id);

        if (!$entity) {
            throw $this->createNotFoundException('Unable to find Invoice entity.');
        }

        $deleteForm = $this->createDeleteForm($id);
        $editForm = $this->createForm(new InvoiceType(), $entity);
        $editForm->bind($request);

        if ($editForm->isValid()) {
            $em->persist($entity);
            $em->flush();

            return $this->redirect($this->generateUrl('invoice_edit', array('id' => $id)));
        }

        return $this->render('TechPeopleInvoiceBundle:Invoice:edit.html.twig', array(
            'entity'      => $entity,
            'edit_form'   => $editForm->createView(),
            'delete_form' => $deleteForm->createView(),
        ));
    }

    /**
     * Deletes a Invoice entity.
     *
     */
    public function deleteAction(Request $request, $id)
    {
        $form = $this->createDeleteForm($id);
        $form->bind($request);

        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $entity = $em->getRepository('TechPeopleInvoiceBundle:Invoice')->find($id);

            if (!$entity) {
                throw $this->createNotFoundException('Unable to find Invoice entity.');
            }

            $em->remove($entity);
            $em->flush();
        }

        return $this->redirect($this->generateUrl('invoice'));
    }

    private function createDeleteForm($id)
    {
        return $this->createFormBuilder(array('id' => $id))
            ->add('id', 'hidden')
            ->getForm()
        ;
    }
}

这些都是非常基本的东西,直接来自文档,因为,正如我所说,我只是在学习Symfony。任何帮助非常感谢。

1 个答案:

答案 0 :(得分:2)

$ this-&gt;附件必须是UploadedFile对象。

但是在你的方法preUpload()中你犯了一个错误,并为字符串覆盖它:

$this->attachment = $filename.'.'.$this->attachment->guessExtension();

然后调用upload()方法并检查$ this-&gt;附件是否为null,这是真的,因为它是一个字符串:

if (null === $this->attachment) {
     return;
}

在字符串上执行 - &gt; move()会显示错误;)

所以回答一下,在preUpload()方法中替换这一行:

$this->attachment= $filename.'.'.$this->attachment->guessExtension();

有关:

$this->path = $filename.'.'.$this->attachment->guessExtension();