Рейтинг:2

Как использовать значения ссылочного объекта в TableSort?

флаг ai

У меня есть пользовательский объект с полем, которое определяется следующим образом.

$fields['файл'] = BaseFieldDefinition::create('файл')
  ->setDescription('Ссылка на встроенный основной тип объекта File.')
  ->setLabel('Файл')
  -> setRequired (ИСТИНА)
  ->setSetting('file_extensions', 'pdf rtf doc docx')
  ->setSetting('max_filesize', '20MB')
  ->setSetting('поле_описания', ИСТИНА)
  ->setDisplayOptions('форма', ['тип' => 'файл'])
  ->setDisplayOptions('вид', ['тип' => 'файл']);

У меня нет проблем с доступом к полям ссылки Файл сущность из экземпляров моего собственного типа сущности. Так, например, эти строки работают как положено.

$filename = $my_entity->file->entity->filename->value;
$username = $my_entity->file->entity->uid->entity->name->value;

Когда я пытаюсь использовать поля указанного Файл сущность с Сортировка таблицы, который я хочу подключить к запросу объекта для моего пользовательского типа объекта, код выдает исключение.

$ заголовок ['имя'] = [
  'данные' => 'Имя файла',
  'поле' => 'file.entity.filename',
  'specifier' => 'file.entity.filename',
];
$ заголовок ['пользователь'] = [
  'данные' => 'Кем загружено',
  'поле' => 'файл.entity.uid.entity.name',
  'specifier' => 'file.entity.uid.entity.name',
];

// ¦

$запрос->tableSort($заголовок);

Неперехваченное исключение PHP Drupal\Core\Entity\Query\QueryException: «файл не найден»

Для синтаксиса $ заголовок массив я в основном полагаюсь на подсказки, которые я получил от Сортировка таблиц с EntityQuery, в котором Бердир рекомендует взглянуть на нагрузка() и построитьЗаголовок() методы UserListBuilder учебный класс. К сожалению, этот пример, похоже, использует значения полей, которые хранятся непосредственно в базовой таблице, поэтому я возвращаюсь к предположению, что, поскольку мы находимся в области запросов сущностей, тот же синтаксис, описанный в QueryInterface::условие() можно было бы ожидать.

Я просмотрел ряд открытых вопросов, таких как Сортировка таблицы игнорирует «поле», всегда добавляет заголовок в качестве параметра запроса заказа и Очистка таблицы, но я не видел ничего, что пролило бы свет на проблему.

