Создайте объект DataObject для построения строк и столбцов таблицы в SilverStripe

Я пытаюсь сделать что-то совсем другое для сайта SilverStripe: на нескольких подстраницах находятся таблицы данных, и у каждой из этих таблиц есть свой собственный набор заголовков столбцов, а в некоторых таблицах столбцов больше, чем в других. Я хочу избегать создания таблиц в Rich Text Editor, так как это подвержено множеству ошибок, и с течением времени это сложно поддерживать.

То, что я хотел бы сделать, это создать DataObject, который учитывает n-е число столбцов и n-е число соответствующих строк. Таким образом, я могу вызвать цикл (или, возможно, два) внутри шаблона, где у меня уже есть структура таблицы HTML. Менеджеры контента имеют полный контроль над тем, какие столбцы находятся в таблицах для любой заданной подстраницы, и им не нужно беспокоиться о поддержке настройки таблицы HTML.

У меня была пара идей, которые не дают желаемых результатов без: а) создания пользовательского интерфейса слишком сложным для контент-менеджеров и б) неспособности правильно связать столбцы со строками.

Я думал о создании объекта DataObject для заголовков таблиц и объекта для строк таблиц, но затем я был озадачен тем, как объединить их таким образом, чтобы это имело смысл, тем более что столбцов может быть сколько угодно.

Кто-нибудь есть какие-либо предложения по подходу к этому?

ОБНОВЛЕНИЕ: Хорошо, у меня есть кое-что для объекта данных TableRowItem, который может работать и близок к работе. Однако проблема заключается в следующем: как сохранить значения полей в базе данных, когда я создаю их в основном на лету? Как и сейчас, единственное поле, которое сохраняет в базу данных, - это поле загрузки файла PDF, все остальное стирается при нажатии "создать".

<?php

class TruckBodyPdfTableRowItem extends DataObject {

    private static $db = array(
    );

    // One-to-one relationship with gallery page
    private static $has_one = array(
        'TablePage'=> 'Page',
        'TableColumnSet' => 'TableColumnSet',
        'PDF' => 'File',
    );


    // tidy up the CMS by not showing these fields
    public function getCMSFields() {
        $fields = parent::getCMSFields();
        $fields->removeFieldFromTab("Root.Main","TablePageID");
        $fields->removeFieldFromTab("Root.Main","TableColumnSetID");
        $fields->removeFieldFromTab("Root.Main","SortOrder");
        $fields->addFieldsToTab("Root.Main", $this->getMyColumnOptions());

        return $fields;
    }
    public function getMyColumnOptions()
    {
        $columnArray = [];
        $Columns = DataObject::get('TableColumnSet');

        foreach($Columns as $Column){
          $columnArray[] = TextField::create($Column->TableColumnHeader);
        }

        return $columnArray;
    }

    // Tell the datagrid what fields to show in the table
    private static $summary_fields = array(
    );

    public function canEdit() {
        return true;
    }

    public function canDelete() {
        return true;
    }

    public function canCreate(){
        return true;
    }

    public function canPublish(){
        return true;
    }

    public function canView(){
        return true;
    }
}

Но это сложные моменты: выяснить, как отобразить значения из одного объекта DataObject в метки для другого, а затем автоматически сгенерировать n-е число строк на основе количества созданных столбцов.

<?php

class TablePage extends Page
{
    private static $db = array(
        'H1' => 'varchar(250)',
    );

    private static $has_many = array(
        'TableRowItems' => 'TableRowItem',
        'TableColumnSets' => 'TableColumnSet'
    );

    private static $has_one = array(

    );

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

        $fields->addFieldToTab("Root.Main", new TextField("H1"), "Content");

        $gridFieldConfig = GridFieldConfig_RecordEditor::create();

        $gridFieldConfig->getComponentByType('GridFieldDataColumns')->setDisplayFields(array(
            // field from drawer class => label in UI
            'TableColumnHeader' => 'Table Column Header'
        ));

        $gridfield = new GridField(
            "TableColumnSets",
            "Table Column Sets",
            $this->TableColumnSets(),
            $gridFieldConfig
        );

        $fields->addFieldToTab('Root.Specs Table', $gridfield);




        $gridFieldConfig2 = GridFieldConfig_RecordEditor::create();

        $gridFieldConfig2->getComponentByType('GridFieldDataColumns')->setDisplayFields(array(
            // field from drawer class => label in UI
            'TableRowValue' => 'Table Row Value'
        ));

