这是我的表单类型:
class TestFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('thumbnail', 'hidden', array(
'label' => 'Thumbnail',
'label_attr' => array(
'class' => 'col-xs-2 control-label'
),
'required' => false,
'error_bubbling' => true,
'required' => false
));
$builder->add('thumbnail_data', 'file', array(
'error_bubbling' => true,
'required' => false
));
}
public function setDefaultOptions(\Symfony\Component\OptionsResolver\OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'X\LibraryBundle\Entity\Test',
'cascade_validation' => true,
'error_bubbling' => true,
));
}
public function getName()
{
return 'test';
}
}
这是实体,重要的部分是setThumbnailData($ file)方法,它存储缩略图文件并通过setThumbnail(string)方法设置缩略图路径。
<?php
namespace X\LibraryBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Test
*
* @ORM\Table(name="test")
* @ORM\Entity(repositoryClass="X\LibraryBundle\Repository\TestRepository")
*/
class Test
{
/**
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="text", nullable=true)
*/
protected $thumbnail;
/**
* Set thumbnail
*
* @param string $thumbnail
* @return Test
*/
public function setThumbnail($thumbnail)
{
$this->thumbnail = $thumbnail;
return $this;
}
/**
* Get thumbnail
*
* @return string
*/
public function getThumbnail()
{
return $this->thumbnail;
}
/**
* This will save file to disk
* @param $file
*/
public function setThumbnailData($file) {
if($file !== null && $file !== false)
{
$fileName = $file->getClientOriginalName();
$baseDir = __DIR__ . '/../../../../../../../web/uploads/promotional_material/';
$dir = sha1(microtime());
while (is_dir($baseDir . $dir)) {
$dir = sha1(microtime());
}
mkdir($baseDir . $dir);
$this->setThumbnail('/uploads/promotional_material/' . $dir . '/' . $fileName);
$file->move($baseDir . $dir, $fileName);
}
}
public function getThumbnailData() {
return '';
}
}
现在问题是,如果表单遇到验证错误,则以下树枝线产生不同的输出,从第二行输出正确的值,另一个产生原始缩略图路径。因此,如果我使用{{form_widget(form.thumbnail)}}输出缩略图输入,我将获得原始缩略图路径,而不是应通过setThumbnailData()方法更改的路径。
{{ dump(form.thumbnail.vars.data) }}
{{ dump(form.vars.data.thumbnail) }}
使用setThumbnailData()方法设置缩略图是否会导致问题?不知道如何解决这个问题,而不是硬编码输入,如下所示:
<input type="hidden" name="test[thumbnail]" value="{{ form.vars.value.thumbnail }}"/>
答案 0 :(得分:5)
我无法完全解决您的问题,因为在我看来,您的做法是错误的。数据类实际上只负责保存您的数据,因此您的方法set/getThumbnailData
应该如下所示
<?php
// ...
private $thumbnailData;
public function setThumbnailData(UploadedFile $thumbnailData) {
$this->thumbnailData = $thumbnailData;
}
public function getThumbnailData() {
return $this->thumbnailData;
}
在你的控制器中你有这样的东西:
<?php
// ...
public function formAction() {
$form = // ...
$form->handleRequest($request);
if($form->isValid()) {
$test = $form->getData();
/* @var $test Test */
$thumbnailUploader = $this->get('thumbnail_uploader');
/* @var $thumbnailUploader ThumbnailUploadService */
$file = $test->getThumbnailData();
$filename = $file->getClientOriginalName();
$thumbnailUploader->upload($filename, $file);
// ...
}
}
我建议将与表单或请求无关的所有逻辑移动到服务中。在这种情况下,您的服务可以更通用地处理具有给定文件名的任何symfony文件。
<?php
class ThumbnailUploadService {
/**
* @param $file Symfony\Component\HttpFoundation\File\File
*
*/
public function upload($filename, File $file) {
// ...
}
}
答案 1 :(得分:0)
还有另一种使用回调的方法。在这里,我给你一个通用类来上传图像并生成缩略图。我希望这对你有用。此类管理创建更新时自动生成的文件o删除实体。
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints as DoctrineAssert;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints as Assert;
use App\MyBundleBundle\Util\Util;
/**
* Image
*
* @ORM\Table(name="image")
* @ORM\Entity()
* @ORM\HasLifecycleCallbacks
*/
class Image
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string")
* @Assert\NotBlank()
*/
private $name;
private $temp;
/**
* @ORM\Column(type="string", length=255)
*/
protected $path;
/**
* @Assert\Image(maxSize="5M")
*/
private $file;
/**
* Sets file.
*
* @param UploadedFile $file
*/
public function setFile(UploadedFile $file = null)
{
$this->file= $file;
if (isset($this->path)) {
$this->temp = $this->path;
$this->path= null;
} else {
$this->path= 'initial';
}
}
/**
* Get file.
*
* @return UploadedFile
*/
public function getFile()
{
return $this->file;
}
/**
* @ORM\PrePersist()
* @ORM\PreUpdate()
*/
public function preUpload()
{
if (null !== $this->getFile()) {
// do whatever you want to generate a unique name
$filename = Util::getSlug($this->name) . uniqid() . '.' . $this->file->guessExtension();
$this->path = $filename;
}
}
/**
* @ORM\PostPersist()
* @ORM\PostUpdate()
*/
public function upload()
{
if (null === $this->getFile()) {
return;
}
$this->getFile()->move($this->getUploadRootDir(), $this->path);
if (isset($this->temp)) {
if (file_exists($this->getUploadRootDir() .'/'. $this->temp)) {
unlink($this->getUploadRootDir() . '/' . $this->temp);
}
$this->temp = null;
}
$this->file= null;
//create a dir to save de thumbnails
if (!file_exists($this->getUploadRootDir() . '/thumbnails')) {
mkdir($this->getUploadRootDir() . '/thumbnails');
}
//call a method in util class to generate the thumbnails
Util::redim($this->getUploadRootDir() . '/' . $this->path, $this->getUploadRootDir() . '/thumbnails/' . $this->path, 128, 128);
}
/**
* @ORM\PostRemove()
*/
public function removeUpload()
{
//This is to remove the files when the entity is delete
if ($file = $this->getAbsolutePath()) {
if (file_exists($file)) {
unlink($file);
$thumb = $this->getUploadRootDir() . '/thumbnails/' . $this->getPath();
if (file_exists($thumb)) {
unlink($thumb);
}
}
}
}
public function getAbsolutePath()
{
return null === $this->path ? null : $this->getUploadRootDir() . '/' . $this->path;
}
public function getWebPath()
{
return null === $this->path? null :
$this->getUploadDir() . '/' . $this->path;
}
protected function getUploadRootDir()
{
return $this->getUploadDir();
}
protected function getUploadDir()
{
return 'uploads/image/';
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set nombre
*
* @param string $name
* @return Image
*/
public function setName($name)
{
$this->name= $name;
return $this;
}
/**
* Get nombre
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set path
*
* @param string $path
* @return Imagen
*/
public function setPath($path)
{
$this->path= $path;
return $this;
}
/**
* Get path
*
* @return string
*/
public function getPath()
{
return $this->path;
}
public function __toString()
{
return $this->getName();
}
}