#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 .