0

ユーザーがプロフィール写真をアップロードして保存できるユーザー プロフィールがあります。

UserProfile エンティティと Document エンティティがあります。

エンティティ/UserProfile.php

namespace Acme\AppBundle\Entity\Profile;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="ISUserProfile")
 */
class UserProfile extends GenericProfile
{

    /**
     * @ORM\OneToOne(cascade={"persist", "remove"}, targetEntity="Acme\AppBundle\Entity\Document")
     * @ORM\JoinColumn(name="picture_id", referencedColumnName="id", onDelete="set null")
     */
    protected $picture;

    /**
     * Set picture
     *
     * @param Acme\AppBundle\Entity\Document $picture
     */
    public function setPicture($picture)
    {
        $this->picture = $picture;
    }

    /**
     * Get picture
     *
     * @return Acme\AppBundle\Entity\Document
     */
    public function getPicture()
    {
        return $this->picture;
    }
}

エンティティ/Document.php

namespace Acme\AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks
 */
class Document
{

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

    /**
     * @Assert\File(maxSize="6000000")
     */
    private $file;


    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()
    {
        // the absolute directory path where uploaded documents should be saved
        return __DIR__.'/../../../../web/'.$this->getUploadDir();
    }

    protected function getUploadDir()
    {
        // get rid of the __DIR__ so it doesn't screw when displaying uploaded doc/image in the view.
        return 'uploads/documents';
    }

    /**
     * @ORM\PrePersist()
     * @ORM\PreUpdate()
     */
    public function preUpload()
    {
        if (null !== $this->file) {
            $this->path = sha1(uniqid(mt_rand(), true)).'.'.$this->file->guessExtension();
        }
    }

    /**
     * @ORM\PostPersist()
     * @ORM\PostUpdate()
     */
    public function upload()
    {
        if (null === $this->file) {
            return;
        }

        $this->file->move($this->getUploadRootDir(), $this->path);

        unset($this->file);
    }

    /**
     * @ORM\PostRemove()
     */
    public function removeUpload()
    {
        if ($file = $this->getAbsolutePath()) {
            unlink($file);
        }
    }

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

    /**
     * Set path
     *
     * @param string $path
     */
    public function setPath($path)
    {
        $this->path = $path;
    }

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

    /**
     * Set file
     *
     * @param string $file
     */
    public function setFile($file)
    {
        $this->file = $file;
    }

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

}

私のユーザー プロファイル フォーム タイプは、ドキュメント フォーム タイプを追加して、ユーザー プロファイル ページにファイル アップローダを含めます。

フォーム/UserProfileType.php

namespace Acme\AppBundle\Form;

use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class UserProfileType extends GeneralContactType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
    parent::buildForm($builder, $options);
    /*
    if(!($pic=$builder->getData()->getPicture()) || $pic->getWebPath()==''){
      $builder->add('picture', new DocumentType());
    }
    */

    $builder
      ->add('picture', new DocumentType());
      //and add some other stuff like name, phone number, etc
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
      'data_class' => 'Acme\AppBundle\Entity\Profile\UserProfile',
      'intention'  => 'user_picture',
      'cascade_validation' => true,
        ));
    }


    public function getName()
    {
        return 'user_profile_form';
    }
}

フォーム/DocumentType.php

namespace Acme\AppBundle\Form;

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

class DocumentType extends AbstractType
{
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
                $builder
                        ->add('file')
                        ;
        }

        public function setDefaultOptions(OptionsResolverInterface $resolver)
        {
            $resolver->setDefaults(array(
                    'data_class' => 'Acme\AppBundle\Entity\Document',
            ));
        }

        public function getName()
        {
                return 'document_form';
        }
}

私のコントローラーには、プロファイルの更新アクションがあります。

コントローラー/ProfileController.php

namespace Acme\AppBundle\Controller;


class AccountManagementController extends BaseController
{

    /**
     * @param Symfony\Component\HttpFoundation\Request
     * @return Symfony\Component\HttpFoundation\Response
     */
    public function userProfileAction(Request $request) {
        $user = $this->getCurrentUser();
        $entityManager = $this->getDoctrine()->getEntityManager();

        if($user && !($userProfile = $user->getUserProfile())){
            $userProfile = new UserProfile();
            $userProfile->setUser($user);
        }

        $uploadedFile = $request->files->get('user_profile_form');
        if ($uploadedFile['picture']['file'] != NULL) {
                $userProfile->setPicture(NULL);
        }

        $userProfileForm = $this->createForm(new UserProfileType(), $userProfile);

        if ($request->getMethod() == 'POST') {
          $userProfileForm->bindRequest($request);

          if ($userProfileForm->isValid()) {
            $entityManager->persist($userProfile);
            $entityManager->flush();

            $this->get('session')->setFlash('notice', 'Your user profile was successfully updated.');
            return $this->redirect($this->get('router')->generate($request->get('_route')));
          } else {
            $this->get('session')->setFlash('error', 'There was an error while updating your user profile.');
          }
        }

        $bindings = array(
          'user_profile_form' => $userProfileForm->createView(),
        );

        return $this->render('user-profile-template.html.twig', $bindings);
    }
}

さて、このコードは機能します...しかし、それは地獄のように醜いです. アップロードされたファイルのリクエスト オブジェクトをチェックし、ピクチャを null に設定して、新しい Document エンティティを保持する必要があることを Symfony が認識しなければならないのはなぜですか?

プロフィール画像として画像をアップロードするオプションを備えたシンプルなユーザー プロフィール ページを用意することは、これよりも簡単であるはずです。

私は何が欠けていますか??

4

1 に答える 1

0

(数か月経った今、フィードバックを期待しているとは思いませんが、同じ問題を抱えている他の人に役立つかもしれません)

私は同様の設定と目標を持っています。この投稿を見つけ、コードの一部をコピーした後、「醜い」と呼ばれる「$uploadedFile」スニペットは必要ないことがわかりました。fos 登録フォームを上書きします。追加する必要があるのは、DocumentType.php と RegistrationFormType.php (ユーザーの UserProfileType など) だけです。

あなたのバージョンに醜いコードが必要な理由がわかりません。(または、更新フォームをコーディングしているときに同じ問題に遭遇するのでしょうか?)。

于 2013-08-09T11:20:18.610 に答える