【问题标题】:Silverstripe 3.1 table of multiple many_many relationshipsSilverstripe 3.1 多个many_many 关系表
【发布时间】:2014-07-29 15:02:06
【问题描述】:

我有一个数据对象“矩形”。它与“AttributeValue”(例如 10 英寸)存在多对多关系。数据对象“AttributeValue”也与“Attribute”有很多关系(例如长度(或宽度))。我想在 CMS 中的“矩形”页面上创建一个表格,显示 AttributeValue 和相关的 Attribute:

属性 |价值

长度 | 10英寸

宽度 | 20英寸

颜色 |红色

Cause Attribute 与 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');
}

编辑:

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

【问题讨论】:

  • 不应该AttributeValueAttributeType$has_one 关系吗? AttributeValue 不能同时是 lengthwidthAttributeType 将与 AttributeValue 建立 $has_many 关系,但不是多对多。
  • AttributeValue 两者都可以,例如:10 inch 可以是长度值,也可以是宽度值。 (AttributeValue 是一个对象,所以我得到一个表格,其中的值不应出现多次。)

标签: silverstripe


【解决方案1】:

首先,为了清楚起见,您可能应该复数您的 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 内容。

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

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

【讨论】:

  • 感谢您的快速回答,但不幸的是它对我没有帮助。我认为,您误解了我的情况,为了更清楚,我已经编辑了我的问题
  • 不,抱歉。你没有说得更清楚。基本上,我不知道您要达到什么目的。在您目前的设置中,您可以根据需要将所有内容存储在数据库中,因为矩形和类型之间存在关系,通过属性值。您不能将 Type 存储在 Rectangle 表中,因为 type 是属于属性值表的东西。那么,您要在哪个表中存储什么,以及 - 最重要的是 - 出于什么原因?
  • 好的,我有三个对象:矩形(box1),属性值(10英寸,20英寸,红色),属性(长度,宽度,颜色)。我要做的就是在 CMS 中的一个简单的 Silverstripe 网格字段中显示数据。我可以创建一个与 Rectangle 相关的 AttributeValues 的网格字段,但我也希望显示与 Values 相关的 Attributes。我不知道“Silverstripe 语言”中的表示法来获取间接相关对象的数据(-> 属性)
  • 但这就是我在回答的后半部分试图做的。它可能是复制粘贴(但未经测试),并将在摘要网格字段中添加一个额外的列。
  • 你能告诉我一个矩形最多有多少个属性吗?
【解决方案2】:

就个人而言,我不建议您采用这种方法,因为您将拥有一个 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-29
    • 1970-01-01
    • 2022-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多