symfony2.1での画像の扱い方
symfony2.0を使ったことがあって、画像の扱い方(アップロードとリサイズ)がよく理解できていませんでした。
symfony2.1のインストールを機に、それをもう一度調べて、やってみました。
画像のアップロード
仮にユーザ登録の機能(userテーブルを使う)で、一個の画像ファイルをプロファイル画像としてアップロードする必要とします。
●Entity(class=User)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | /** * User * * @ORM\Table(name="user") * @ORM\HasLifecycleCallbacks */ class User { ... /** * @var string * * @ORM\Column(name="image", type="string", length=256) */ private $image; /** * @Assert\Image( * maxSize = "5240000", * maxSizeMessage = "5MB以下の画像をアップロードしてください", * mimeTypes = {"image/jpeg", "image/pjpeg", "image/png", "image/x-png"}, * mimeTypesMessage = "画像はjpgまたはpngのみアップロード可能", * minWidth = "200", * minWidthMessage = "幅が200px以上の画像をアップロードしてください" * ) */ public $imagefile; ... public function getAbsolutePathImage() { return null === $this->image ? null : $this->getUploadRootDir().'/'.$this->image; } public function getWebPathImage() { return null === $this->image ? null : $this->getUploadDir().'/'.$this->image; } 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 up // when displaying uploaded doc/image in the view. return 'uploads/images'; } /** * @ORM\PrePersist() * @ORM\PreUpdate() */ public function preUpload() { if (null !== $this->imagefile) { $this->image = sha1(uniqid(mt_rand(), true)).'.'.$this->imagefile->guessExtension(); } } /** * @ORM\PostPersist() * @ORM\PostUpdate() */ public function upload() { if (null !== $this->imagefile) { $this->imagefile->move($this->getUploadRootDir(), $this->image); $this->imagefile = null; } } /** * @ORM\PostRemove() */ public function removeUpload() { if ($imagefile = $this->getAbsolutePathImage()) { if (file_exists($imagefile)) { unlink($imagefile); } } } } |
userテーブルには「image」というフィールドがあって、画像ファイルのファイル名を保存します。
「imagefile」は別にテーブルのファールドではなく、外部にも直接アクセスしたから、「public」にします。
HasLifecycleCallbacksの使いより、新規作成と編集前には「preUpload」が動いて、新規作成と編集後は「upload」が動きます。削除されたときも、「removeUpload」が動きますので、なかなかきれいな解決方法だと思います。
●Form(class=”UserType”)
1 2 3 4 5 6 7 8 9 | public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('imagefile', 'file', array( 'label' => 'プロファイル画像', 'required' => true, )) ... ; } |
DBに保存する「image」は出てこなくて、「imagefile」が出てきます。
●Twig(Template, filename=new.html.twig)
1 | {{form_label(form.imagefile)}}:{{ form_errors(form.imagefile) }}{{ form_widget(form.imagefile) }} |
●Controller(PHP, filename=UserController.php)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public function newAction() { $entity = new User(); $request = $this->get('request'); $form = $this->createForm(new UserType(), $entity); if ($request->getMethod() == 'POST') { $form->bind($request); if ($form->isValid()) { $em = $this->getDoctrine()->getManager(); $em->persist($entity); $em->flush(); // ユーザ一覧画面にredirect return $this->redirect($this->generateUrl('user_list')); } } return array( 'entity' => $entity, 'form' => $form->createView(), ); } |
アップした画像のリサイズ
このバンドル(プラグイン)を使ってみました。
便利ですが、注意点が一個あります。
●Twig(Template)
1 | <img src="{{ image('profile.jpg').resize(200,150) }}" /> |
上記コードは、使い方を示していますが、「profile.jpg」は想定パス(urlの)ではなく、絶対パスであることを注意しなければなりません。
おまけ
複数画像をアップするなら、このバンドルが便利です。
自動的に画像をサイズで振り分けで作成してくれるですが、一箇所に複数の画像をアップロードすることができ、Entityとの連動が難しいです。
Author Profile
スターフィールド編集部
SHARE