2016-09-27 56 views
0

我需要帮助,我symfony3应用程序创建我的实体丝毫原则2:带有doctrine和symfony 3的文件存储?

我想我的用户可以张贴文章,其内容是:

  • 标题
  • 作者
  • 任何一个独特的图像(上传文件)
  • 或一个独特的电影($网址)

什么你推荐? 我应该如何构建我的文章实体?

class Article 
{ 
    /** 
    * @var int 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var integer 
    * 
    * @ORM\Column(name="author", type="integer") 
    */ 
    private $author; 

    /** 
    * @var ? 
    * 
    * @ORM\Column(name="image", type="?") 
    */ 
    private $image; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="url_movie", type="string") 
    */ 
    private $url_movie; 

    /** 
    * @var integer 
    * 
    * @ORM\Column(name="media", type="integer") 
    */ 
    private $media; 
} 

(在控制器:如果$媒体= 1 =>这是一个图像,否则这是一个视频)

或者使用类似的关系一比一与新的实体“媒体”例如 ?

我的情况最好的办法是什么?

回答

1

是的,这是正常的。可悲的是,鉴别器列是由数据库方面的Doctrine使用,因此它不能在您的实体中访问。有两种可能的方式来实现你想要什么:


首先,使用儿童类名:

/** 
* Article 
* 
* @ORM\Table(name="article") 
* @ORM\Entity(repositoryClass="PM\PlatformBundle\Repository\ArticleRepository") 
* @ORM\InheritanceType("SINGLE_TABLE") 
* @ORM\DiscriminatorColumn(name="media", type="string") 
* @ORM\DiscriminatorMap({"article" = "Article", "movie" = "Movie", "image" = "Image"}) 
*/ 
class Article 
{ 
    /** 
    * @var int 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="title", type="string", length=255) 
    */ 
    private $title; 

    //... 

    /** 
    * Get article type. 
    * 
    * @return string 
    */ 
    public function getType() 
    { 
     // This will return "movie" or "image" 
     return strtolower(substr(strrchr(get_class($this), "\\"), 1)); 
    } 
} 

/** 
* Movie 
* 
* @ORM\Entity 
*/ 
class Movie extends Article 
{ 
    /** 
    * @var string 
    * 
    * @ORM\Column(name="url", type="text") 
    */ 
    private $url; 

    //getter setter 
} 

/** 
* Image 
* 
* @ORM\Entity 
*/ 
class Image extends Article 
{ 
    /** 
    * @var string 
    * 
    * @ORM\Column(name="path", type="string", length=255) 
    */ 
    private $path; 

    //getter setter 
} 

第二,在你的类声明手动类型:

/** 
* Article 
* 
* @ORM\Table(name="article") 
* @ORM\Entity(repositoryClass="PM\PlatformBundle\Repository\ArticleRepository") 
* @ORM\InheritanceType("SINGLE_TABLE") 
* @ORM\DiscriminatorColumn(name="media", type="string") 
* @ORM\DiscriminatorMap({"article" = "Article", "movie" = "Movie", "image" = "Image"}) 
*/ 
class Article 
{ 
    /** 
    * @var int 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="title", type="string", length=255) 
    */ 
    private $title; 

    /** 
    * @var string 
    */ 
    protected $type; 

    //... 

    /** 
    * Get article type. 
    * 
    * @return string 
    */ 
    public function getType() 
    { 
     return $this->type; 
    } 
} 

/** 
* Movie 
* 
* @ORM\Entity 
*/ 
class Movie extends Article 
{ 
    /** 
    * @var string 
    * 
    * @ORM\Column(name="url", type="text") 
    */ 
    private $url; 

    public function __construct() 
    { 
     $this->type = 'movie'; 
    } 

    //getter setter 
} 

/** 
* Image 
* 
* @ORM\Entity 
*/ 
class Image extends Article 
{ 
    /** 
    * @var string 
    * 
    * @ORM\Column(name="path", type="string", length=255) 
    */ 
    private $path; 

    public function __construct() 
    { 
     $this->type = 'image'; 
    } 

    //getter setter 
} 

Personnaly,我有一个pr参考第一个解决方案。我发现它更清洁,更具演化性(如果您必须添加第三种文章类型,此代码将适应)。

当然,您也可以使用instanceof来确定哪个子类是您正在操作的Article实体。

+1

感谢您的帮助,但我已经在我的模板中直接为测试文章类型创建了自己的树枝扩展,现在它完美地工作!不需要手动声明类型或其他方法。 –

+0

这是另一种方式来做到这一点!我很高兴你达到了你想要的。 :) – Boulzy

+0

我回到了这里,目前我正在通过表单添加新文章。我很困惑。看这里http://stackoverflow.com/questions/39791247/build-form-with-single-table-inheritance –

1

我认为使用媒体实体和处理媒体实体中的媒体类型是最好的方法。

class Article 
{ 
    /** 
    * @var int 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    // ... 

    /** 
    * @var Media 
    * 
    * @OneToOne(targetEntity="Media") 
    * @ORM\JoinColumn(name="media_id", referencedColumnName="id") 
    */ 
    private $media; 
} 

class Media 
{ 
    const TYPE_IMAGE = 'image'; 
    const TYPE_MOVIE = 'movie'; 

    /** 
    * @var int 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var string 
    * 
    * @ORM\Column(type="string") 
    */ 
    private $url; 

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

一种其他的方式来做到这一点可能是使用entity inheritance来对图像和动画型动物实体 - 如果你需要。

+0

但是我不明白你上面的媒体类。您的类别没有图片路径或电影网址的属性。它是如何工作的? –

+1

我没有将这个反射推得太远:D我假设(错误地,我猜^^)你的图像也是由URL定义的。如果管理它们的方式不同,那么实体继承可能是一个很好的选择。媒体实体将只是一个类,在您的Article实体中只有一个属性“媒体”,它可以包含两种不同类的类。 – Boulzy

+0

有效的是。所以在Doctrine的文档中,我必须在单表继承和类表继承之间进行选择? –

0

好吧,我做了我的文章类中的单表继承:

/** 
* Article 
* 
* @ORM\Table(name="article") 
* @ORM\Entity(repositoryClass="PM\PlatformBundle\Repository\ArticleRepository") 
* @ORM\InheritanceType("SINGLE_TABLE") 
* @ORM\DiscriminatorColumn(name="media", type="string") 
* @ORM\DiscriminatorMap({"article" = "Article", "movie" = "Movie", "image" = "Image"}) 
*/ 
class Article 
{ 
    /** 
    * @var int 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="title", type="string", length=255) 
    */ 
    private $title; 

    //... 
} 

/** 
* Movie 
* 
* @ORM\Entity 
*/ 
class Movie extends Article 
{ 
    /** 
    * @var string 
    * 
    * @ORM\Column(name="url", type="text") 
    */ 
    private $url; 

    //getter setter 
} 

/** 
* Image 
* 
* @ORM\Entity 
*/ 
class Image extends Article 
{ 
    /** 
    * @var string 
    * 
    * @ORM\Column(name="path", type="string", length=255) 
    */ 
    private $path; 

    //getter setter 
} 

这伟大工程!