1

See: https://craftcms.com/docs/4.x/entries.html#descendantof

I want to create a field which allows to select all (direct) descendants of a certain entry (id=306), section type = structure.

My solution: {craft.entries().descendantOf(306).all()}

Result: I got all entries ... not only the wanted descendants ... but why?
I've no idea ... it should work - but it does not.

Further testing and tryout: A dump in a twig template works fine:
{% dump(craft.entries().descendantOf(306).all()) %}

Screenshots

Field configuration

enter image description here

Section

enter image description here

wrong result -> too many entries

enter image description here

2 Answers 2

2

Parent/child (aka ancestor/descendant) relationships aren't relations, which is what the "Related to" (and the relatedTo query param underpinning it) works with. In other words, it's not possible to create a "Related to" condition that does what you need it to.

Unfortunately, neither Craft 4 or 5 has a "Descendant of" condition type. Sounds like a valid feature request, though!

If you really want to pull this off, the only solution I can think of is to create a custom Yii module, with an event listener for the EVENT_DEFINE_SELECTION_CRITERIA event:

use yii\base\Event;
use craft\fields\BaseRelationField;
use craft\events\ElementCriteriaEvent;

Event::on(
    BaseRelationField::class,
    BaseRelationField::EVENT_DEFINE_SELECTION_CRITERIA,
    function (ElementCriteriaEvent $event) {
        $field = $event->sender;
        if ($field->handle !== 'entryFieldHandle') {
            return;
        }
        $event->criteria['descendantOf'] = 306;
    }
);

Finally, as general advice you should avoid hard coding entry IDs anywhere in your build. Entry IDs will typically vary between environments, so a better approach is to either use environment variables, or an entry query to find the proper entry without depending on a hard coded ID.

1
1

I see ... thanks a lot, Mats!

I modified your code a little bit (thanks to ChatGPT), now it works for multiple parent ids (Craft 4):

custom.php

[...]
'customParentIds' => [306, 556],
[...]

module

use yii\base\Event;
use craft\fields\BaseRelationField;
use craft\events\ElementCriteriaEvent;
use craft\elements\Entry;
use Craft;

Event::on(
    BaseRelationField::class,
    BaseRelationField::EVENT_DEFINE_SELECTION_CRITERIA,
    function (ElementCriteriaEvent $event) {
        $field = $event->sender;

        // check field handle
        if ($field->handle !== 'entryFieldHandle') {
            return;
        }

        // get customParentIds
        $parentIds = Craft::$app->config->custom->customParentIds;

        // merge descendant IDs
        $descendantIds = [];
        foreach ($parentIds as $parentId) {
            $descendants = Entry::find()->descendantOf($parentId)->level(2)->ids();
            $descendantIds = array_merge($descendantIds, $descendants);
        }

        // set the ID criteria for the event
        $event->criteria['id'] = $descendantIds;
    }
);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.