1
votes

I have an entity that stores large files as blobs to the DB.

I would now like to get Symfony to never ever load these blobs unless I specifically request them via the appropriate getter.

In essence I want the same idea as lazy-loading relationships but for a string property.

What I have tried so far is to put all my other properties that hold the file meta data into a trait and then apply that trait to two entities.

namespace App\Entity\Traits;

use Doctrine\ORM\Mapping as ORM;

trait DocumentMetaData
{
    /**
     * @var int|null
     *
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var \DateTime|null
     *
     * @ORM\Column(type="datetime")
     */
    private $date_uploaded;
}

One entity has nothing to it but the trait...

namespace App\Entity;

use App\Entity\Traits\DocumentMetaData;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table(name="documents")
 * @ORM\Entity()
 */
class Document
{
    use DocumentMetaData;
}

...the other has the added blob property:

namespace App\Entity;

use App\Entity\Traits\DocumentMetaData;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table(name="documents")
 * @ORM\Entity()
 */
class DocumentFile
{
    use DocumentMetaData;

    /**
     * @var string|null
     *
     * @ORM\Column(type="blob")
     */
    private $blob;
}

Now, if I don't want the blob to be loaded, for example for a listing of files, I simply use the entity that doesn't have the blob.

This approach sort of works but causes issues as I need to point both entities at the same table (see the class level ORM annotations).

Specifically, it makes doctrine freak out when running migrations:

The table with name 'myapp.documents' already exists.

That makes perfect sense and really I'm hoping that someone can point me to a nicer solution.

How can I tell doctrine not to load the blob unless its explicitly asked for?

1
Move the blob into it's very own table/entity. Or don't use the ORM. - Cerad
I don't think not using the ORM is an option in my case but the new table approach sounds interesting. Could you elaborate @Cerad ? I assume you mean to have it stored as a One to One relationship instead of directly on the main Entity? - Bananaapple
Nothing mysterious. Make yourself a DocumentMetaData entity with an id property as well as a blob property. Then associate it with your Document entity. You can even explicitly set LAZY_LOAD on the associations just to make sure how it is loaded even though lazy loading will be used by default. It is all in the docs. - Cerad
Perfect, thanks @Cerad . If you want to add an answer I'm more than happy to tick it. - Bananaapple

1 Answers

1
votes

So as per the comments on my question - the way to do this so that migrations do not break is to leverage doctrine's ability to lazy load relationships between tables.

Basically I had to go and create a new entity that only holds my giant blobs and then establish a one to one relationship between the original entity and the blob entity.

I then set that relationship to load EXTRA_LAZY and as a result I can now control when precisely the blobs of giant data should be loaded.

I don't think this is ideal in terms of normalising the DB design but it works a lot better than anything else so happy with that.