我研究了How to Handle File Uploads with Doctrine并且我不想对__DIR__.'/../../../../web/'.$this->getUploadDir();
路径进行硬编码,因为将来我可能会更改web/
目录。怎么做更灵活?我找到了this,但它没有回答如何从实体内部更灵活地解决这个问题
答案 0 :(得分:6)
您不应在此处使用实体类作为表单模型。它根本不适合那份工作。如果实体具有path
属性,则它可以存储的唯一有效值为:null
(如果缺少文件)和表示文件路径的字符串。
创建一个单独的类,它将成为您表单的模型:
class MyFormModel {
/** @Assert\File */
private $file;
/** @Assert\Valid */
private $entity;
// constructor, getters, setters, other methods
}
在表单处理程序(通过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访问任何依赖项/属性(包括上载目录的路径)。
您链接的教程有效,但这是糟糕设计的一个例子。 实体不应了解文件上传。
答案 1 :(得分:1)
要从控制器外部访问根目录,只需在服务配置中注入'%kernel.root_dir%'作为参数。
service_name:
class: Namespace\Bundle\etc
arguments: ['%kernel.root_dir%']
然后,您可以在类构造函数中获取Web根目录:
public function __construct($rootDir)
{
$this->webRoot = realpath($rootDir . '/../web');
}
答案 2 :(得分:-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
...
答案 3 :(得分:-1)
我通过创建一个抽象类来处理这个问题,实体可以在处理文件上传时扩展,如Symfony文档中所述。我创建了文件数组,因此我可以在set方法中创建现有文件路径的副本,以便在成功更新或删除时从文件系统中删除它,而无需在实体中定义任何其他属性。
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();
}