将参数注入实体

时间:2014-11-29 14:18:36

标签: symfony doctrine-orm

我经常遇到这个问题,但直到现在我才想学习最好的方法。

假设我有一个Image实体,它有一个'path'属性,用于存储图像文件的相对路径。例如,图像的“路径”为“20141129 / 123456789.jpg”。

在parameters.yml中,我设置了存储图像文件的目录的绝对路径。像这样:

image_dir: %user_static%/images/galery/

我想将方法​​'getFullPath()'添加到Image实体,其中'image_dir'参数将与'path'属性连接。我不想在控制器中进行连接,因为我将使用它很多。此外,我不想将图像目录插入到图像的“路径”属性中,因为我可能稍后更改图像目录路径(这意味着我将不得不更新数据库中所有图像的“路径”)。

那么如何将参数注入Image实体,以便getFullPath()可以使用它?由于Image实体将由存储库方法提取而不是创建Image的新实例,因此将变量传递给构造方法将不起作用。

或者有更优雅的方法吗?我只是希望Image实体有getFullPath()方法,我将通过存储库方法(find,findBy ...)和查询构建器获取图像。

2 个答案:

答案 0 :(得分:4)

您可以收听doctrine postLoad事件并在其中设置image目录,以便以后调用getFullPath()时,它可以返回图像目录和路径的连接字符串。

postLoad listener

namespace Acme\ImageBundle\Doctrine\EventSubscriber;

use Acme\ImageBundle\Model\ImageInterface;
use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
use Doctrine\ORM\Events;

class ImageDirectorySubscriber implements EventSubscriber
{
    protected $imageDirectory;

    public function __construct($imageDirectory)
    {
        $this->imageDirectory = $imageDirectory;
    }

    public function getSubscribedEvents()
    {
        return array(
            Events::postLoad,
        );
    }

    public function postLoad(LifecycleEventArgs $args)
    {
        $image = $args->getEntity();

        if (!$image instanceof ImageInterface) {
            return;
        }

        $image->setImageDirectory($this->imageDirectory);
    }
}

services.yml

parameters:
    acme_image.subscriber.doctrine.image_directory.class:
            Acme\ImageBundle\Doctrine\EventSubscriber\ImageDirectorySubscriber

services:
    acme_image.subscriber.doctrine.image_directory:
        class: %acme_image.subscriber.doctrine.image_directory.class%
        arguments:
            - %acme_image.image_directory%
        tags:
            - { name: doctrine.event_subscriber }

图像模型

class Image implements ImageInterface
{
    protected $path;

    protected $imageDirectory;

    .. getter and setter for path..

    public function setImageDirectory($imageDirectory)
    {
        // Remove trailing slash if exists
        $this->imageDirectory = rtrim($imageDirectory, '/');

        return $this;
    }

    public function getFullPath()
    {
        return sprintf('%s/%s', $this->imageDirectory, $this->path);
    }
}

答案 1 :(得分:1)

@ Qoop的方法的另一种方法是制作图像管理器服务并在其中执行路径。代码会更简单一些。

class ImageManager
{
    public function __construct($imageDirectory)
    {
        $this->imageDirectory = $imageDirectory;
    }
    public function getFullPath($image)
    {
        return $this->imageDirectory . $image->getPath();
    }
}

// Controller
$imageManager = $this->get('image_manager');

echo $imageManager->getFullPath($image);

这是一种权衡。在幕后使用"明确管理图像"事件