Silverstripe 3.1多个many_many关系表

时间:2014-07-29 15:02:07

标签: silverstripe

我有一个DataObject“Rectangle”。它与“AttributeValue”(例如10英寸)存在许多关系。 DataObject“AttributeValue”也与“属性”(例如长度(或宽度))有许多关系。我想在CMS的“矩形”页面上创建一个表,它显示了AttributeValue和相关的属性:

属性|值

长度| 10英寸

宽度| 20英寸

颜色|红色

原因属性与Rectangle无关,我不知道如何获取该表中的数据。使用以下代码生成表的值:

class Rectangle extends Page {
    private static $db = array(...);
    private static $many_many = array(
        'AttributeValue' => 'AttributeValue',
    );
    public function getCMSFields() {
        $fields = parent::getCMSFields();

        $config = GridFieldConfig_RelationEditor::create();
        $config->getComponentByType('GridFieldDataColumns')->setDisplayFields(array(
            'AttributeValue'=>'Value'
        ));

        $attrField = new GridField(
            'AttributeValue',
            'AttributeValue',
            $this->AttributeValue(),
            $config
        );

        $fields->addFieldToTab('Root.Attribute', $attrField);        
        return $fields;
    }
}
class AttributeValue extends DataObject {
    private static $db = array('AttributeValue' => 'Varchar');
    private static $belongs_many_many = array('Rectangle' => 'Rectangle');
    private static $many_many   = array('Attribute' => 'Attribute');
}

class Attribute extends DataObject {
    private static $db = array('Attribute' => 'Varchar');   
    private static $belongs_many_many = array('AttributeValue' => 'AttributeValue');
}

修改

我有RectangleAttributeValues相关的一些Attribute(例如10英寸,20英寸,红色),所以在数据库中有一个表Rectangle_AttributeValue,它显示了这种关系。我还有与AttributeValue(表AttributeValue_Attribute)相关的对象{{1}},例如10英寸 - >长度,或红色 - >颜色。所以整个“关系链”看起来像:Rectangle-> AttributeValue-> Attribute(Rectangle1 - > 10 inch - > length,或Rectangle1 - >>> color)。我希望我能说得更清楚......

2 个答案:

答案 0 :(得分:0)

首先,为了清楚起见,您应该将您的many_many声明复数化,如:

private static $many_many   = array('AttributeTypes' => 'AttributeType');

private static $belongs_many_many = array('Rectangles' => 'Rectangle');

回答你的问题“因为AttributeType与Rectangle无关,我不知道如何获取该表中的数据”:你没有,你不应该这样做。要在矩形页面中“获取”某些类型的属性,首先要创建一个具有关联类型的属性,然后将其添加到“矩形”页面。然后,您可以访问类型:

foreach($this->AttributeValues() as $attribute) {
    echo "attribute: ".$attribute->AttributeValue."<br />";
    foreach($attribute->AttributeTypes() as $type) {
        echo "type: ".$type->AttributeType."<br />;
    }
}

但也许您只想在矩形页面上的CMS中显示后端的类型。为此,你可以在矩形对象的静态$ summary_fields中添加一个额外的非现有字段,例如。

private static $summary_fields = array(
    "yourfield" => "CMS Titel", //one line per field you want in the summary
    "AttributeValuesAndTypes" => "Attribute values and types"
);

然后您可以使用上面的代码在矩形类中执行类似的操作:

public function getAttributeValuesAndTypes() {
    $attributes = array();
    foreach($this->AttributeValues() as $attribute) {
        $types = array();
        foreach($attribute->AttributeTypes() as $type) {
            $types[] = $attribute->AttributeType;
        }
        $attributes[] = $attribute->AttributeValue." (".implode(",",$types).")";
    }
    return implode(",",$attributes);
}

这将在概述中添加一个额外的列,其中包含“属性1(类型1,类型2),属性2(类型2,类型3)等”。作为额外的奖励,你可以摆脱额外的getCMSFields。

请注意,如果每个矩形有很多属性,并且每个属性有很多类型,这很快就会变得混乱。

希望这会有所帮助。如果没有,请稍微澄清一下你的问题:-)

答案 1 :(得分:-1)

就个人而言,我不建议您采用的方法,因为您将获得将使用的每个唯一值的Attribute记录;因此,设置几乎看起来像EAV模型。 EAV模型很糟糕

话虽如此,它可能是唯一的方法。这就是我构建它的方式:

class Rectangle extends Page {
    private static $many_many = array(
        'Attributes' => 'Attribute'
    );

    public function getCMSFields() {
        $fields = parent::getCMSFields();

        $fields->addFieldToTab('Root.Attributes', new GridField('Attributes', 'Attributes', $this->Attributes(), GridFieldConfig_RelationEditor::create()));

        return $fields;
    }
}

class Attribute extends DataObject {
    static $db = array(
        'Title' => 'Varchar(255)', // You may want to make this an enum to limit what gets added 'Enum(array("Length", "Width", "Colour"))'
        'Value' => 'Varchar(255)'
    );

    static $belongs_many_many = array(
        'Pages' => 'Page'
    );

    static $summary_fields = array(
        'Title',
        'Value'
    );

    static $searchable_fields = array(
        'Title',
        'Value'
    );
}

这里不需要第三个模型。名称和值将存储为Attribute,并附加到页面。

我使用与此几乎完全相同的结构来保存商务模块中的产品属性。像魅力一样。

让我知道你对这种方法的看法。

有关EAV的更多信息:http://en.wikipedia.org/wiki/Entity-attribute-value_model