2012-10-15 57 views

回答

6

你不應該在這裏使用實體類作爲表單模型。這根本不適合那份工作。如果實體具有path屬性,則它可存儲的唯一有效值爲:null(如果文件不存在)以及表示文件路徑的字符串。

  1. 創建一個單獨的類,即會是爲表單的模型:

    class MyFormModel { 
        /** @Assert\File */ 
        private $file; 
    
        /** @Assert\Valid */ 
        private $entity; 
    
        // constructor, getters, setters, other methods 
    } 
    
  2. 在您的表單處理程序(通過DIC配置單獨的對象;推薦)或控制器:

    ... 
    if ($form->isValid()) { 
        /** @var \Symfony\Component\HttpFoundation\File\UploadedFile */ 
        $file = $form->getData()->getFile(); 
    
        /** @var \Your\Entity\Class */ 
        $entity = $form->getData()->getEntity(); 
    
        // move the file 
        // $path = '/path/to/the/moved/file'; 
    
        $entity->setPath($path); 
    
        $someEntityManager->persist($entity); 
    
        return ...; 
    } 
    ... 
    

在表單處理程序/控制器中,您可以訪問DIC中的任何依賴關係/屬性(包括路徑到上傳目錄)。


您鏈接的教程有效,但這是一個糟糕的設計。實體不應該知道文件上傳。

+0

我明白了。謝謝。但是,如何使用生命週期回調來管理用您的代碼刪除文件? – Mikhail

+0

基於以前的經驗,我建議你存儲絕對路徑(或者至少相對於webroot路徑)。 –

+0

創建一個偵聽器,訂閱'preRemove'(或'preDelete')事件(參見[how to](http: //symfony.com/doc/current/cookbook/doctrine/event_listeners_subscribers.html))並在那裏取消鏈接文件。 – Crozin

-1

你可以在你的parameters.yml中使用一個變量。像這樣你可以在你想要的時候改變路徑。

例如:

# app/config/parameters.yml 
# Upload directories 
upload_avatar_dir:  /uploads/avatars 
upload_content_dir:  /uploads/content 
upload_product_offer_dir: /uploads/product-offer 
... 
+0

如何在實體內部獲取它? – Mikhail

+0

您的實體不知道文檔的存儲位置。呦可以將這個責任移交給你的控制器。或者你可以添加一個路徑屬性到你的實體 –

1

我通過創建一個抽象類,如果他們正在處理文件上傳如Symfony的文檔中描述該實體可以延伸這樣處理。我創建了文件數組,以便我可以在set方法中創建現有文件路徑的副本,以便在成功執行更新或刪除操作時將其從文件系統中刪除,而無需在Entity中定義任何其他屬性。

use Symfony\Component\HttpFoundation\File\File; 

abstract class FileUploadEntity 
{ 
    private $files; 

    public function __set($name, File $value) 
    { 
     $this->files[$name] = $value; 
    } 

    public function __get($name) 
    { 
     if (!is_array($this->files)) $this->files = array(); 

     if (!array_key_exists($name, $this->files)) { 
      return null; 
     } 
     return $this->files[$name]; 
    } 

    public function getUploadRootDirectory() 
    { 
     return $this->getWebDirectory() . $this->getUploadDirectory(); 
    } 

    public function getWebDirectory() 
    { 
     return __DIR__ . "/../../../../web/"; 
    } 

    public function getUploadDirectory() 
    { 
     $year = date("Y"); 
     $month= date("m"); 

     return "images/uploads/$year/$month/"; 
    } 

    public function getEncodedFilename($name) 
    { 
     return sha1($name . uniqid(mt_rand(), true)); 
    } 

    // this should be a PrePersist method 
    abstract public function processImages(); 

    // This should be defined as a Doctrine PreUpdate Method 
    abstract public function checkImages(); 

    // this should be a PostPersist method 
    abstract public function upload(); 

    // this should be a PostUpdate method and delete old files 
    abstract public function checkUpload(); 

    // This should be a PostRemove method and delete files 
    abstract public function deleteFile(); 
} 
+1

嗯,我看到你使用了__DIR__。 「/../../../../web/」',但我的問題是如何避免它。 – Mikhail

+0

我不確定有沒有。看起來我能做的最好的事情就是將它定義在一個地方。 –

+0

明白了。謝謝你的解決方案湯姆 – Mikhail

1

要從控制器外部訪問根目錄,只需在服務配置中注入'%kernel.root_dir%'作爲參數即可。

service_name: 
    class: Namespace\Bundle\etc 
    arguments: ['%kernel.root_dir%'] 

然後你就可以得到網站根在類的構造函數:

public function __construct($rootDir) 
{ 
    $this->webRoot = realpath($rootDir . '/../web'); 
}