如何将2个表加载到Doctrine2中的一个对象中?

时间:2011-11-17 21:21:38

标签: doctrine-orm

例如,我们有一个国家和城市的外部数据库。我们需要能够在以下条件下读取外部数据库:

  1. 我们无法以任何方式更改或修改World DB。例如,我们无法添加FK。
  2. 使用外部数据库时,我们希望保留一个内部参考,例如我们想要保留参考的实体“用户”,例如User-> city
  3. 我们希望有一个内部实体CustomCities,用户可以在其中创建自己的城市。
  4. 这样做的最佳方法是什么?

    我们尝试了几种选择,但所有选项都以这种或那种方式打破。一个建议是使用带有外部参考readOnly的@Table,但这不起作用。

    我们找到的最接近的解决方案是使用表示City对象的中间类,但不真正保存数据,然后通过本机查询填充该假对象。然后使用内部逻辑确定所请求的项目(如User-> getCity())是来自City DB还是来自CityCustomDB ...

    有关如何处理此事的任何想法?

1 个答案:

答案 0 :(得分:1)

我猜测了可能的架构,您是否尝试过使用类表继承,以便该国家/地区成为您的界面。

Database Schema

interface CountryInterface
{
    public function getName();
}

所以你的实体可能看起来像这样

/**
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="type", type="string")
 * @DiscriminatorMap({
 *     "internal" = "InternalCountry"
 *     ,"external" = "ExternalCountryAlias"
 * })
 */
abstract class AbstractCountry implements CountryInterface
{
    protected $id;
}

class InternalCountry extends AbstractCountry
{
    protected $name;

    public function getName()
    { 
        return $this->name;
    }
}

ExternalCountryAlias的工作方式类似于ExternalCountry的代理,但我将其命名为Alias,以免将其与Data Mapper Proxies混淆。

class ExternalCountryAlias extends AbstractCountry
{
    /**
     * @OneToOne(targetEntity="ExternalCountry")
     * @JoinColumn(name="external_country_id"
     *     ,referencedColumnName="id")
     */
    protected $externalCountry;

    public function getName()
    {
        return $this->externalCountry->getName();
    }
}

ExternalCountry不必从基类扩展。

class ExternalCountry 
{
    protected $name;

    public function getName()
    {
        return $this->name;
    }
}

因此,当您获得一个国家时,您正在引用基类。我们可以说country.id = 1是内部国家,country.id = 2是外部国家。

// returns an instance of InternalCountry
$entityManager->find('AbstractCountry', 1);

// returns an instance of ExternalCountryAlias 
$entityManager->find('AbstractCountry', 2); 

因为他们都实现了CountryInterface,你不必担心他们来自哪里,你仍然可以通过调用getName()来访问该名称;