2013-09-24 28 views
4

我一直在使用基于Symfony 2.3中的食谱收件人How To Handle File Uploads With Doctrine的附件实体。Symfony HttpFoundation UploadedFile“未上传,因为未知错误”使用Doctrine DataFixtures

它运作良好,即使在功能测试。但是在Doctrine DataFixtures中使用它会导致我遇到问题。

[Symfony\Component\HttpFoundation\File\Exception\FileException]
The file "o-rly-copy.jpg" was not uploaded due to an unknown error.

这是没有帮助的,但是我没跑php app/console doctrine:fixtures:load -v,弹出一个堆栈跟踪,并将其显示在没有抛出异常的持续性的方法,但在$manager->flush()

Attachment::setFile()需要一个UploadedFile的实例,所以我想知道是否有方法。

它出现在错误发生时对Symfony\Component\HttpFoundation\File\UploadedFile

return $this->test ? $isOk : $isOk && is_uploaded_file($this->getPathname()) 

条件225线is_uploaded_file()回报false因为该文件已经在服务器上。

<?php 

/** 
* Prepopulate the database with image attachments. 
*/ 
final class AttachmentFixtures extends AbstractFixture implements OrderedFixtureInterface, ContainerAwareInterface 
{ 
    private static $imageData = array(
     array(
      'name' => "O RLY?", 
      'file' => "o-rly", 
      'type' => "jpg", 
     ), 
     //... 
    ); 

    public function getPathToImages() 
    { 
     return $this->container->get('kernel')->getRootDir() . '/../src/Acme/DemoBundle/Resources/public/default/images'; 
    } 

    public function getPathToUploads() 
    { 
     return $this->container->get('kernel')->getRootDir() . '/../web/uploads/fixtures'; 
    } 

    /** 
    * {@inheritDoc} 
    */ 
    public function load(ObjectManager $manager) 
    { 
     $imageReferences = array(); 
     $filesystem = $this->container->get('filesystem'); 

     foreach (self::$imageData as $image) { 
      $imageFilename   = sprintf('%s.%s',  $image['file'], $image['type']); 
      $copiedImageFilename = sprintf('%s-copy.%s', $image['file'], $image['type']); 

      $pathToImageFile = sprintf('%s/%s', $this->getPathToImages(), $imageFilename); 

      try { 
       $filesystem->copy($pathToImageFile, $pathToCopiedFile = sprintf('%s/%s', $this->getPathToUploads(), $copiedImageFilename)); 
       $filesystem->chmod($pathToCopiedFile, 0664); 
      } catch (IOException $e) { 
       $this->container->get('logger')->err("An error occurred while copying the file or changing permissions."); 
      } 

      $imageFile = new UploadedFile(
       $pathToCopiedFile,            // The full temporary path to the file 
       $copiedImageFilename,           // The original file name 
       'image/' . 'jpg' === $image['type'] ? 'jpeg' : $image['type'], // Mime type - The type of the file as would be provided by PHP 
       filesize($pathToCopiedFile), 
       null, 
       null, 
       true 
      ); 

      $imageAttachment = new Attachment(); 

      $imageAttachment->setName($image['name']); 
      $imageAttachment->setFile($imageFile); 

      // Populate a reference array for later use 
      $imageReferences['attachment-'.$image['file']] = $imageAttachment; 

      $manager->persist($imageAttachment); 
     } 

     $manager->flush(); // <-- Exception throw here 


     // Create references for each image to be used by other entities that 
     // maintain a relationship with that image. 
     foreach ($imageReferences as $referenceName => $image) { 
      $this->addReference($referenceName, $image); 
     } 
    } 
} 

回答

3

Thanks to stof,解决的办法是使Attachment::setFile()(或Document::setFile()如果使用食谱例如)暗示为UploadedFile的父类,Symfony\Component\HttpFoundation\File\File的一个实例,并且在夹具类,创建一个新实例,并将其传递到setFile方法

Attachment.php

<?php 

namespace Acme\DemoBundle\Entity; 

use Symfony\Component\HttpFoundation\File\File; 
//... 

class Attachment 
{ 
    /** 
    * Sets file. 
    * 
    * @param File $file 
    */ 
    public function setFile(File $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'; 
     } 
    } 

    //... 
} 

AttachmentF ixtures.php

<?php 

namespace Acme\DemoBundle\DataFixtures\ORM; 

use Symfony\Component\HttpFoundation\File\File; 
//... 

class AttachmentFixtures //... 
{ 
    //... 

    public function load(ObjectManager $manager) 
    { 
     //... 
     $imageFile = new File($pathToCopiedFile); 

     $imageAttachment = new Attachment(); 

     $imageAttachment->setFile($imageFile); 
     //... 
    } 
} 
1

现在有一个更好的解决方案:

UploadedFile构造函数有一个布尔$test参数,禁用使用is_uploaded_file检查。该参数已添加用于测试/夹具代码。

只需将其设置为true,检查UploadedFile将不再是一个问题了。

实施例:

// My data fixture code. 
$test = true; 
$userPhoto->setImageFile(new UploadedFile($photoDir . $photoFile, $photoFile, null, null, null, $test));