Как поставщик данных формы администратора страницы CMS получает свои данные?
Короче говоря, длинная история:
Класс поставщика данных формы администратора страницы CMS Magento\Cms\Model\Page\DataProvider
, более конкретный метод getData
всегда возвращает массив с одним элементом, который содержит данные для страницы, которую я редактирую, а ключом элемента является идентификатор страницы.
Как это происходит? Где применяется фильтр по идентификатору страницы?
Короткий рассказ длинный:
На первый взгляд, какой метод Magento\Cms\Model\Page\DataProvider::getData
возврат не так очевиден.
В метод есть такая строка
$items = $this->collection->getItems();
И элемент коллекции var инициализируется в __construct
с помощью
$this->collection = $pageCollectionFactory->create();`
Где $pageCollectionFactory
является экземпляром Magento\Cms\Model\ResourceModel\Page\CollectionFactory
.
Итак, когда я впервые посмотрел, я подумал: "Какого черта он загружает полную коллекцию, если я редактирую только один элемент? Это не масштабируется".
При ближайшем рассмотрении я увидел, что коллекция возвращает один-единственный предмет. Тот, который я редактирую. Это хорошо, но как это работает?
Если я напечатаю запрос на сбор данных echo $this->collection->getSelect()
, я возвращайся
SELECT `main_table`.* FROM `cms_page` AS `main_table` WHERE (`main_table`.`page_id` = '2')
Где 2
- идентификатор страницы, которую я редактирую.
Теперь любопытная часть (если это было недостаточно любопытно) Если я создам свою собственную сущность, следуя тем же рекомендациям для класса поставщика данных, она будет работать так же. Я получаю обратно один-единственный предмет.
Это заставляет меня думать, что фильтрация происходит где-то выше в дереве наследования, но я понятия не имею, где?
Примечание: Пожалуйста, не объясняйте, как заставить это работать в моем пользовательском модуле. Я знаю, как это сделать. Я просто нужно объяснение того, как/почему/где происходит волшебство.
1 answers
/**
* {@inheritdoc}
*/
public function getDataSourceData()
{
$dataSource = [];
$id = $this->getContext()->getRequestParam($this->getContext()->getDataProvider()->getRequestFieldName(), null);
$filter = $this->filterBuilder->setField($this->getContext()->getDataProvider()->getPrimaryFieldName())
->setValue($id)
->create();
$this->getContext()->getDataProvider()
->addFilter($filter);
$data = $this->getContext()->getDataProvider()->getData();
if (isset($data[$id])) {
$dataSource = [
'data' => $data[$id]
];
} elseif (isset($data['items'])) {
foreach ($data['items'] as $item) {
if ($item[$item['id_field_name']] == $id) {
$dataSource = ['data' => ['general' => $item]];
}
}
}
return $dataSource;
}
Следующая строка - создать коллекцию как единый элемент
$this->getContext()->getDataProvider()
->addFilter($filter);
[Правка OP].
Трассировка такова:
- \Magento\Фреймворк\Представление\Элемент\Компонент\Тип содержимого\Json::визуализация()
- \Magento\Фреймворк\Представление\Элемент\Компонент\Контекст::getdatasourcedata()
- \Magento\Пользовательский интерфейс\Компонент\Форма::getdatasourcedata()