phpsymfonydoctrinedropzoneoneupuploaderbundle

OneToMany in Doctrine ORM Mapping with Dropzone images


I have a form in Symfony where there is a dropzone using dropzone.js to upload images, when the images are uploaded, the image path along with the id of the current instance of the entity that the form pertains to are uploaded to an Image table as imageName and listing_id respectively. The listing_id is the id of the current listing which the user is filling out. Since I'd have multiple images per listing, I'm wondering if it's possible to maintain a OneToMany relationship between the listing object and the images.

When the user clicks "Add Listing", the listing object is created with null values as a draft (aside from the id) and afterwards, the images are dropped in so they're added to the db afterwards.

Listing.php

/**
 * @ORM\OneToMany(targetEntity="Image", mappedBy="listing", cascade={"persist"}, orphanRemoval=true)
 */
private $images;

Image.php

/**
 * @ORM\ManyToOne(targetEntity="Listing", inversedBy="images")
 * @ORM\JoinColumn(name="listing_id", referencedColumnName="id", onDelete="CASCADE")
 */
private $listing;

This results in an error when dropping the image in but if I change $listing to

 /**
 * @ORM\Column(type="integer", nullable=true, name="listing_id")
 */
protected $listing;

It works but my intention is to retrieve the images later on using the listing object so it's not the desired outcome. My question is, can I still keep this sort of coupling between these two values even if the image object is created at a different time (later on) than the listing. As it is, I get an error when I put something in the drop zone using these annotations.

Since the image rows are being inserted into table in real time as opposed to on form submit, it might cause an error when using this sort of coupling but I'm not sure.


Solution

  • You are on the right path. I am using oneup/uploader-bundle for this task.

    The correct @ManyToOne is needed. @Column wont work.

    But in my usecase it was an inlined image with additional data.

    I had to deactivate the dropzone autoloading and manually handcraft the dropzone call and settings to include the additional form fields.

    There is also an option to start uploading manually not right after dropping the file. This way it may be possible create the whole thing with one post request an no prior persisting of listing to have an ID...

    I hope it helps. I can share my code but not at the machine right now.

    EDIT: This is my code:

    var myDropzone = new Dropzone("#documentTypeUploadDropzone", {
    
                url : actionUrl,
                dictDefaultMessage: 'Bitte das neue Dokument hier ablegen!',
    
                // The configuration we've talked about above
                autoProcessQueue: false,
    
                maxFiles: 1,
                init: function () {
                    this.on('success', function(e, serverResponse) {
    
                        myDropzone.removeAllFiles();
    
                    });
    
                    this.on('sending', function(file, xhr, formData) {
                        // Add additional data form original <form> which was already checked by html5 client side verification
                        formData.append('productId', 1);
                        formData.append('documentType[name]', value1;
                        formData.append('documentType[foreignUrl]',   $(#formInput).val());
    
                    });
    
                    var myDropzone = this;
    
                    $('#documentTypeUploadForm').on('submit', function(e) {
                        // Make sure that the form isn't actually being sent.
                        e.preventDefault();
                        e.stopPropagation();
    
    
                        var files = myDropzone.getQueuedFiles();
                        if (!files.length) {
                            $.growl.error({ title:"Fehler", message: 'Bitte zuerst ein Dokument zum Hochladen auswählen.'});
                            return
                        }
    
    
                        myDropzone.processQueue();
                    });
    
    
                }
            });