Silverstripe:$ has_many汇总字段问题

Dal*_*lby 2 php silverstripe

我试图使用Has_many关系作为DataObject的摘要字段,似乎无法使其工作.

基本上:

  • 我有一张表格
  • 每个表单都有许多提交/条目
  • 每个表格都有很多字段
  • 每个领域都有很多答案.

我正在尝试在每个表单的后端管理区域中创建一个网格字段,显示每个表单的条目.

在条目的摘要字段中,我想显示创建的日期,以及该表单的前3个字段.

因此,例如,如果我们有一个带有姓名,电子邮件和电话字段的表单,汇总字段将如下所示:

  • 创建日期
  • 名称
  • 电子邮件
  • 电话

将相关的条目数据/响应作为条目的摘要信息.

这是我到目前为止所拥有的.这是形式:

<?php

class ContactBlock extends Block {
    private static $db = array(
        // Fields for the form/block go here
    );

    private static $has_many = array(
        'ContactBlockFields' => 'ContactBlockField',
        'ContactBlockEntries' => 'ContactBlockEntry' 
    );

    public function getCMSFields() {

       // Irrelevant code goes here!


        // CONTACT BLOCK ENTRIES
        $entriesInfo = new GridFieldDataColumns();
        $entriesInfo->setDisplayFields(singleton('ContactBlockEntry')->summaryFields());

        $entriesConfig = GridFieldConfig::create();
        $entriesConfig->addComponents(
            new GridFieldToolbarHeader(),
            new GridFieldAddNewButton('toolbar-header-right'),
            $entriesInfo,
            new GridFieldSortableHeader(),
            new GridFieldPaginator(50),
            new GridFieldEditButton(),
            new GridFieldDeleteAction(),
            new GridFieldDetailForm()
        );

        $entriesGrid = GridField::create('ContactBlockEntries', 'Form Entries', $this->ContactBlockEntries(), $entriesConfig);
        $fields->addFieldToTab('Root.FormEntries', $entriesGrid);

        return $fields;
    }

}
Run Code Online (Sandbox Code Playgroud)

这是Entry DataObject:

<?php

class ContactBlockEntry extends DataObject {

    private static $has_one = array(
        'ContactBlock' => 'ContactBlock'
    );

    private static $has_many = array(
        'ContactBlockFieldAnswers' => 'ContactBlockFieldAnswer',
    );

    private static $many_many = array(
        'FormFields' => 'ContactBlockField'
    );

    static $summary_fields = array(
        'Date'
    );

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

        //=== REMOVE FIELDS ====
        $fields->removeFieldFromTab('Root','FormFields');
        $fields->removeFieldFromTab('Root','ContactBlockFieldAnswers');
        $fields->removeFieldFromTab('Root.Main','ContactBlockID');
        //=== REMOVE FIELDS ====

        return $fields;
    }

    public function onBeforeDelete() {
        parent::onBeforeDelete();

        // Delete answers that are associated with this block.
        $data = ContactBlockFieldAnswer::get()
           ->filter('ContactBlockEntry', $this->ID);

        foreach( $data as $d) {
            $d->delete();
        }

    }

    public function getDate() {
        $date = date('d/m/Y',strtotime($this->Created));
        return $date;
    }

}
Run Code Online (Sandbox Code Playgroud)

这是字段代码:

<?php

class ContactBlockField extends DataObject {
    private static $db = array(
        'SortOrder' => 'Int',
        'FieldName' => 'Varchar',
        'FieldType' => 'Varchar',
        'DropdownValues' => 'Varchar(255)',
        'Label' => 'Varchar',
        'Placeholder' => 'Varchar',
        'Required' => 'Boolean'
    );

    private static $has_one = array(
        'ContactBlock' => 'ContactBlock',
    );

    private static $has_many = array(
        'ContactBlockFieldAnswer' => 'ContactBlockFieldAnswer',
    );

    private static $belongs_many_many = array(
        'Entries' => 'ContactBlockEntry'
    );

    static $searchable_fields = array(
        'FieldType',
        'FieldLabel',
        'Required'
    );

    static $summary_fields = array(
        'FieldType' => 'Field Type',
        'Label' => 'Field Label',
        'Required'  => 'Required Field?'
    );

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

          // Unrelated stuff here

        return $fields;
    }

}
Run Code Online (Sandbox Code Playgroud)

我似乎无法弄清楚如何获取列标签,以及它们在gridfield上显示的相关数据.任何帮助或建议将不胜感激.

更新24/3/17:

好的,我还有一点这个.在ContactBlockEntryDataObject上,在实现UncleCheese建议的更改后,我发现了以下内容:

public function getFirstField() {
        return $this->FormFields()->first();
    }

    public function getSecondField() {
        return $this->FormFields()->offsetGet(1);
    }

    public function getThirdField() {
        return $this->FormFields()->offsetGet(2);
    }

    public function summaryFields() {
        return [
            'Date'                      => 'Submitted',
            'Answers.First.Value'       => $this->getFirstField()->Label,
            'Answers.Second.Value'      => $this->getSecondField()->Label,
            'Answers.Third.Value'       => $this->getThirdField()->Label,
        ];
    }
Run Code Online (Sandbox Code Playgroud)

$this->getFirstField()->Label正在恢复[Notice] Trying to get property of non-object然而,当我回声/打印在getCMSFields此函数()可以看我的标签值.

Answers.First.Value作品.它返回在第一个字段中提交的值/答案.问题是,我似乎无法获得第二个和第三个值,因为我无法找出检索它们的方法.我尝试了offsetGet(),它说该方法不可用.

Unc*_*ese 5

在这种情况下,您可以定义一个summaryFields()方法来代替静态数组.这将允许您返回标题的计算值.

让事情复杂化的是获得价值观.前三个字段不是Entry对象的属性,因此您需要为Entry数据对象提供getter,以便将它们即时计算为"虚拟"属性.这有点笨拙,但这样的事情应该有效.

public function getFirstField()
{
    return $this->FormFields()->first();
}

public function getSecondField()
{
    return $this->FormFields()->offsetGet(1);
}

public function getThirdField()
{
    return $this->FormFields()->offsetGet(2);
}

public function summaryFields()
{
    return [
        'Created' => 'Created',
        'FirstField.Answer' => $this->getFirstField()->FieldName,
        'SecondField.Answer' => $this->getSecondField()->FieldName,
        'ThirdField.Answer' => $this->getThirdField()->FieldName,
    ];
}
Run Code Online (Sandbox Code Playgroud)

不过,我对你的数据模型不太了解.你has_many的场对象有答案.在这种情况下,您必须在Field对象上创建另一个getter,以便AnswerLabel将所有答案连接成一个字符串,或者只是获得第一个.无论您选择何种业务逻辑.只需FirstField.AnswerLabel在数组中使用等,或者您选择调用该方法的任何内容.关键是,您需要将多个关系解析为单个可读值.你如何做到这一点取决于你.