Orm Silverstripe:同一类的多对多关系

Orm Silverstripe:同一类的多对多关系,orm,many-to-many,silverstripe,Orm,Many To Many,Silverstripe,我有一个班叫“表演”,可以互相表演,互相推荐表演。经过一些尝试和错误,我有一些半工作,使用ORM: public static $many_many = array( 'Recommendations' => 'Performance' ); public static $belongs_many_many = array( 'Recommendations' => 'Performance' ); 上面让我指定了推荐,但在正常的多对多(两

我有一个班叫“表演”,可以互相表演,互相推荐表演。经过一些尝试和错误,我有一些半工作,使用ORM:

public static $many_many = array(
    'Recommendations'       => 'Performance'
);

public static $belongs_many_many = array(
    'Recommendations'       => 'Performance'
);
上面让我指定了推荐,但在正常的多对多(两个类之间)中,也可以使用另一种方式的关系。这里不是。关于如何使反向关系在“Performance”类上可见而不创建多对多反向关系并手动插入反向关系的任何线索

更新(2014年5月22日):目前我的结论是,这个问题没有现成的解决方案。基于@FinBoWa的解决方案,我给出了以下最小示例,其中显示了“Degree.interestingdegrees的逆分量versed not found(Degree)”:


我还尝试了@g4b0的解决方案,但它有一个严重的缺点,即它没有在管理中显示反向关系。目前我正在使用他的解决方案,但这并不是问题的真正解决方案。因此,我暂时不接受答案…

您应该能够在关系中使用点符号

我们的一个项目有学位,我们希望使用同一个类来关联有趣的学位:

private static $many_many = array(
    'InterestingDegrees' => 'Degree'
);

private static $belongs_many_many = array(
    'InterestingDegreesReversed' => 'Degree.InterestingDegrees'
);
如果在关联站点树时手动添加编辑器,则此操作有效

但是如果您使用模型管理,您必须手动声明字段,否则将出现错误。因此,如果您使用的是model admin,一个工作示例是:

class Degree extends DataObject {

    private static $db = array(
        "Name"  => "Varchar(255)",
    );

    private static $many_many = array(
        'InterestingDegrees' => 'Degree'
    );

    private static $belongs_many_many = array(
        'InterestingDegreesReversed' => 'Degree.InterestingDegrees'
    );

    public function getCMSFields() {

        $fields =  new FieldList();

        $fields->add(new TextField("Name"));

        // dont show the field untill we have something to relate to 
        if($this->ID){
            //Interesting degrees
            $gfc = GridFieldConfig_RelationEditor::create();
            //Remove add and edit features
            $gfc->removeComponentsByType('GridFieldAddNewButton');
            $gfc->removeComponentsByType('GridFieldEditButton');
            $gf = new GridField('InterestingDegrees', null, $this->InterestingDegrees(), $gfc);
            $fields->add($gf);
        }
        return $fields;
    }
}

class DegreeAdmin extends ModelAdmin {
    public static $managed_models       = array('Degree'); 
    static $url_segment                 = 'degrees'; 
    static $menu_title                  = 'Degrees';
}

您应该能够在关系中使用点符号

我们的一个项目有学位,我们希望使用同一个类来关联有趣的学位:

private static $many_many = array(
    'InterestingDegrees' => 'Degree'
);

private static $belongs_many_many = array(
    'InterestingDegreesReversed' => 'Degree.InterestingDegrees'
);
如果在关联站点树时手动添加编辑器,则此操作有效

但是如果您使用模型管理,您必须手动声明字段,否则将出现错误。因此,如果您使用的是model admin,一个工作示例是:

class Degree extends DataObject {

    private static $db = array(
        "Name"  => "Varchar(255)",
    );

    private static $many_many = array(
        'InterestingDegrees' => 'Degree'
    );

    private static $belongs_many_many = array(
        'InterestingDegreesReversed' => 'Degree.InterestingDegrees'
    );

    public function getCMSFields() {

        $fields =  new FieldList();

        $fields->add(new TextField("Name"));

        // dont show the field untill we have something to relate to 
        if($this->ID){
            //Interesting degrees
            $gfc = GridFieldConfig_RelationEditor::create();
            //Remove add and edit features
            $gfc->removeComponentsByType('GridFieldAddNewButton');
            $gfc->removeComponentsByType('GridFieldEditButton');
            $gf = new GridField('InterestingDegrees', null, $this->InterestingDegrees(), $gfc);
            $fields->add($gf);
        }
        return $fields;
    }
}

class DegreeAdmin extends ModelAdmin {
    public static $managed_models       = array('Degree'); 
    static $url_segment                 = 'degrees'; 
    static $menu_title                  = 'Degrees';
}

您必须为many\u many和properties\u many指定两个不同的名称,以便访问它们。例如:

public static $many_many = array(
    'RelatedRecommendations' => 'Performance'
);

public static $belongs_many_many = array(
    'Recommendations'        => 'Performance'
);

您必须为many\u many和properties\u many指定两个不同的名称,以便访问它们。例如:

public static $many_many = array(
    'RelatedRecommendations' => 'Performance'
);

public static $belongs_many_many = array(
    'Recommendations'        => 'Performance'
);

这两个想法我都看过了,这就是我为一个正在进行的项目(我使用的是
品牌
模型)想到的。 这是两种解决方案的启发,我要添加的唯一附加项是
onAfterWrite
方法。在这里,我只是循环浏览所有品牌,并添加另一面

这只需要通过
品牌
选项卡编辑所有品牌。另一个应该在
getCMSFields
中删除,如下所示:
$fields->removeByName('RelatedBrands')


这两个想法我都考虑过了,这就是我为一个正在进行的项目(我使用的是
品牌
模型)想到的。 这是两种解决方案的启发,我要添加的唯一附加项是
onAfterWrite
方法。在这里,我只是循环浏览所有品牌,并添加另一面

这只需要通过
品牌
选项卡编辑所有品牌。另一个应该在
getCMSFields
中删除,如下所示:
$fields->removeByName('RelatedBrands')



谢谢你的回答!但是,将这两个结果添加到编辑屏幕中的两个选项卡中,这两个选项卡似乎没有关系。也就是说,当添加一个RelatedRecommension时,不会添加一个建议。上面的代码对我来说很有用,如果我将一个RelatedRecommension(a)添加到现有性能(B)中,那么我可以在a的建议中看到B。只需尝试在模板中循环推荐和RelatedRecommensions。我还建议您通过removeByName函数删除“建议”选项卡。好的,我明天再查。但是,我需要两个制表符,因为关系不是对称的。有没有关于如何做到这一点的线索?顺便问一下,ORM应该如何知道如何将两者联系起来?试试吧。在B中,您将在“相关建议”选项卡中看到A,而在B中,您将在“建议”选项卡中看到A。您可以选择是将两个选项卡保留在后端,还是删除其中一个选项卡。在前端,它将只是工作尊重。谢谢你的回答!但是,将这两个结果添加到编辑屏幕中的两个选项卡中,这两个选项卡似乎没有关系。也就是说,当添加一个RelatedRecommension时,不会添加一个建议。上面的代码对我来说很有用,如果我将一个RelatedRecommension(a)添加到现有性能(B)中,那么我可以在a的建议中看到B。只需尝试在模板中循环推荐和RelatedRecommensions。我还建议您通过removeByName函数删除“建议”选项卡。好的,我明天再查。但是,我需要两个制表符,因为关系不是对称的。有没有关于如何做到这一点的线索?顺便问一下,ORM应该如何知道如何将两者联系起来?试试吧。在B中,您将在“相关建议”选项卡中看到A,而在B中,您将在“建议”选项卡中看到A。您可以选择是将两个选项卡保留在后端,还是删除其中一个选项卡。在前端,它将只是作为尊重的工作。谢谢。。。我已经尝试过这个解决方案,但它导致了一个错误:Performance.RecommendationsReversed not found(Performance)的反向组件绝对适用于3.1.4,因此您必须在不同的版本上运行,或者在启用它之后忽略运行开发版本。这显然不适用于3.1.4和3.1.5。我创建了一个极小的对象,它给出了相同的错误消息。但这可能是因为我没有使用正常的页面结构。我只是在处理DataObjects:class Degree扩展了DataObject,我们的代码来自于生产代码,而且它确实有效!我去看看还有什么要说的吗!我认为您依赖于模型管理员自动生成编辑器,因此关系本身不是问题,而是自动编辑器g