问题
I researched the How to Handle File Uploads with Doctrine and I don't want to hard-code the __DIR__.'/../../../../web/'.$this->getUploadDir();
path because maybe in future I will change the web/
directory. How to do it more flexible? I found this but it doesn't answer the question how to do it more flexible from inside the Entity
回答1:
You shouldn't use entity class as a form model here. It's simply not suitable for that job. If the entity has the path
property, the only valid values it can stores are: null
(in case lack of the file) and string representing the path to the file.
Create a separate class, that's gonna be a model for your form:
class MyFormModel { /** @Assert\File */ private $file; /** @Assert\Valid */ private $entity; // constructor, getters, setters, other methods }
In your form handler (separate object configured through DIC; recommended) or the controller:
... 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 ...; } ...
Inside form handler/controller you can access any dependencies/properties from DIC (including path to the upload directory).
The tutorial you've linked works, but it's an example of bad design. The entities should not be aware of file upload.
回答2:
To access the root directory from outside the controller you can simply inject '%kernel.root_dir%' as an argument in your services configuration.
service_name:
class: Namespace\Bundle\etc
arguments: ['%kernel.root_dir%']
Then you can get the web root in the class constructor:
public function __construct($rootDir)
{
$this->webRoot = realpath($rootDir . '/../web');
}
回答3:
You can use a variable in your parameters.yml. Like this you'll can change path when you want.
for example :
# app/config/parameters.yml
# Upload directories
upload_avatar_dir: /uploads/avatars
upload_content_dir: /uploads/content
upload_product_offer_dir: /uploads/product-offer
...
回答4:
I handled this by creating an abstract class that Entities may extend if they are handling file uploads as described in the Symfony Documentation. I created the files array so I could create a copy of the existing file path in the set methods so it could be deleted off the file system on a successful update or delete without defining any additional properties in the Entity proper.
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();
}
来源:https://stackoverflow.com/questions/12893657/how-to-get-web-directory-path-from-inside-entity