symfonydoctrineentitiespersist

Symfony2 persist not working from my controller


I am new with symfony and I've been trying for several days to implement a multiple image upload. I use entity Image and entity CollecImages with a oneToMany relation. I managed to do so thanks to this article. So now I can upload an image collection and i can see it in my database.

Now I am trying to use ImageCollec with my User entity by calling ImageCollec's action inside a view of my User. I would like to set the user's property imageCollec so that I can use it after the collection is uploaded but for some reason the CollecImages field is not updated in my databse and stays to NULL. The following lines should do the trick but it doesn't.

        $user->setCollecImages($collecImages);
        $em->persist($user); 

Is there a problem with my entities? Am I doing this the wrong way? I've tryed several things but I am stuck here.

My Image entity

<?php
namespace BeArts\ImageBundle\Entity;

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

/**
* @ORM\Entity
 * @ORM\Entity(repositoryClass="BeArts\ImageBundle\Entity\ImageRepository")
* @ORM\Table(name="image")
*/
class Image
{
 /**
 * @var integer $id
 * @ORM\Id
 * @ORM\Column(type="integer")
 * @ORM\GeneratedValue(strategy="AUTO")
 */
protected $id;

/**
* @ORM\ManyToOne(targetEntity="BeArts\ImageBundle\Entity\CollecImages", inversedBy="images" )
* @ORM\JoinColumn(nullable=false)
*/
private $collecImages;

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

/**
 * @var File $file    
 * @Assert\File(
 *     maxSize = "2M",
 *     mimeTypes = {"image/jpeg", "image/gif", "image/png"},
 *     mimeTypesMessage = "Uniquement des images (png, jpg, gif)",
 *     notFoundMessage = "Le fichier n'a pas été trouvé sur le disque",
 *     uploadErrorMessage = "Erreur dans l'upload du fichier"
 * )
 */
private $file;


  /**
 * Set collecImages
 *
 * @param \BeArts\ImagesBundle\Entity\CollecImages $collecImages
 * @return Image
 */
public function setCollecImages(CollecImages $collecImages)
{
    $this->collecImages = $collecImages;

    return $this;
}

/**
 * Get collecImages
 * @param \BeArts\ImagesBundle\Entity\CollecImages $collecImages
 * @return \BeArts\ImagesBundle\Entity\CollecImages 
 */
public function getCollecImages()
{
    return $this->collecImages;
}

public function getFile()
{
    return $this->file;
}

public function setFile($file)
{
    $this->file = $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()
{
    // le chemin absolu du répertoire où les documents uploadés doivent être sauvegardés
    return __DIR__.'/../../../../web/'.$this->getUploadDir();
}

protected function getUploadDir()
{
    // le chemin relatif du répertoire
    return 'uploads/images';
}


public function getId()
{
    return $this->id;
}

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

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

    return $this;
}

 /**
 * @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) {
        $this->path = sha1(uniqid(mt_rand(), true)).'.'.$this->file->guessExtension();
    }
    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);
    }
}

}

My CollecImages entity

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

/**
* @ORM\OneToMany(targetEntity="Image", mappedBy="collecImages", cascade={"persist", "remove"})
*/
protected $images;

public function __construct()
{
    $this->images = new ArrayCollection();
}

public function getDescription()
{
    return $this->description;
}

public function setDescription($description)
{
    $this->description = $description;
}

public function getImages()
{
    return $this->images;
}

public function setImages(ArrayCollection $images)
{

    foreach ($images as $image) {
    $image->setCollecImages($this); 
}

    $this->images = $images;
}
}

CollecImages controller

<?php
// src/BeArts/ImageBundle/Controller/CollecImagesController.php
namespace BeArts\ImageBundle\Controller;

use BeArts\ImageBundle\Entity\CollecImages;
use BeArts\ImageBundle\Entity\Image;
use BeArts\ImageBundle\Form\Type\CollecImagesType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;


use Symfony\Component\HttpFoundation\Response;

class CollecImagesController extends Controller
{
public function newAction(Request $request)
{
    $collecImages = new CollecImages();

    $form = $this->createForm(new CollecImagesType(), $collecImages);

    // analyse le formulaire quand on reçoit une requête POST
    if ($request->isMethod('POST')) {
        $form->handleRequest($request);
        if ($form->isValid()) {
            // ici vous pouvez par exemple sauvegarder la CollecImages et ses objets Image

            $collecImages->getImages();
            $em = $this->getDoctrine()->getManager();
            foreach ( $collecImages->getImages() as $image ) {
                $image->setCollecImages($collecImages);  
                $image->upload();
                $em->persist($image); 
            }

            $em->persist($collecImages); 
            $em->flush();
            $request->getSession()->getFlashBag()->add('notice', 'Collection bien enregistrée.');
        // return $this->redirect($this->generateUrl('bearts_image_collec_images_new'));
            return $this->redirect($this->generateUrl('fos_user_profile_show'));



        }
    }

    return $this->render('BeArtsImageBundle:CollecImages:new.html.twig', array(
        'form' => $form->createView(),
        ));
}

public function newUserCollecAction(Request $request)
{

    $user = $this->getUser();
    $collecImages = new CollecImages();

    $form = $this->createForm(new CollecImagesType(), $collecImages);

    // analyse le formulaire quand on reçoit une requête POST
    if ($request->isMethod('POST')) {
        $form->handleRequest($request);
        if ($form->isValid()) {
            // ici one sauvegarde la CollecImages et ses objets Image

            $collecImages->getImages();
            $em = $this->getDoctrine()->getManager();
            foreach ( $collecImages->getImages() as $image ) {
                $image->setCollecImages($collecImages);  
                $image->upload();
                $em->persist($image); 
            }
            $em->persist($collecImages); 

            $user->setCollecImages($collecImages);
            $em->persist($user); 

            $em->flush();


            $request->getSession()->getFlashBag()->add('notice', 'Collection bien enregistrée.');
        // return $this->redirect($this->generateUrl('bearts_image_collec_images_new'));
            return $this->redirect($this->generateUrl('fos_user_profile_show'));



        }
    }

    return $this->render('BeArtsImageBundle:CollecImages:new.html.twig', array(
        'form' => $form->createView(), 'user' => $user
        ));
}

//edit

//show
public function showAction($collecImages)
{
    $collecImages = $this;
    return $this->render('BeArtsImageBundle:CollecImages:show.html.twig', array(
        'collecImages' => $collecImages
        ));

}

}

My User entity

<?php
namespace BeArts\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;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * User
 *
 * @ORM\Table(name="bearts_user")
 * @ORM\HasLifecycleCallbacks()
 * @ORM\Entity(repositoryClass="BeArts\UserBundle\Entity\UserRepository")
 */
class User extends BaseUser
{
  /**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
  protected $id;


/**
 * @ORM\Column(name="type", type="text")
 * @Assert\Choice(choices = {"artiste", "lieu"}, message = "Quel type d'utilisateur êtes vous?")
 */
public $type;

/**
 * @ORM\Column(name="domaine", type="text")
 * @Assert\Choice(choices = {"Musique", "Danse", "Theatre", "Photo", "Cinema", "ArtsPlastique"}, message = "Choisissez votre principale domaine artistique.")
 */
public $domaine;

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

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

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

/**
 * @var string
 *
 * @ORM\Column(name="description", type="text", nullable=true)
 */
public $description;

/**
 *
 * @ORM\Column(name="adress", type="text",nullable=true)
 */
public $adress;

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

// for temporary storage
private $tempProfilePicturePath;

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



/**
 * @ORM\OneToOne(targetEntity="\BeArts\ImageBundle\Entity\CollecImages",   cascade={"persist"})
 */
protected $collecImages;




 public function __construct()
 {
  parent::__construct();
 } 

 /**
 * 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);
    }
}



// public function setImages(ArrayCollection $images)
// {
//     foreach ($images as $image) {
//         $image->setAdvert($this);
//     }
//     $this->images = $images;
// }

// /**
//  * Add image
//  *
//  * @param \BeArts\CoreBundle\Entity\Image $image
//  * @return User
//  */
// public function addImage(Image $image)
// {
//     $this->images[] = $image;
//     return $this;
// }

// *
//  * Remove image
//  *
//  * @param \BeArts\CoreBundle\Entity\Image $image

// public function removeImage(Image $image)
// {
//     $this->images->removeElement($image);
// }



// public function getImages()
// {
//     return $this->images;
// }






public function setCollecImages(\BeArts\ImageBundle\Entity\CollecImages     $collecImages = null)
{
    $this->collecImages = $collecImages;
}

public function getCollecImages()
{
    return $this->collecImages;
}

}

The user view in which I call the collecImages controller

{% trans_default_domain 'FOSUserBundle' %}
<main class="wrapper">
<div class="fos_user_user_show">
<section class="profil1">
        <div class="wrapper row">
            <div class="columns col-6">
                <img src="../../uploads/user/profilePics/{{user.profilePicturePath}}" alt="">
            </div>
            <div class="columns col-6">
                <ul class="border">
                    <h2 class="article-subtitle">Informations personnelles</h2>
                    <li>{{ 'profile.show.username'|trans }}: {{ user.username }}</li>
                    <li>{{ 'profile.show.email'|trans }}: {{ user.email }}</li>
                    <li>{{user.nom}}</li>
                    <li>{{user.prenom}}</li>
                    <li>Site web</li>
                    <li>Page facebook</li>
                    <li>Page autre reseau social</li>
                </ul>
                <div class="buttonBox"><a class="button" href="{{ path('fos_user_profile_edit') }}">Editer le profil</a></div>

            </div>
            <div class="columns col-6">
                <article  class="border-top-left">
                <h2 class="article-title">{{user.nomDeScene}}</h2>
                <p class="article-subtitle">Activité</p>
                <p>{{user.description}}
                </article>
            </div>

        </div>
        </section>
        <section class="profil2">
            <div class="wrapper row">
            <div class="columns col-6">
                    {{ render(controller("BeArtsImageBundle:CollecImages:newUserCollec")) }}
                {% if user.collecImages is null %}
{% else %}
{{ 
                render(
                    controller( "BeArtsImageBundle:CollecImages:show",
                    {'collecImages':user.collecImages}  
                    )
                ) 
            }}
{% endif %}



            </div>              
            <div class="columns col-6">             
            </div>                  
        </div>
        </section>
</div>
</main>   

the new view for collecImages

{# src/Acme/TaskBundle/Resources/views/CollecImages/new.html.twig #}
<form action="{{ path('bearts_image_collec_images_new') }}" method="POST" {{     form_enctype(form) }}>
<h3>Creation galerie de {{user.id}}</h3>
<ul class="images" data-prototype="{{ form_widget(form.images.vars.prototype)|e }}">
    {# itère sur chaque images existant  #}
    {% for image in form.images %}
        <li>{{ form_row(image.file) }}</li>

    {% endfor %}
</ul>
{{ form_rest(form) }}
{# ... #}
</form>

Any help is welcome :) Again I am new with symfony2 and it is likely that i made mistakes that i'll be glad to fix.

If any other part of my code is needed just ask.


Solution

  • Ok i managed to fix this somehow by regenerating my User entity with

    php app/console doctrine:generate:entities BeArtsUserBundle