2014-09-08 5 views
3

Я собираюсь приступить к попытке добавить поле профиля изображения к своему пользовательскому объекту в проекте symfony2, над которым я работаю, который использует FOSUserBundle. У меня такое чувство, что это должно быть очень просто, однако я не нашел полезной документации, объясняющей, как это сделать.Symfony2 FOSUserBundle Загрузка файлов (профиль Pic) Советы?

На данный момент я планирую добавить неотображенное поле к моему объекту формы (который я расширил из общей формы ProfileEdit), которая берет загруженный файл. Затем я создам прослушиватель событий для FOSUserEvents::PROFILE_EDIT_SUCCESS или FOSUserEvents::PROFILE_EDIT_COMPLETED, который примет форму, обработает загрузку файла и сохранит путь к загруженному файлу (с методами для получения общедоступного URL-адреса и абсолютного пути) к объекту User перед добавив сообщение в Flashbag, чтобы сказать, что оно было успешным или неудачным. Это действительно правильный/лучший способ сделать это? Или я чего-то не хватает? Действительно ли эта функциональность еще не включена в FOSUserBundle? Если это так, я не нашел документы для этого, но мне понравилось бы, если бы это было ...

Любая помощь/советы/советы вуду были бы очень благодарны!

+0

Кажется, альтернативой этому является добавление прослушиватель событий самой формы. Есть ли у кого-нибудь опыт в отношении того, что предпочтительнее? –

ответ

8

Итак, оказывается, что я теряюсь, отвечая на этот вопрос: загрузка файла не должна обрабатываться FOSUserBundle как таковой, а с помощью Doctrine. Я добавил свойство для своего объекта User, который не сохраняется, но который просто используется формой для редактирования профиля пользователя. В приведенном ниже коде это свойство - $profilePictureFile. Обратные вызовы жизненного цикла затем гарантируют, что этот файл будет скопирован в соответствующее место до того, как объект будет сохранен (и аналогичным образом отредактирован и удален).

Тем не менее, я думал, что отправлю ответ рядом с моим кодом здесь, чтобы помочь другим, которые хотят в будущем добавлять фотографии профиля к пользователю в FOSUserBundle.

Соответствующая документация: http://symfony.com/doc/current/cookbook/doctrine/file_uploads.html https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/overriding_forms.rst

<?php 
// DAWeldonExampleBundle/Entity/User.php 
namespace DAWeldon\Example\UserBundle\Entity; 

use FOS\UserBundle\Model\User as BaseUser; 
use Doctrine\ORM\Mapping as ORM; 
use Symfony\Component\Validator\Constraints as Assert; 
use Symfony\Component\HttpFoundation\File\UploadedFile; 
use Symfony\Component\Security\Core\Util\SecureRandom; 

/** 
* @ORM\Entity() 
* @ORM\HasLifecycleCallbacks() 
* @ORM\Table(name="fos_user") 
*/ 
class User extends BaseUser 
{ 
    /** 
    * @ORM\Id 
    * @ORM\Column(type="integer") 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    protected $id; 

    /** 
    * @ORM\Column(type="datetime") 
    */ 
    protected $lastEdited; 

    /** 
    * @ORM\Column(type="string", length=255) 
    * @Assert\NotBlank(message="Please enter your surname.", groups={"Registration", "Profile"}) 
    */ 
    protected $surname; 

    /** 
    * @ORM\Column(type="string", length=255) 
    * @Assert\NotBlank(message="Please enter your forename.", groups={"Registration", "Profile"}) 
    */ 
    protected $forename; 

    /** 
    * @ORM\Column(type="string", length=255, nullable=true) 
    */ 
    protected $nickname; 

    /** 
    * @Assert\File(maxSize="2048k") 
    * @Assert\Image(mimeTypesMessage="Please upload a valid image.") 
    */ 
    protected $profilePictureFile; 

    // for temporary storage 
    private $tempProfilePicturePath; 

    /** 
    * @ORM\Column(type="string", length=255, nullable=true) 
    */ 
    protected $profilePicturePath; 

    public function __construct() 
    { 
     parent::__construct(); 
     // your own logic 
    } 

    /** 
    * Get id 
    * 
    * @return integer 
    */ 
    public function getId() 
    { 
     return $this->id; 
    } 

