Skip to content

[4.x][5.x]: GQL potential naming conflicts for element interface field definitions #16862

@nfourtythree

Description

@nfourtythree

What happened?

Description

When defining field definitions for a GQL element interface there are potential naming conflicts that can arise based on the following code:

private function _getKnownSpecialEagerLoadNodes(): array
{
if (!isset($this->_additionalEagerLoadableNodes)) {
$list = [
'photo' => [UserField::class, 'canBeAliased' => false],
'addresses' => [UserField::class, 'canBeAliased' => true],
'author' => [EntryField::class, 'canBeAliased' => false],
'uploader' => [AssetField::class, 'canBeAliased' => false],
'parent' => [BaseRelationField::class, 'canBeAliased' => false],
'ancestors' => [BaseRelationField::class, 'canBeAliased' => false],
'children' => [BaseRelationField::class, 'canBeAliased' => true],
'descendants' => [BaseRelationField::class, 'canBeAliased' => false],
'currentRevision' => [BaseRelationField::class, 'canBeAliased' => false],
'draftCreator' => [BaseRelationField::class, 'canBeAliased' => false],
'drafts' => [BaseRelationField::class, 'canBeAliased' => false],
'revisions' => [BaseRelationField::class, 'canBeAliased' => false],
'revisionCreator' => [BaseRelationField::class, 'canBeAliased' => false],
self::LOCALIZED_NODENAME => [CategoryField::class, EntryField::class],
];
// Fire a 'registerGqlEagerLoadableFields' event
if ($this->hasEventHandlers(self::EVENT_REGISTER_GQL_EAGERLOADABLE_FIELDS)) {
$event = new RegisterGqlEagerLoadableFields(['fieldList' => $list]);
$this->trigger(self::EVENT_REGISTER_GQL_EAGERLOADABLE_FIELDS, $event);
$list = $event->fieldList;
}
$this->_additionalEagerLoadableNodes = $list;
}
return $this->_additionalEagerLoadableNodes;
}

This set of names defined by both Craft and anyone using the event can cause issues.

As an example photo is defined in the list. If you were to create a new element interface that had a field called photo that used a getter (getPhoto()) and should simply return a string, the naming conflict here would head down a path of trying to get data from eager loading and eventually return null.

This is in part due to the following call which routes through the __get() method.

$result = $source->$fieldName;

Craft CMS version

4.x/5.x

PHP version

No response

Operating system and version

No response

Database type and version

No response

Image driver and version

No response

Installed plugins and versions

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions