1

I have an entity Project that is related with some files via one-to-many relationship like this:

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

    /**
     * @ORM\OneToMany(targetEntity="files", mappedBy="project", cascade= {"persist","merge","remove"},orphanRemoval=true)
     */
    protected $project_files;
}

And File entity:

class files{

    private $files;

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

    /**
     * @ORM\ManyToOne(targetEntity="projects", inversedBy="project_files")
     */
     protected $project;
}

So when I edit a project, I want to be able to add some new files to it or delete some olds. I found a workaround to implement this but I can't figure out the way Symfony and Doctrine really handle this kind of operations. More precisely, my code (that works fine) that handles the deletion of some old files on edit is:

private function persistProject(Form $form) {
    $project = $form->getData();
    $raw_files = $project->getProjectFiles()->toArray();
    $ready_files = self::setUpFiles($raw_files, $project);
    $project->setProjectFiles($ready_files);
    $em->merge($project);
    $em->flush();
}

private function setUpFiles($project_files, $project) {
    $ready_files = new ArrayCollection();
    foreach ($project_files as $project_file){
        if ((!empty($project_file->getId())) && ($project_file->getDescription() != '--del')){
            $ready_files->add($project_file);
        }
        else if ((!empty($project_file->getId())) && ($project_file->getDescription() == '--del')){
            unlink($this->uploadDir . $project_file->getPath());
            // --- controversial line of code --- //
            $project->removeProjectFile($project_file); 
        }
    }
    return $ready_files;
}

So in brief the situation is about this: if I remove line "$project->removeProjectFile($project_file);", the files are not deleted, even if my ArrayCollection $ready_files, that is ultimately stored to the object in line "$project->setProjectFiles($ready_files);", is exactly as it should be and does not contain the deleted files.

So my question is dual:

  1. Shouldn't symfony persist the exact ArrayCollection (and only this) that I set and delete all the others files stored? Why does not the code work properly without the line "$project->removeProjectFile($project_file);"?

  2. How does the line "$project->removeProjectFile($project_file);" affects the $project object in function persistProject() since the object is passed as a simple argument and not by reference? Isn't it obvious to expect that everything that happens to $project object in function setUpFiles() will do nothing to the original $project in function persistProject() as it is in different scope?

Can anyone help me to clear this up?

iiirxs
  • 4,493
  • 2
  • 20
  • 35

0 Answers0