    /** 
    * Set surname 
    * 
    * @param string $surname 
    * @return User 
    */ 
    public function setSurname($surname) 
    { 
     $this->surname = $surname; 

     return $this; 
    } 

    /** 
    * Get surname 
    * 
    * @return string 
    */ 
    public function getSurname() 
    { 
     return $this->surname; 
    } 

    /** 
    * Set forename 
    * 
    * @param string $forename 
    * @return User 
    */ 
    public function setForename($forename) 
    { 
     $this->forename = $forename; 

     return $this; 
    } 

    /** 
    * Get forename 
    * 
    * @return string 
    */ 
    public function getForename() 
    { 
     return $this->forename; 
    } 

    /** 
    * Asks whether the user is granted a particular role 
    * 
    * @return boolean 
    */ 
    public function isGranted($role) 
    { 
     return in_array($role, $this->getRoles()); 
    } 

    /** 
    * Set nickname 
    * 
    * @param string $nickname 
    * @return User 
    */ 
    public function setNickname($nickname) 
    { 
     $this->nickname = $nickname; 

     return $this; 
    } 

    /** 
    * Get nickname 
    * 
    * @return string 
    */ 
    public function getNickname() 
    { 
     return $this->nickname; 
    } 

    /** 
    * Get the best way to address this person 
    * 
    * @return string 
    */ 
    public function getBestAddress() { 
     if (empty($this->getNickname()) and empty($this->getForename()) && empty($this->getSurname())) { 
      return $this->getUsername(); 
     } 
     elseif (empty($this->getNickname())) { 
      return $this->getForename().' '.$this->getSurname(); 
     } 
     else { 
      return $this->getNickname(); 
     } 
    } 

    /** 
    * Sets the file used for profile picture uploads 
    * 
    * @param UploadedFile $file 
    * @return object 
    */ 
    public function setProfilePictureFile(UploadedFile $file = null) { 
     // set the value of the holder 
     $this->profilePictureFile  = $file; 
     // check if we have an old image path 
     if (isset($this->profilePicturePath)) { 
      // store the old name to delete after the update 
      $this->tempProfilePicturePath = $this->profilePicturePath; 
      $this->profilePicturePath = null; 
     } else { 
      $this->profilePicturePath = 'initial'; 
     } 

     return $this; 
    } 

    /** 
    * Get the file used for profile picture uploads 
    * 
    * @return UploadedFile 
    */ 
    public function getProfilePictureFile() { 

     return $this->profilePictureFile; 
    } 

    /** 
    * Set profilePicturePath 
    * 
    * @param string $profilePicturePath 
    * @return User 
    */ 
    public function setProfilePicturePath($profilePicturePath) 
    { 
     $this->profilePicturePath = $profilePicturePath; 

     return $this; 
    } 

    /** 
    * Get profilePicturePath 
    * 
    * @return string 
    */ 
    public function getProfilePicturePath() 
    { 
     return $this->profilePicturePath; 
    } 

    /** 
    * Get the absolute path of the profilePicturePath 
    */ 
    public function getProfilePictureAbsolutePath() { 
     return null === $this->profilePicturePath 
      ? null 
      : $this->getUploadRootDir().'/'.$this->profilePicturePath; 
    } 

    /** 
    * Get root directory for file uploads 
    * 
    * @return string 
    */ 
    protected function getUploadRootDir($type='profilePicture') { 
     // the absolute directory path where uploaded 
     // documents should be saved 
     return __DIR__.'/../../../../web/'.$this->getUploadDir($type); 
    } 

    /** 
    * Specifies where in the /web directory profile pic uploads are stored 
    * 
    * @return string 
    */ 
    protected function getUploadDir($type='profilePicture') { 
     // the type param is to change these methods at a later date for more file uploads 
     // get rid of the __DIR__ so it doesn't screw up 
     // when displaying uploaded doc/image in the view. 
     return 'uploads/user/profilepics'; 
    } 

    /** 
    * Get the web path for the user 
    * 
    * @return string 
    */ 
    public function getWebProfilePicturePath() { 

     return '/'.$this->getUploadDir().'/'.$this->getProfilePicturePath(); 
    } 

