OctoberCMS 根据当前选定的记录过滤关系小部件

OctoberCMS filter Relation Widget based from currently selected record

标题说明了一切,还是举个例子吧。我有一个 Member 记录和一个 Group。一个成员可以拥有多个组的成员资格,一个组可以有多个成员。 (所以这是多对多,我会有一个支点 table。)

现在,每个群组都有会员等级。例如,(免费、免费增值、高级、超级高级)。所以 membership_grade 应该属于枢轴 table,对吗?但问题是,并非所有小组的成绩都相同。有些可能只有 FreeFreemium,有些可能全部都有。

Membership枢轴模型的fields.yaml中,我将membership_grades定义为Relation Widget,像这样:

pivot[grade]:
  label: Membership Grade
  span: full
  type: relation
  nameFrom: name

并且在 Membership.php 中的关系是这样的:

public $belongsTo = [
    'grade' => [
        'Acme\Models\Grade',
    ]
];

显然,这将公开 ALL 成绩,因为我正在从 Grade 模型中提取数据。我想要的是公开该组可用的成绩,而不是 all.

我想做的(但我没有,因为这似乎不可能)是尝试从组的 grades 关系中提取数据,但我应该怎么做? (由于 Relation 小部件管理模型的关系,我不能像那样简单地从其他来源提取数据)。

我也试过 scopes 但我应该如何通过我所在的当前组?由于需要它作为过滤器,像这样:

// Membership.php

public $belongsTo = [
    'grade' => [
        'Acme\Models\Grade',
        'scope' => 'filteredIt'
     ],
     // added this relationship to try the scopes approach
     'group' => [
        'Acme\Models\Group'
     ]
];

// Grade.php

public function scopeFilteredIt($query, Membership $m) 
// yes, the second parameter in the scope will be the 
// current Membership model. I've tried it.
{
    // this won't work, since we want the overall relation filter;
    // an instance of Membership won't help.
    // this would work if I can find a way to pass the 
    // current Group (record) selected, and get its grades, then use it here.
    return $query->whereIn('id', $m->group->grades->pluck('id')->all());
}

有什么想法吗?

我在 pivot model ajax 通话期间注意到一些 post values

当你add new record和你的枢轴模型打开时post values是这样的

Array (
    [_relation_field] => groups
    [_relation_extra_config] => W10=
    [foreign_id] => 1
    [_session_key] => VrSCoKQrSkIsZNGIju5QIqpdbS3AADoGQRHAsv1e
)

好消息是我们现在可以得到 foreign_id 因为它将是你的 selected group id 我们可以在创建时使用它for updateyou know时我们有relation so we use that

public function scopefilteredIt($query, Membership $m)
{
    // we are checking relation is there or not
    if($m->group) {
        // yes group is there we use it 
        return $query->whereIn('id', $m->group->grades->pluck('id')->all());
    }
    else {
        // seems new record then use foreign_id
        $foreign_id = post('foreign_id'); //<-this will be your selected group id
        if($foreign_id) { // <- double check if its there
            $group = Group::find($foreign_id);
            return $query->whereIn('id', $group->grades->pluck('id')->all());
        }
    }
    return $query;
}

如有任何问题,请发表评论。

to check post

public function scopefilteredIt($query, Membership $m)
{

    // will show flash message with post data array
    $post = print_r(post(), true);
    \Flash::success($post);

    // we are checking relation is there or not
    if($m->group) {
        // yes group is there we use it 
        return $query->whereIn('id', $m->group->grades->pluck('id')->all());
    }
    else {
        // seems new record then use foreign_id
        $foreign_id = post('foreign_id'); //<-this will be your selected group id
        if($foreign_id) { // <- double check if its there
            $group = Group::find($foreign_id);
            return $query->whereIn('id', $group->grades->pluck('id')->all());
        }
    }
    return $query;
}