Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How would you add a file upload to a Symfony2 DataFixture?

I can't seem to wrap my head around how I would go about adding a file upload to a DataFixture. I'm trying to upload an image for the dummy content my fixtures load. This seems like something that would be useful to know.

like image 909
ornj Avatar asked Sep 06 '12 22:09

ornj


People also ask

How do I upload a file to Symfony?

Symfony Form component provides FileType class to handle file input element. It enables easy uploading of images, documents, etc. Let us learn how to create a simple application using FileType feature. Step 1 − Create a new application, fileuploadsample using the following command.

What are fixtures Symfony?

Fixtures are used to load a "fake" set of data into a database that can then be used for testing or to help give you some interesting data while you're developing your application. This bundle is compatible with any database supported by Doctrine ORM (MySQL, PostgreSQL, SQLite, etc.).


1 Answers

Although this question has been asked 1 year ago it appears that there is not a lot of information out there on how to upload a file via doctrine data fixture. I could only find this post.

I've been looking and I've taken a slightly different approach than ornj's. (Might have to do with Symfony's updates.)

I first had to

use Symfony\Component\HttpFoundation\File\UploadedFile;

and then used copy() to copy the image because as ornj said it will move it.

copy($art1->getFixturesPath() . '01.jpg', $art1->getFixturesPath() . '01-copy.jpg');

Then create and add the file by using:

$file = new UploadedFile($art1->getFixturesPath() . '01-copy.jpg', 'Image1', null, null, null, true);

$art1->setFile($file);

$manager->persist($art1);

If I did not set the last parameter to ''true'' in the ''UploadedFile'' constructor as it throws an unknown error when running ''doctrine:fixtures:load''. This parameter is "Whether the test mode is active". Seeing it's a fixture it makes sense to set to test mode.

The method ''getFixturesPath()'' just retrieves the path where my sample images are stored:

// Entity file
public function getFixturesPath()
{
    return $this->getAbsolutePath() . 'web/uploads/art/fixtures/';
}

The ''getAbsolutePath()'' method has been taken from Doctrine File Uploads.

The full working code: Entity:

<?php
//src/User/MyBundle/Entity/Art.php

namespace User/MyBundle/Entity;

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

/**
 * 
 * Art Entity
 * 
 * @ORM\Entity(repositoryClass="User\MyBundle\Entity\Repository\ArtRepository")
 * @ORM\Table(name="art")
 * @ORM\HasLifecycleCallbacks
 */
class Art
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=100)
     */
    protected $title;

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

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

    private $temp;

    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/art';
    }

    public function getFixturesPath()
    {
        return $this->getAbsolutePath() . 'web/uploads/art/fixtures/';
    }

    /**
     * Sets file.
     *
     * @param UploadedFile $file
     */
    public function setFile(UploadedFile $file = null)
    {
        $this->file = $file;
        // check if we have an old image path
        if (isset($this->path)) {
            // store the old name to delete after the update
            $this->temp = $this->path;
            $this->path = null;
        } else {
            $this->path = 'initial';
        }
    }

    /**
     * Get file.
     *
     * @return UploadedFile
     */
    public function getFile()
    {
        return $this->file;
    }

    /**
     * @ORM\PrePersist()
     * @ORM\PreUpdate()
     */
    public function preUpload()
    {
        if (null !== $this->getFile()) {
            // do whatever you want to generate a unique filename
            $filename = sha1(uniqid(mt_rand(), true));
            $this->path = $filename . '.' . $this->getFile()->guessExtension();
        }
    }

    /**
     * @ORM\PostPersist()
     * @ORM\PostUpdate()
     */
    public function upload()
    {
        // the file property can be empty if the field is not required
        if (null === $this->getFile()) {
            return;
    }

        // if there is an error 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->getFile()->move($this->getUploadRootDir(), $this->path);

        // check if we have an old image
        if (isset($this->temp)) {
            // delete the old image
            unlink($this->getUploadRootDir() . '/' . $this->temp);
            // clear the temp image path
            $this->temp = null;
        }

        $this->file = null;
    }

    /**
     * @ORM\PostRemove()
     */
    public function removeUpload()
    {
        if ($file = $this->getAbsolutePath()) {
            unlink($file);
        }
    }
}

Fixture:

<?php
// src/User/MyBundle/DataFixtures/ORM/ArtFixtures.php

namespace User\MyBundle\DataFixtures\ORM;

use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Fredzz\LotwBundle\Entity\Art;
use Symfony\Component\HttpFoundation\File\UploadedFile;

class ArtFixtures extends AbstractFixture implements OrderedFixtureInterface
{
    public function load(ObjectManager $manager)
    {
        $art1 = new Art();
        $art1->setTitle('MyTitle');
        $art1->setDescription('My description');

        copy($art1->getFixturesPath() . '01.jpg', $art1->getFixturesPath() . '01-copy.jpg');
        $file = new UploadedFile($art1->getFixturesPath() . '01-copy.jpg', 'Image1', null, null, null, true);
        $art1->setFile($file);

        $art1->setUser($manager->merge($this->getReference('user-1')));

        $manager->persist($art1);
        $manager->flush();
    }
}

Hope this helps someone! Sorry if something is wrong. I'm still learning :)

like image 92
Fred John Avatar answered Oct 23 '22 20:10

Fred John