    /** 
    * @ORM\PrePersist() 
    * @ORM\PreUpdate() 
    */ 
    public function preUploadProfilePicture() { 
     if (null !== $this->getProfilePictureFile()) { 
      // a file was uploaded 
      // generate a unique filename 
      $filename = $this->generateRandomProfilePictureFilename(); 
      $this->setProfilePicturePath($filename.'.'.$this->getProfilePictureFile()->guessExtension()); 
     } 
    } 

    /** 
    * Generates a 32 char long random filename 
    * 
    * @return string 
    */ 
    public function generateRandomProfilePictureFilename() { 
     $count     = 0; 
     do { 
      $generator = new SecureRandom(); 
      $random = $generator->nextBytes(16); 
      $randomString = bin2hex($random); 
      $count++; 
     } 
     while(file_exists($this->getUploadRootDir().'/'.$randomString.'.'.$this->getProfilePictureFile()->guessExtension()) && $count < 50); 

     return $randomString; 
    } 

    /** 
    * @ORM\PostPersist() 
    * @ORM\PostUpdate() 
    * 
    * Upload the profile picture 
    * 
    * @return mixed 
    */ 
    public function uploadProfilePicture() { 
     // check there is a profile pic to upload 
     if ($this->getProfilePictureFile() === null) { 
      return; 
     } 
     // if there is an error when moving the file, an exception will 
     // be automatically thrown by move(). This will properly prevent 
     // the entity from being persisted to the database on error 
     $this->getProfilePictureFile()->move($this->getUploadRootDir(), $this->getProfilePicturePath()); 

     // check if we have an old image 
     if (isset($this->tempProfilePicturePath) && file_exists($this->getUploadRootDir().'/'.$this->tempProfilePicturePath)) { 
      // delete the old image 
      unlink($this->getUploadRootDir().'/'.$this->tempProfilePicturePath); 
      // clear the temp image path 
      $this->tempProfilePicturePath = null; 
     } 
     $this->profilePictureFile = null; 
    } 

    /** 
    * @ORM\PostRemove() 
    */ 
    public function removeProfilePictureFile() 
    { 
     if ($file = $this->getProfilePictureAbsolutePath() && file_exists($this->getProfilePictureAbsolutePath())) { 
      unlink($file); 
     } 
    } 



    /** 
    * Set lastEdited 
    * 
    * @param \DateTime $lastEdited 
    * @return User 
    */ 
    public function setLastEdited($lastEdited) 
    { 
     $this->lastEdited = $lastEdited; 

     return $this; 
    } 

    /** 
    * Get lastEdited 
    * 
    * @return \DateTime 
    */ 
    public function getLastEdited() 
    { 
     return $this->lastEdited; 
    } 

    /** 
    * @ORM\PrePersist() 
    * @ORM\PreUpdate() 
    */ 
    public function setLastEditedValueAsNow() { 
     $this->setLastEdited(new \DateTime()); 
    } 

} 

И, конечно же, форма профиля выглядит следующим образом:

<?php 
// DAWeldonExampleBundle/Form/Type/ProfileFormType.php 
namespace DAWeldon\Example\UserBundle\Form\Type; 

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 

class ProfileFormType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     // add your custom field 
     $builder->add('username') 
       ->add('surname') 
       ->add('forename') 
       ->add('nickname') 
       ->add('profilePictureFile'); 
    } 

    public function getParent() 
    { 
     return 'fos_user_profile'; 
    } 

    public function getName() 
    { 
     return 'readypeeps_user_profile'; 
    } 
} 
+0

Спасибо за обмен. У меня есть вопрос здесь. Если вы хотите показать фотографию пользователя в шаблоне редактирования профиля, как вы это делаете? Как вы называете методы объекта пользователя внутри шаблона ветви. Cheers –

+0

Эй, cute.S, я думаю, что это вопрос, более связанный с наследованием пучков. Вам придется «переопределить» пакет, а затем создать новый шаблон в пространстве имен пакета для новой формы и контроллера. Я надеюсь, что следующие документы помогут! http://symfony.com/doc/current/cookbook/bundles/inheritance.html –

+0

(Я должен был ответить очень быстро, ответьте, если у вас есть вопрос!) –

Смежные вопросы