silverstripe 4.7 — manymanyextrafields — как их использовать?

#php #many-to-many #silverstripe-4

#php #многие ко многим #silverstripe-4

Вопрос:

у меня есть класс «Product» и класс «MaterialOrder». Они разделяют отношение many_many, в котором Продукты в MaterialOrder имеют дополнительные поля «PriceSum» и «Количество». Таким образом, теоретически кто-то должен иметь возможность заказать что-то, где он видит список всех активных продуктов с полем ввода для каждой записи, чтобы определить, сколько товаров он хочет. После нажатия create он должен создать новую запись materialorder с текущей суммой цен и определенным количеством.

Теперь я ничего не могу найти, как правильно получить доступ к этим дополнительным полям, и я понятия не имею, как добавить поле ввода в поле сетки, чтобы затем защитить новый объект materialorder с информацией…

MaterialOrder.php

 <?php

use SilverStripeORMDataObject;
use SilverStripeSecurityMember;
use SilverStripeFormsCurrencyField;
use SilverStripeFormsDropdownField;
use SilverStripeFormsFieldList;
use SilverStripeFormsTabSet;
use SilverStripeFormsTextField;
use SilverStripeFormsCheckboxField;
use SilverStripeFormsGridFieldGridField;

class MaterialOrder extends DataObject
{
    private static $db = [
        "LastReminder" => "Date",
        "IsOrdered" => "Boolean",
        "IsPaid" => "Boolean"
    ];

    private static $has_one = [
        "Member" => Member::class
    ];

    private static $many_many = [
        "Products" => Product::class
    ];

    private static $many_many_extraFields = [
        "Products" => [
            "PriceSum" => "Currency",
            "Quantity" => "Int"
        ]
    ];

    public function getCMSfields()
    {
        $fields = FieldList::create(TabSet::create("Root"));
        $fields->addFieldsToTab("Root.Main", [
            $grid = GridField::create("Products", "Products", Product::getAllProducts(true))
        ]);

        // GridField configuration
        $config = $grid->getConfig();

        return $fields;
    }
}
 

Product.php

 <?php

use SilverStripeAssetAdminFormsUploadField;
use SilverStripeAssetsImage;
use SilverStripeFormsCheckboxField;
use SilverStripeFormsCurrencyField;
use SilverStripeFormsDropdownField;
use SilverStripeFormsFieldList;
use SilverStripeFormsTabSet;
use SilverStripeFormsTextField;
use SilverStripeORMDataObject;

class Product extends DataObject
{

    private static $db = [
        "Name" => "Varchar",
        "Price" => "Currency",
        "IsActive" => "Boolean",
    ];

    private static $has_one = [
        "Category" => Category::class,
        "Image" => Image::class,
    ];

    private static $belongs_many_many = [
        "MaterialOrders" => MaterialOrder::class,
    ];

    private static $summary_fields = array(
        "IsActive" => "Is active?",
        "Name" => "Name",
        "Category.Title" => "Category",
        "Price" => "Price",
    );

    public function getCMSfields()
    {
        $fields = FieldList::create(TabSet::create("Root"));
        $fields->addFieldsToTab("Root.Main", [
            CheckboxField::create("IsActive", "Is active?"),
            TextField::create("Name"),
            CurrencyField::create("Price", "Price (per piece)"),
            DropdownField::create("CategoryID", "Category")
                ->setSource(Category::get()->map("ID", "Title")),
            $upload = UploadField::create(
                "Image",
                "Product image"
            ),
        ]);

        $upload->getValidator()->setAllowedExtensions(array(
            "png", "jpeg", "jpg", "gif",
        ));
        $upload->setFolderName("product-images");

        return $fields;
    }

    public static function getAllProducts($filterValue = null)
    {
        $products = Product::get();
        if (!is_null($filterValue)) {
            $products = $products->filter(["IsActive" => $filterValue]);
        }

        return $products->sort("Name");
    }
}
 

Ответ №1:

У меня была эта проблема некоторое время назад, и я написал об этом в своем блоге.

В вашем случае вы должны добавить MaterialOrder::getCMSields() что-то вроде

     $detailFormComponent = $grid->getConfig()->getComponentByType(GridFieldDetailForm::class);
        $detailFormComponent->setItemEditFormCallback(function ($form, $itemrequest) {
            $record = $itemrequest->record;
            $priceField = CurrencyField::create('ManyMany[Price]', 'Price (per piece)', $record->Price);
            $form->Fields()->add($priceField);
        });
 

для редактирования множества полей в форме deatail.

Мы получаем компонент GridFieldDetailForm конфигурации поля grid и изменяем его, добавляя поле в CMSFields MaterialOrder. С помощью метода setItemEditFormCallback() мы можем добавить анонимную функцию для добавления необходимых полей. Многие дополнительные поля сохраняются с использованием синтаксиса ManyMany[FieldName] , поэтому нам нужно ManyMany[Price] в качестве имени поля; нам также нужно получить текущее значение из $itemrequest->record .