Реализовано скачивание файлов поверх документации. Но когда я решил использовать «несколько», выдать ошибку
"Catchable Fatal Error: Argument 1 passed to Kulabuhov\MainBundle\Entity\Photo::setFile() must be an instance of Symfony\Component\HttpFoundation\File\UploadedFile, array given,"
. Я понимаю, что вместо Object передается массив. Но как реализовать несколько загрузок файлов, не нарушая ничего, что вы написали в документации?
$builder
->add('file','file',['multiple'=>true])
->add('article')
;
Вы предоставили очень мало кода о том, как вы использовали функцию загрузки файлов с помощью Doctrine, что было бы полезно, потому что существует дюжина способов приблизиться к выполнению соглашения об именовании файлов, плюс вы даже не показали свой собственный попытаться изменить сущность, с которой вы работаете, обрабатывать загрузку нескольких файлов, но я дам вам шанс. Это предполагает, что вы следовали всем инструкциям до самого конца.
Когда вы следовали инструкциям, вы, вероятно, создали setFile
функционировать как что-то вроде:
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';
}
}
но, конечно, вы отправляете массив UploadedFile
возражает против setFile
функция, которая не соответствует UploadedFile
аргумент, что это нужно. Вы также сохраняете только одну строку для пути, поэтому вы должны исправить это тоже.
Итак, сначала вы должны изменить свой $path
тип переменной из string
в некоторый тип массива. Предполагая, что вам не нужно много данных, связанных с каждым файлом и именами файлов не будет запятых в них, давайте просто придерживаться simple_array
:
/**
* @ORM\Column(name="paths", type="simple_array")
*/
private $paths = array();
И теперь вам нужен массив, объявленный для file
атрибут:
/**
* @Assert\File(maxSize="60000000")
*/
private $files = array();
Теперь вы должны изменить свой setFile
функция для обработки ввода массива (давайте переименуем в setFiles
для согласованности):
public function setFiles($files)
{
$this->files = $files;
// In this scenario, we'll delete the old batch of uploads, so store it in $temp
if (!empty($this->paths)) {
$this->temp = $this->getAbsolutePaths();
}
$this->paths = array();
}
А также getFiles
:
public function getFiles()
{
return $this->files;
}
Теперь ваш новый upload()
функция:
/**
* @ORM\PostPersist()
* @ORM\PostUpdate()
*/
public function upload()
{
if (empty($this->files)) {
return;
}
// Now we have to iterate through each file object
foreach ($this->getFiles() as $file) {
// Change $tempPath to whatever random filename strategy you use
$tempPath = sha1(uniqid(mt_rand(), true)) . '.' . $file->guessExtension();
$file->move(
$this->getUploadRootDir(),
$tempPath
);
// Now add it to the paths array
$this->paths[] = $tempPath;
}
// Need to delete all of the old files
foreach ($this->temp as $del) {
if (is_file($del)) {
unlink($del);
}
}
// Reset the $files var
$files = array();
}
а затем для удаления полностью удалите все файлы:
/**
* @ORM\PostRemove()
*/
public function removeUpload()
{
foreach ($this->getAbsolutePaths() as $path) {
if (is_file($path)) {
unlink($path);
}
}
}
Поскольку, когда вы работаете с объектом, вы теперь обрабатываете массив путей, поэтому вам необходимо обновить также функции веба и абсолютного пути:
public function getAbsolutePaths()
{
$out = array();
foreach ($this->getPaths() as $path) {
$out[] = $this->getUploadRootDir().'/'.$this->path;
}
return $out;
}
public function getWebPath()
{
$out = array();
foreach ($this->getPaths() as $path) {
$out[] = '/' . $this->getUploadDir() . '/' . $this->path;
}
}
и вуаля … как только вы обновите свой строитель, чтобы перейти к files
вместо file
, он должен уметь правильно обрабатывать несколько загрузок файлов. Хотя приведенный выше код непроверенной, это должно дать вам много работы.
Проблема не в вашей форме, а в вашей модели. setFile()
метод на Photo
предназначен для получения UploadedFile
, а не массив. Если фотография должна иметь несколько файлов, объявите связь как OneToMany и реализуйте setFiles()
функция, которая принимает массив:
protected $files;
function setFiles(array $files)
{
$this->files = $files;
return $this;
}