флаг cn
Он определенно поддерживается с синтаксисом, который вы используете, так как он отлично работает для узлов, использующих, например. uid.entity.name в качестве спецификатора. Были ли у вас проблемы с установкой этого файлового поля? Или, может быть, изменили его после установки? Поменял кардинальность, что-то в этом роде?
флаг ai
@Clive - никаких проблем с установкой поля, и в его конфигурацию не вносились никакие изменения. Я могу прекрасно заполнить поле при создании или обновлении сущностей и могу получить доступ к любому из свойств поля, используя стандартный синтаксис доступа к полям сущностей. Должен ли я подать отчет об ошибке (с репро-кейсом), как вы думаете?
флаг cn
Я не уверен, что это ошибка или что-то недокументированное, есть синтаксис, который работает для полей базового файла. Я вставил ответ, но, надеюсь, обновлю его, когда у меня будет время, чтобы узнать больше.
флаг ai
@Clive - Прежде всего, я _очень_ впечатлен тем, что ты это понял. Я обновил свой [отчет об ошибке] (https://www.drupal.org/project/drupal/issues/3278083), чтобы отразить эту новую информацию. Краткая версия: это ошибка в документации или программном обеспечении, и я полагаю, что можно привести более веские доводы в пользу того, чтобы программное обеспечение соответствовало синтаксису, документированному в настоящее время для _любого_ основного типа поля ссылки. Я принимаю ваш блестящий ответ еще до того, как вы успели его обновить.
Рейтинг:2
флаг cn

В ядре есть ошибка, и на данный момент есть обходной путь:

'specifier' => 'file.target_id.entity.filename',

Причина этого заключается в том, что синтаксис отношения запросов к объектам начинался как поддержка соединения, он предшествует поддержке ссылок на объекты в ядре и, как таковой, в то время как $entity->file->target_id->entity не поддерживается ядром, file.target_id.entity поддерживается запросом объекта, чтобы указать, что он должен присоединиться к объекту, указанному файл поле и идентификатор объекта должны быть такими, как указано target_id. Это немного неуклюже, но в то время это было то, что работало.

Это должен быть в состоянии выяснить file.entity.filename а также потому, что имя основного свойства для файл поле оказывается target_id и поэтому он может расширить его для вас в file.target_id.entity.filename. Однако класс в случае Drupal\Core\Entity\Query\Sql\Tables чрезвычайно запутан, и в этом расширении есть ошибка для случая с общей таблицей, которая будет исправлена ​​в https://www.drupal.org/project/drupal/issues/3278083

флаг ai
То есть вы предлагаете исправить документацию, а не код? Будет не в первый раз.
флаг ai
Я принимаю ваш отличный ответ, хотя я не уверен, что понимаю, что вы имеете в виду в своем объяснении.У меня есть бесчисленное множество примеров ссылочных условий сущности в запросах сущностей, которые полагаются на поле ссылки, хранящееся в базовой таблице, и они отлично работают с задокументированным синтаксисом.
флаг cn
Да, ссылка на ванильную сущность в качестве базового поля работает, как и следовало ожидать. Если бы я делал ставки, не глядя должным образом, я бы сказал, что это, вероятно, потому, что базовое поле ссылки на сущность имеет только один столбец БД (`target_id`), поэтому не было бы необходимости в синтаксисе для поддержки «подполей». "; можно сделать вывод о столбце `fieldname__target_id` (кстати, подполя, вероятно, НЕ являются официальным термином :)). Поля файла имеют 3 столбца БД, поэтому в запросах необходимо явно указать, какой столбец `file__*` в базовой таблице необходимо использовать, отсюда и другой синтаксис. Хотя может быть что-то еще
флаг cn
Нашел - `DefaultTableMapping::getFieldColumnName()` - это дымящийся пистолет. Если поле имеет только один столбец, его имя столбца БД является именем поля. Таким образом, поле ссылки на объект с идентификатором «uid» имеет столбец БД с именем «uid». Когда вы запрашиваете `uid.entity.*`, есть прямое совпадение с именем столбца БД, и все в порядке. Когда поле имеет более одного столбца, столбцы БД называются `fieldname__property_name`, поэтому, когда вы запрашиваете `fieldname.entity`, нет соответствующего столбца `fieldname` БД. Расширенный синтаксис восполняет этот пробел и позволяет выбрать правильный столбец.
флаг ai
Спасибо за эту прекрасную спелеологию. Я включу ссылку на эту страницу из отчета об ошибке.
Smartsheet eng avatar
флаг um
Это обходной путь, который работает, но не является причиной того, что `fieldname.entity.propertyname` не работает. Причина в том, что если 1) поле с несколькими столбцами 2) хранится в общей таблице 3) и используется в запросе, где спецификаторы следуют за именем поля, тогда код отображения таблицы вообще не вызывается. Ошибка в таблицах. Я оставил ответ и подал патч. Кроме того, «система просто не знает, что это за файл». оно точно знает, это поле. Код просто не вызывает $sql_column = $table_mapping->getFieldColumnName($field_storage, $column); это очень редкий пограничный случай.
флаг cn
@Smartsheeteng Действительно, ошибка может легко быть причиной того, что _система просто не знает, что такое файл_ в этот момент (чего нет, сопоставления таблиц не содержат `файл`, они содержат `файл__*`)
Smartsheet eng avatar
флаг um
@Clive система знает, что такое файл, это поле. Вы смотрите не на тот класс, ошибка в таблицах, а не в классе сопоставления. Сама ошибка в том, что класс не вызывается в первую очередь для этого спецификатора. Этот ответ совершенно неверен, я отредактирую его и удалю свой, потому что он лишний.
флаг cn
@Smartsheeteng Я не знал, что вы написали исходный код, так что честно, ответ отредактирован
Рейтинг:1
флаг ai

Описанный выше сбой, по-видимому, является результатом ошибка в ФайлЭлемент плагин. Несмотря на то, что плагин типа поля претензии это ссылка на объект ( @FieldType аннотация говорит категория = @Translation("Ссылка")), а во всем остальном, что верно, поддержка документированный синтаксис запроса сущности сломан.

Пока ошибка не будет исправлена, обходным путем будет отказ от специализации, реализованной в ФайлЭлемент тип поля и используйте простой entity_reference вместо этого поле. При этом измените Сортировка таблицы код выше работает правильно.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.