0

I have one entity "Task" and another "Attachments". I want to store all attachments in their own table associated with their task and user. So I created this entity Class:

<?php

namespace Seotool\MainBundle\Entity;

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

/**
 * @ORM\Entity
 * @ORM\Table(name="attachments")
 */
class Attachments {

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

/**
 * @ORM\Column(type="string", length=255)
 * @Assert\NotBlank
 */
public $name;

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

/**
 * @ORM\ManyToOne(targetEntity="User", inversedBy="attachments")
 * @ORM\JoinColumn(name="user", referencedColumnName="id")
 */
protected $User;

/**
 * @ORM\ManyToOne(targetEntity="User", inversedBy="attachments")
 * @ORM\JoinColumn(name="editor", referencedColumnName="id")
 */
protected $Editor;

/**
 * @ORM\ManyToOne(targetEntity="Task", inversedBy="attachments")
 * @ORM\JoinColumn(name="task", referencedColumnName="id")
 */
protected $Task;

/**
 * @Assert\File(maxSize="6000000")
 */
private $file;

/**
 * Sets file.
 *
 * @param UploadedFile $file
 */
public function setFile(UploadedFile $file = null)
{
    $this->file = $file;
}

/**
 * Get file.
 *
 * @return UploadedFile
 */
public function getFile()
{
    return $this->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()
{
    // 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/documents';
}

....

In my Form Type for my Task Form I want to add now the file upload. But how can I do this? I can't add $builder->add('Attachment', 'file'); because it's not the same entity. So how can I do it, so that I have in my FormType of Entity Task the upload field which stores the uploaded data in the table of Entity Class Attachment??

EDIT

this is my Controller:

/**
@Route(
 *     path = "/taskmanager/user/{user_id}",
 *     name = "taskmanager"
 * )
 * @Template()
 */
public function taskManagerAction($user_id, Request $request)
{

     /* #### NEW TASK #### */

    $task = new Task();
    $attachment = new Attachments();

    $task->getAttachments()->add($attachment);
    $addTaskForm = $this->createForm(new TaskType(), $task);

    $addTaskForm->handleRequest($request);

    if($addTaskForm->isValid()):

        /* User Object of current Users task list */
        $userid = $this->getDoctrine()
            ->getRepository('SeotoolMainBundle:User')
            ->find($user_id);

        $task->setDone(FALSE);
        $task->setUser($userid);
        $task->setDateCreated(new \DateTime());
        $task->setDateDone(NULL);
        $task->setTaskDeleted(FALSE);

        $attachment->setTask($task);
        $attachment->setUser($userid);

        $em = $this->getDoctrine()->getManager();
        $em->persist($task);
        $em->persist($attachment);
        $em->flush();

        $this->log($user_id, $task->getId(), 'addTask');

        return $this->redirect($this->generateUrl('taskmanager', array('user_id' => $user_id)));

    endif;
}

3 Answers 3

1

You should rename your entity from Attachments to Attachment as it would be storing data of only one attachment.

In your case you need Symfony2 form collection type to allow adding attachment in task form (TaskType):

$builder->add('attachments', 'collection', array(
    'type' => new AttachmentType(),
    // 'allow_add' => true,
    // 'allow_delete' => true,
    // 'delete_empty' => true,
));

You will also need to create AttachmentType form type for single attachment entity.

Doc of collection field type: http://symfony.com/doc/current/reference/forms/types/collection.html More information about embedding form collection you can find on: http://symfony.com/doc/current/cookbook/form/form_collections.html

Then also read sections:

Sign up to request clarification or add additional context in comments.

2 Comments

Please let me know if you run into any problems.
I made a new answer, would be happy, when you could take a look :)
1

Ok, that's because you have to initialize new instance of TaskType in your controller - there are no attachments at the beginning that are assigned to this task.

public function newAction(Request $request)
{
    $task = new Task();

    $attachment1 = new Attachment();
    $task->getAttachments()->add($attachment1);
    $attachment2 = new Attachment();
    $task->getAttachments()->add($attachment2);
    // create form
    $form = $this->createForm(new TaskType(), $task);

    $form->handleRequest($request);
    ...
}

Now there should be 2 file input for new attachments.

10 Comments

I get this exception: FatalErrorException: Error: Call to a member function add() on a non-object in /Applications/MAMP/htdocs/Seotool/src/Seotool/MainBundle/Controller/DashboardController.php line 52. Line 52 is: $task->getAttachments()->add($attachment);
Did you set: $this->attachments = new ArrayCollection(); in constructor of your Task entity class?
I did it now. The exception is gone but nothing is outputted...No file upload. :-/
It's explained here:symfony.com/doc/current/cookbook/form/form_collections.html - try to check your code or give me more code :)
By exception you mean: "Symfony only should add an attachment entry when there is selected a file to upload?" I yes you should not to that manually: $attachment->setTask($task); $attachment->setUser($userid); because this will always save you one attachment.
|
0

I added a new Form Type: AttachmentsType.php

<?php
namespace Seotool\MainBundle\Form\Type;

use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class AttachmentsType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('name', 'text');
    $builder->add('file', 'file');
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver
            ->setDefaults(array(
                'data_class' => 'Seotool\MainBundle\Entity\Attachments'
            ));
}

public function getName()
{
    return 'attachments';
}
}

And used this for embbing it into my form builder of the TaskType.php

$builder->add('attachments', 'collection', array(
    'type' => new AttachmentsType(),
));

But my output only gives me following HTML:

 <div class="form-group"><label class="control-label required">Attachments</label><div id="task_attachments"></div></div><input id="task__token" name="task[_token]" class="form-control" value="brHk4Kk4xyuAhST3TrTHaqwlnA03pbJ5RE4NA0cmY-8" type="hidden"></form>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.