使用 Sonata Admin 和 Doctrine 上传文件时出错

Posted

技术标签:

【中文标题】使用 Sonata Admin 和 Doctrine 上传文件时出错【英文标题】:Error uploading file using Sonata Admin and Doctirne 【发布时间】:2016-06-02 07:43:28 【问题描述】:

我正在遵循有关处理学说上传和奏鸣曲管理员的指南。 我只用 id、路径和文件(图像)设置了我的实体:

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

/**
 * @ORM\Entity
 * @ORM\Table(name="viaggio_perfetto")
*/
class ViaggioPerfetto

    private $temp;

    /**
    * @ORM\Column(type="integer")
    * @ORM\GeneratedValue(strategy="AUTO")
    * @ORM\Id
    */
    protected $id;


    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    protected $path;

    /**
     * @Assert\File(maxSize="6000000")
     */
    protected $file;

    /**
     * Get file.
     *
     * @return UploadedFile
     */
    public function getFile()
    
        return $this->file;
    

    /**
     * Sets file.
     *
     * @param UploadedFile $file
     */
    public function setFile(UploadedFile $file = null)
    
        $this->file = $file;
        // check if we have an old image path
        if (isset($this->path)) 
            // store the old name to delete after the update
            $this->temp = $this->path;
            $this->path = null;
         else 
            $this->path = 'initial';
        
    

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

    /**
     * @ORM\PostPersist()
     * @ORM\PostUpdate()
     */
    public function upload()
    
        if (null === $this->getFile()) 
            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->getFile()->move($this->getUploadRootDir(), $this->path);

        // check if we have an old image
        if (isset($this->temp)) 
            // delete the old image
            unlink($this->getUploadRootDir().'/'.$this->temp);
            // clear the temp image path
            $this->temp = null;
        
        $this->file = null;
    

    /**
     * @ORM\PostRemove()
     */
    public function removeUpload()
    
        $file = $this->getAbsolutePath();
        if ($file) 
            unlink($file);
        
    

    public function getAbsolutePath()
    
        return null === $this->path
            ? null
            : $this->getUploadRootDir().'/'.$this->path;
    

    public function getWebPath()
    
        return null === $this->path
            ? null
            : $this->getUploadDir().'/'.$this->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/documents';
    

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


    /**
     * Set path
     *
     * @param string $path
     *
     * @return ViaggioPerfetto
     */
    public function setPath($path)
    
        $this->path = $path;

        return $this;
    

    /**
     * Get path
     *
     * @return string
     */
    public function getPath()
    
        return $this->path;
    

为了更好地阅读实体,我删除了一些文件。 对于这个实体,我遵循了 symfony 食谱。 web/uploads下的文件夹有777权限。

然后我添加到奏鸣曲管理员:

protected function configureFormFields(FormMapper $formMapper)

    $formMapper->add('title', 'text');
    $formMapper->add('text', 'text');
    $formMapper->add('startDate', 'date');
    $formMapper->add('endDate', 'date');
    $formMapper->add('active', 'checkbox', array('required' => false));
    $formMapper->add('file', 'file');


protected function configureDatagridFilters(DatagridMapper $datagridMapper)

    $datagridMapper->add('text');


protected function configureListFields(ListMapper $listMapper)

    $listMapper->addIdentifier('title');
    $listMapper->add('text');

现在我登录奏鸣曲管理页面并尝试创建新实体。 除了文件之外,我的数据库中的所有字段都正确。 web/uploads/documents 下没有文件,并且数据库中的路径文件中没有路径(如果未设置路径,我在 SetFile 函数中设置了“初始”)。

我不知道我错在哪里。感谢您的帮助。

【问题讨论】:

【参考方案1】:

问题是您从不调用实体的upload 方法。

将以下方法添加到您的管理类(奏鸣曲):

/**
 * Handles file upload on create.
 *
 * @param object $created The newly created entity
 */
public function prePersist($created)

    $created->upload();


/**
 * Handles file upload on update.
 *
 * @param object $updated The updated entity
 */
public function preUpdate($updated)

    $updated->upload();

它应该可以工作。

这将在持久化/更新实体之前调用您的实体的upload 方法。

参见奏鸣曲的对应部分File upload recipe。

【讨论】:

【参考方案2】:

你必须添加

* @ORM\HasLifecycleCallbacks

阻止

/**
 * @ORM\Entity
 * @ORM\Table(name="viaggio_perfetto")
*/

供使用

/**
* @ORM\PrePersist()
* @ORM\PreUpdate()
*/

【讨论】:

以上是关于使用 Sonata Admin 和 Doctrine 上传文件时出错的主要内容,如果未能解决你的问题,请参考以下文章

Symfony - Sonata Abstract Admin 和 getDoctrine

Sonata Admin Bundle 中的标签

禁用 SonataUserBundle sonata.user.admin.group 服务

Sonata Admin 嵌套表单

Sonata admin:默认选择马赛克

Sonata Media Bundle 与 Sonata Admin Bundle 3.0(或 2.4)