使用 Doctrine ORM (1.2) 为预先存在的记录创建一对一关系

Posted

技术标签:

【中文标题】使用 Doctrine ORM (1.2) 为预先存在的记录创建一对一关系【英文标题】:Creating a one-to-one relation for a pre-existing record using Doctrine ORM (1.2) 【发布时间】:2011-07-27 17:00:29 【问题描述】:

背景/应用

我有两个数据库表,supplieraddress 具有一对一的关系,因为并非所有供应商都有地址(这只是一个更大应用程序的简化示例)。我在 mysql 数据库中使用 Doctrine ORM (1.2)。

我无法向没有地址的现有供应商添加地址。我可以修改已有供应商的地址,而该供应商确实有一个没有问题的供应商。

以下架构和四个简单脚本显示了流程的每个阶段发生的情况。

架构

Address:
  columns:
    id:
      type: integer
      primary: true
      autoincrement: true
    town: string(300)

Supplier:
  columns:
    id:
      type: integer
      primary: true
      autoincrement: true
    name: string(300)
    address_id: integer
  relations:
    Address:
      foreignType: one

脚本一:创建两个供应商,有地址和没有地址

$supplier = new Supplier();
$supplier->name = 'A supplier with an address';
$supplier->Address->town = 'A town';
$supplier->save();

$supplier = new Supplier();
$supplier->name = 'A supplier without an address';
$supplier->save();

脚本二:确认数据已保存

$supplier = Doctrine_Core::getTable('Supplier')->find(1);
var_dump($supplier->toArray());

$supplier = Doctrine_Core::getTable('Supplier')->find(2);
var_dump($supplier->toArray());

输出:

array
  'id' => string '1' (length=1)
  'name' => string 'A supplier with an address' (length=26)
  'address_id' => string '1' (length=1)
array
  'id' => string '2' (length=1)
  'name' => string 'A supplier without an address' (length=29)
  'address_id' => null

脚本三:获取和更新/创建地址

$supplier = Doctrine_Core::getTable('Supplier')->find(1);
$supplier->Address->town = 'A Different Town';
$supplier->save();
var_dump($supplier->toArray());

$supplier = Doctrine_Core::getTable('Supplier')->find(2);
$supplier->Address->town = 'A New Town';
$supplier->save();
var_dump($supplier->toArray());

输出:(注意,此时,它会建议该地址是为之前没有地址的第二个供应商创建的)

array
  'id' => string '1' (length=1)
  'name' => string 'A supplier with an address' (length=26)
  'address_id' => string '1' (length=1)
  'Address' => 
    array
      'id' => string '1' (length=1)
      'town' => string 'A Different Town' (length=16)
array
  'id' => string '2' (length=1)
  'name' => string 'A supplier without an address' (length=29)
  'address_id' => string '2' (length=1)
  'Address' => 
    array
      'id' => string '2' (length=1)
      'town' => string 'A New Town' (length=10)

脚本四:确认更改已保存

$supplier = Doctrine_Core::getTable('Supplier')->find(1);
var_dump($supplier->toArray());

$supplier = Doctrine_Core::getTable('Supplier')->find(2);
var_dump($supplier->toArray());

$address = Doctrine_Core::getTable('Address')->find(2);
var_dump($address->toArray());

输出:

array
  'id' => string '1' (length=1)
  'name' => string 'A supplier with an address' (length=26)
  'address_id' => string '1' (length=1)
array
  'id' => string '2' (length=1)
  'name' => string 'A supplier without an address' (length=29)
  'address_id' => null
array
  'id' => string '2' (length=1)
  'town' => string 'A New Town' (length=10)

谁能解释为什么第二个供应商的地址被插入到数据库中,但实际上并没有链接到供应商?

【问题讨论】:

【参考方案1】:

我不知道教义。我使用 Propel,但我认为如果您保存供应商,则不会将地址保存在数据库中。

您需要在保存供应商之前保存地址更改。

在伪代码中:

 $supplier=Supplier::find(2);

 $supplier->address->name="New town";

 $supplier->adress->save(); //saving de change in database. If you don't do it your change is only in the object

另一种选择:

 $supplier=Supplier::find(2);

 $address= new Adress();
 $adress->name="New town";
 $adress->save();

 $supplier->adress=$adress;
 $supplier->save();

【讨论】:

感谢 Curlas 的建议。在地址关系上运行 save 方法的第一个建议似乎与 Doctrine 的预期不同。它的输出与我上面的脚本三相似;供应商对象具有 Address 属性,但这次 address_id 属性为空。第二个建议类似于我目前使用的解决我的问题的方法。我正在检查与$supplier->relatedExists('Address') 的关系是否存在,并且要么更改预先存在的地址,要么创建一个新地址。【参考方案2】:

在处理原则对象时,我喜欢做的一件事,尤其是在迭代中,如果它给我带来问题,那就是在创建新对象之前取消设置对象。尝试取消设置

unset($supplier)

为 $supplier 分配新的教义对象之前的第一个对象。

【讨论】:

以上是关于使用 Doctrine ORM (1.2) 为预先存在的记录创建一对一关系的主要内容,如果未能解决你的问题,请参考以下文章

在 Doctrine ORM 中创建文件上传模板

Doctrine ORM 2 选择负数

PHP ORM:Doctrine vs. Propel

Doctrine Abstract - 具体类 ORM

如何将 Doctrine ORM 默认跟踪策略更改为延迟显式

Doctrine ORM 的可排序行为