        $gridfield2 = new GridField(
            "TableRowItems",
            "Table Row Items",
            $this->TableRowItems(),
            $gridFieldConfig2
        );
        $fields->addFieldToTab('Root.Specs Table', $gridfield2);



        return $fields;
    }
}

class TablePage_Controller extends Page_Controller
{
    private static $allowed_actions = array(

    );

    public function init()
    {
        parent::init();
        // You can include any CSS or JS required by your project here.
        // See: http://doc.silverstripe.org/framework/en/reference/requirements
    }
}

Вот классы TableColumnSet и TableRowValue. Я подумал, что будет один набор заголовков столбцов, связанных с n-м числом строк, поэтому я подумал, что будет $has_many связь между двумя классами, в которой TableColumnSet может иметь много TableRowValues, но для всех TableRowValues ​​будет только один TableColumnSet. Я надеялся связать TableRowValues ​​со значениями TableColumnSet, используя раскрывающийся список со всеми созданными заголовками столбцов, но это звучит как плохая идея. Необходимость вручную связывать каждое поле в строке с заголовками столбцов кажется утомительным и потенциально трудным для менеджеров контента.

<?php

class TableColumnSet extends DataObject {

    private static $db = array(
        'SortOrder' => 'Int',
        'TableColumnHeader'=>'varchar(250)'
    );

    // One-to-one relationship with gallery page
    private static $has_one = array(
        'TablePage'=> 'Page'
    );

    private static $has_many = array(
        'TableRowItems' => 'TableRowItem'
    );

    // tidy up the CMS by not showing these fields
    public function getCMSFields() {
        $fields = parent::getCMSFields();
        $fields->removeFieldFromTab("Root.Main","TablePageID");

        $fields->removeFieldFromTab("Root.Main","SortOrder");

        return $fields;
    }

    // Tell the datagrid what fields to show in the table
    private static $summary_fields = array(
        'TableColumnHeader' => 'Table Column Header',
    );

    public function canEdit() {
        return true;
    }

    public function canDelete() {
        return true;
    }

    public function canCreate(){
        return true;
    }

    public function canPublish(){
        return true;
    }

    public function canView(){
        return true;
    }
}

Я чувствую, что может быть что-то здесь, по крайней мере, в отношении отношений между заголовками столбцов и строками? Я не уверен, хотя.

1 ответ

Я мог бы быть вне базы здесь, так как у меня нет опыта с SilverStripe. Но... моё решение для таблиц PHP / HTML может применяться здесь:

<?php

// parse your table data into this structure
$tableData = array(
    "rowOne" => array(
        "columnName" => "columnValue1",
        "colName" => "colValue1"
        // .....
    ),
    "rowTwo" => array(
        "columnName" => "columnValue2",
        "colName" => "colValue2"
        // .....
    )
);

// now loop through the array with a printHeader parameter
$tableHTML = array(
    "<table>"
);
$tableHead = array(
    "<thead>"
);
$tableBody = array(
    "<tbody>"
);
$printHeader = true;

foreach ($tableData as $row) {
    foreach ($row as $column => $value) {
        $tableRow = "<tr>";
        if ($printHeader) {
            $tableHead[] = "<th>".$column."</th>";
        }
        $tableRow .= "<td>".$value."</td>";
    }
    $tableBody[] = $tableRow."</tr>";
    // after the first row, set printHeader to false and close the <thead>
    $printHeader = false;
    $tableHead[] = "</thead>";
}

 // implode table header to string with linebreaks
$tableHead = implode(PHP_EOL, $tableHead);

// close table <tbody> & implode to string with linebreaks
$tableBody[] = "</tbody>";
$tableBody = implode(PHP_EOL, $tableBody);

// add all table elements together
$tableHTML[] = $tableHead;
$tableHTML[] = $tableBody;
$tableHTML[] = "</table>";
// implode table array to string
$tableHTML = implode(PHP_EOL, $tableHTML);

// print or write anywhere
echo($tableHTML);

?>

Структура массива для всех шагов в цикле должна содержать очиститель памяти сервера по умолчанию для удаления старых данных. Если вы согласны ($var .= "string";) все как строки все ссылки будут храниться в памяти и отключаться от сервера при отображении больших таблиц. Я надеюсь, что это поможет

Другие вопросы по тегам