Php SilverStripe-当一个管理模型被赋予新条目时更新另一个管理模型

Php SilverStripe-当一个管理模型被赋予新条目时更新另一个管理模型,php,silverstripe,Php,Silverstripe,在SilverStripe中,我有两个管理模型:服务和位置。位置是位置的列表。服务是这些位置可以提供的服务列表。但是,只有某些地点可以提供某些服务。我想做的是,每当添加一个新位置(或者如果删除或重命名一个位置),我都想将其添加到每个服务下的复选框字段中(这样,内容管理器可以随时轻松控制在何处提供哪些服务) 以下是服务数据对象代码(注意:我还没有在复选框字段中添加): 以下是位置数据对象代码: class Locations extends DataObject { private st

在SilverStripe中,我有两个管理模型:服务和位置。位置是位置的列表。服务是这些位置可以提供的服务列表。但是,只有某些地点可以提供某些服务。我想做的是,每当添加一个新位置(或者如果删除或重命名一个位置),我都想将其添加到每个服务下的复选框字段中(这样,内容管理器可以随时轻松控制在何处提供哪些服务)

以下是服务数据对象代码(注意:我还没有在复选框字段中添加):

以下是位置数据对象代码:

class Locations extends DataObject {

    private static $db = array(
        'Name' => 'varchar',
        'AcceptingAppointments' => 'boolean',
    );

    public static $summary_fields = array(
        'Name' => 'Title',
        'AcceptingAppointments' => 'Accepting Appointments?',
    );

    public function AcceptingAppointments() {
        return ($this->AcceptingAppointments==true ? 'Yes':'No');
    }
}
到目前为止一切正常。我可以添加、编辑和删除位置和服务。但是,我不知道如何处理编码服务,以便每当内容管理器添加、删除或重命名位置条目时,每个服务都会更新为所有位置的完整列表


在这方面,使用
$会有很多关系起作用吗

需要的是
服务
位置
之间的
$many
关系。我们需要多对多关系,因为一个服务可以有多个位置,而一个位置可以有多个服务。要了解有关使用
$many\的更多信息,许多
关系都会阅读或

一旦定义了一个
$many\u many
关系,我们就可以添加一个来控制这个关系

注意,我已将
位置
类重命名为
位置
,将
服务
重命名为
服务
,因为我认为类名应该是单数

服务

class Service extends DataObject {

    private static $db = array(
        'Name' => 'Varchar'
    );

    private static $belongs_many_many = array(
        'Locations' => 'Location'
    );

    private static $summary_fields = array(
        'Name' => 'Title'
    );

    private static $field_labels = array(
        'Name'
    );

    public function getCMSFields() {

        $fields = parent::getCMSFields();

        if ($this->ID) {
            $fields->addFieldToTab('Root.Locations', CheckboxSetField::create(
                'Locations', 
                'Locations', 
                Location::get()->map()
            ));
        }

        return $fields;
    }

}
位置
上,我们将
$bellings\u many
关系添加回
服务
,以便我们可以控制双方的关系

位置

class Location extends DataObject {

    private static $db = array(
        'Name' => 'Varchar',
        'AcceptingAppointments' => 'Boolean'
    );

    private static $many_many = array(
        'Services' => 'Service'
    );

    private static $summary_fields = array(
        'Name',
        'AcceptingAppointmentsNice'
    );

    private static $field_labels = array(
        'Name' => 'Title',
        'AcceptingAppointmentsNice' => 'Accepting Appointments?'
    );

    public function AcceptingAppointmentsNice() {
        return $this->AcceptingAppointments ? 'Yes' : 'No';
    }

    public function getCMSFields() {
        $fields = parent::getCMSFields();
        if ($this->ID) {
            $fields->addFieldToTab('Root.Services', CheckboxSetField::create(
                'Services', 
                'Services', 
                Service::get()->map()
            ));
        }
        return $fields;
    }
}
CheckboxSetField
的另一种选择是。
ListboxField
是一个整洁的下拉多选字段。如果选项列表很长,那么它很有用

class Service extends DataObject {

    // ...

    public function getCMSFields() {

        $fields = parent::getCMSFields();

        if ($this->ID) {
            $fields->addFieldToTab('Root.Locations', ListboxField::create(
                'Locations', 
                'Locations', 
                Location::get()->map('ID', 'Name')->toArray(),
                array(),
                null,
                true
            ));
        }

        return $fields;
    }

}

另外请注意,
$summary\u字段
必须声明为
私有
变量,而不是
公共
变量。

Wow…这太完美了!非常感谢你的回答——它回答了我的确切问题,证实了我的一些想法,似乎已经按照我想要的方式安排好了一切。
class Service extends DataObject {

    // ...

    public function getCMSFields() {

        $fields = parent::getCMSFields();

        if ($this->ID) {
            $fields->addFieldToTab('Root.Locations', ListboxField::create(
                'Locations', 
                'Locations', 
                Location::get()->map('ID', 'Name')->toArray(),
                array(),
                null,
                true
            ));
        }

        return $fields;
    }

}