在 SilverStripe 中获取 has_one 关系
Get has_one relation in SilverStripe
我有一个名为 Applicant
的 DataObject
,它 $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 JOIN
s 有效)。
当您将 $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_to
在 Member
上定义对应部分(参见 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();
我有一个名为 Applicant
的 DataObject
,它 $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 JOIN
s 有效)。
当您将 $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_to
在 Member
上定义对应部分(参见 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();