在 SilverStripe 中获取 has_one 关系

Get has_one relation in SilverStripe

我有一个名为 ApplicantDataObject,它 $has_one Member(这是 SilverStripe Member class)。

private static $has_one = array (
    'MemberApplicant' => 'Member'
);

当会员登录并访问 ApplicationPage 我希望能够根据会员 Applicant 数据填充表单。

我可以完成这项工作,但我觉得我应该能够更轻松地访问数据。

我是这样做的:

$memberID = Member::currentUserID();
$applicant = Applicant::get()->filter('MemberApplicantID', $memberID)->first();

$form->loadDataFrom($applicant);

难道我不能实例化一个 Member 然后调用它的亲戚 $MemberApplicant 吗?

听起来您希望能够通过当前用户的 Member 记录来避免 "additional" ORM 查询,但是 SilverStripe(或任何使用 SQL JOINs 有效)。

当您将 $has_one 添加到 class 时,实际上是将外键添加到 class 的 table。在您的例子中,它将被称为 MemberApplicantID,它是成员 table 的主键 - 它的 ID 字段的外键。因此,您的 ORM 查询需要先通过一个 Applicant 实例。

警告:以上内容并不完全正确,DataObject 确实允许您在模型 classes 上定义私有(SilverStripe 配置)静态 $belongs_to,它允许您查询 "The other way around"。我以前从未真正这样做过,但看起来您确实会在装饰 Member 且值为 "Applicant" 的自定义 DataExtension 上声明它。参见 DataObject::belongsToComponent()

您还可以略微简化现有的 ORM 查询,而不必显式实例化 DataList,但到目标数据的路径保持不变:

// SilverStripe >= 3.2
$applicant = DataObject::get_one('Applicant', array('MemberApplicantID = ?' => $memberID));

// SilverStripe < 3.2
$applicant = DataObject::get_one('Applicant', '"MemberApplicantID" = ' . $memberID); 

Shouldn't I be able to instantiate a Member and then call its relative $MemberApplicant?

当然可以。我假设你有一个 1:1 关系,那么你必须使用 $belongs_toMember 上定义对应部分(参见 this diagram

class Applicant extends DataObject
{
private static $has_one = [
    'MemberApplicant' => 'Member'
];
...

class MemberApplicantExtenension extends DataExtension
{
private static $belongs_to = [
    'Applicant' => 'Applicant'
];

...

现在将 DataExtension 添加到 /mysite/_config/config.yml

中的 Member 对象
Member:
  extensions:
    - MemberApplicantExtenension

和运行一个dev/build?同花顺。

现在您可以使用内置的 ORM 魔法从会员那里获得相关申请人:

//Get the current Member
$member = Member::CurrentUser();

//get the $belongs_to
$applicant = $member->Applicant();