Upload and crop an image for Symfony2
This bundle helps you add a custom file form field. You can single upload and crop an image. The bundle is based on the JCrop JQuery library.
Your contribution is welcome., (*1)
-
Add Media entity, run schema update to generate table, and install assets (Composer should install asset post the installation but just in case), (*9)
``` php
namespace YourNamespace\YourBundle\Entity;, (*10)
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;, (*11)
/**, (*12)
- Description: Media
- @todo adjust to your need if you want to handle uploads by lifecyclecallback
- @ORM\Entity
- @ORM\Table()
-
//@ORM\HasLifecycleCallbacks <-
*/
class Media {, (*13)
/**, (*14)
- @ORM\Id
- @ORM\Column(type="integer")
- @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**, (*15)
- @ORM\Column(type="string", length=255)
*/
protected $name;
public function getName() {
return $this->name;
}, (*16)
public function setName($name) {
$this->name = $name;, (*17)
return $this;
}, (*18)
/**, (*19)
- @ORM\Column(type="string", length=255, nullable=true)
*/
protected $path;
public function setPath($path) {
$this->path = $path;, (*20)
return $this;
}, (*21)
public function getPath() {
return $this->path;
}, (*22)
/**, (*23)
- @ORM\Column(name="created",type="date")
*/
protected $created;
/**, (*24)
- @var File
-
- @Assert\File(
- maxSize = "1M",
- mimeTypes = {"image/jpeg"},
- maxSizeMessage = "The maxmimum allowed file size is 5MB.",
- mimeTypesMessage = "Only the filetypes image are allowed."
- )
*/
protected $file;
public function __construct() {
$this->created = new \Datetime();
}, (*25)
public function getUploadRootDir() {
// absolute path to your directory where images must be saved
return DIR . '/../../../../web/' . $this->getUploadDir();
}, (*26)
public function getUploadDir() {
return 'uploads/';
}, (*27)
public function getAbsolutePath() {
return null === $this->path ? null : $this->getUploadRootDir() . '/' . $this->id . '.' . $this->path;
}, (*28)
public function getWebPath() {
return null === $this->name ? null : '/' . $this->getUploadDir() . '/' . $this->name;
}, (*29)
/**, (*30)
- @ORM\PrePersist()
- @ORM\PreUpdate()
*/
public function preUpload() {
if (null !== $this->file) {
// faites ce que vous voulez pour générer un nom unique
$filename = sha1(uniqid(mt_rand(), true));
$this->name = $filename;
$this->path = $filename . '.' . $this->file->guessExtension();
}
}
/**, (*31)
- @ORM\PostPersist()
-
@ORM\PostUpdate()
*/
public function upload() {
if (null === $this->file) {
return;
}, (*32)
// s'il y a une erreur lors du déplacement du fichier, une exception
// va automatiquement être lancée par la méthode move(). Cela va empêcher
// proprement l'entité d'être persistée dans la base de données si
// erreur il y a
$this->file->move($this->getUploadRootDir(), $this->path);, (*33)
unset($this->file);
}, (*34)
/**, (*35)
- @ORM\PreRemove()
*/
public function storeFilenameForRemove() {
$this->filenameForRemove = $this->getAbsolutePath();
}
/**, (*36)
- @ORM\PostRemove()
*/
public function removeUpload() {
if ($this->filenameForRemove) {
unlink($this->filenameForRemove);
}
}
/**, (*37)
- Get id.
-
- @return int
*/
public function getId() {
return $this->id;
}
/**, (*38)
/**, (*41)
- Get created.
-
- @return \DateTime
*/
public function getCreated() {
return $this->created;
}
/* Set file
*, (*42)
- @param $file
- @return Media
*/
public function setFile($file) {
$this->file = $file;, (*43)
return $this;
}, (*44)
/**, (*45)
- Get file.
-
- @return $file
*/
public function getFile() {
return $this->file;
}
}, (*46)
``` bash
php app/console doctrine:schema:update --force
bash
php app/console asset:install
, (*47)
-
Include the route to your routing.yml and the config to your config.yml:, (*48)
``` yml
upload_crop_image:
resource: "@UploadCropImageBundle/Resources/config/routing.yml"
prefix: /, (*49)
If you did not install the JSroutingBundle include them.
``` yml
# app/config/routing.yml
fos_js_routing:
resource: "@UploadCropImageBundle/Resources/config/routing/routing.xml"
yml
upload_crop_image:
media_entity: YourNamespace\YourBundle\Entity\Media
, (*50)
-
include the style and the javascript in your templates. The demo include is for demo purposes., (*51)
twig
<head>
…
<script src="{{asset("bundles/uploadcropimage/js/jquery.min.js") }}"></script>
<script src="{{ asset('bundles/fosjsrouting/js/router.js') }}"></script>
<script src="{{ path('fos_js_routing_js', {'callback': 'fos.Router.setData'}) }}"></script>
{% include 'UploadCropImageBundle:Commun:demo.includes.html.twig' %}
{% include 'UploadCropImageBundle:Commun:crop.includes.html.twig' %}
</head>
, (*52)
-
Include the javascript before the closing body tag, (*53)
twig
<body>
…
{% include "UploadCropImageBundle:Commun:script.html.twig" %}
</body>
, (*54)
-
Add the following to your Media/Image/Photo form type buildForm method, (*55)
``` php
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
…
->add('file', 'file')
->add('dimensions', 'crop_image', array('mapped' => false, 'label' => false))
…
;
}
```
-
Now in your view, where you are rendering the form, include the following, (*56)
html
…
<div id="jcrop-holder">
<img src="holder.js/300x300?bg=#b8ebb8&fg=#ffffff" id="cropbox">
</div>
…
, (*57)
-
Now add the form tag the coordinate checker and render your file field like so. You can pass the route for upload thru
the html data attributes. supported data attributes are data-route, the route you will handle the upload and
the data-id attributes used to handle any extra route id parameter., (*58)
twig
…
<form name="upload" action="{{ path('your_path') }}" {{ form_enctype(form) }} method="POST" onsubmit="return checkCoords();">
…
{{ form_widget(form.file, {'id':'file','data-route':'media_json_upload'})}}
, (*59)
If you are rendering the form fields individually, you will need to include the following to your form, (*60)
And that's it, let me know if you are facing some problem and let me know ways i can improve the bundle. Enjoy! ;), (*61)