feed-me icon indicating copy to clipboard operation
feed-me copied to clipboard

When I import entries relationships, they are never fully saved

Open JayBox325 opened this issue 8 months ago • 4 comments

Description

I have imported some data that is adding a relationship in an entries field and it appears visually in the CMS, and I can save the entry and make changes etc, which is great.

However, unless I remove and re-add this entry manually, then save... this entries field is always returning empty.

Notice here, there is a selected byline, then the byline array is empty when I fetch it with GraphQL:

Image Image

Steps to reproduce

  1. Create a schema that adds a relationship to entries field
  2. Try to fetch this data in GQL
  3. See the array is empty
  4. Manually remove, re-add and save
  5. See the array is now populated

Additional info

  • Craft version: 5.6.15
  • Feedme version: 6.8.0

JayBox325 avatar Apr 09 '25 22:04 JayBox325

Hi, could you please provide more info on this?

You have an existing “Ryan Delaney back...” entry with a “Byline” Entries field. You’re updating that entry via Feed Me and adding an existing “Sam Morshead” entry to the “Byline” field. The import works as expected. Once imported, you’re querying for the “Ryan Delaney back...” entry via GQL and the “Byline” field is returning an empty array? Is that correct?

i-just avatar Apr 11 '25 13:04 i-just

Yeah, it's also when the original import happens too. The relationship visually looks to be in place in craft as you can see above, but when I query it in graphl, it never finds anything for that field, unless I remove it and re-save it. It's happening for all of them, which isn't ideal.

Image Image

But it works for other entries fields, such as category and tag.

JayBox325 avatar Apr 11 '25 15:04 JayBox325

Doing some digging, I have written a module that sets entry defaults on creation of a new entry.

So, an author sets their post defaults here:

Image

Then my module takes those values and applies them to new posts. It's an effort to save our authors from having to do the same things every time they create a new post. Here's the module if you're interest:

<?php

namespace defaultvalues;

use Craft;
use craft\elements\Entry;
use yii\base\Event;
use yii\base\ModelEvent;

class Module extends \yii\base\Module
{
    public function __construct(string $id, $parent = null, array $config = [])
    {
        Craft::setAlias('@defaultvalues', __DIR__);
        parent::__construct($id, $parent, $config);
    }

    public function init()
    {
        $this->controllerNamespace = 'defaultvalues\controllers';
        parent::init();

        Event::on(
            Entry::class,
            Entry::EVENT_BEFORE_VALIDATE,
            function (ModelEvent $event) {
                $entry = $event->sender;

                // ✅ Check if the entry is new or a draft
                if ($entry->section && (!$entry->id || $entry->getIsDraft())) {
                    // Craft::info( "Found entry: {$entry->section->handle}", __METHOD__);
                    // ✅ Ensure this only applies to "post" entry types
                    if ($entry->section->handle === 'posts') {
                        Craft::info("Applying default values to a post entry", __METHOD__);

                        $this->setDefaultsFromOutlet($entry);
                    } else {
                        Craft::info("Skipping default values: Entry is not a post (Section: {$entry->section->handle})", __METHOD__);
                    }
                }
            }
        );
    }

    private function setDefaultsFromOutlet(Entry $entry)
    {
        $entryTypeHandle = 'outletDefaults';
        $tagFieldHandle = 'tags';
        $sportFieldHandle = 'sports';
        $bylineFieldHandle = 'byline';

        // ✅ Log: Start processing
        Craft::info("Fetching default tags & sports for Entry ID: " . ($entry->id ?? 'NEW'), __METHOD__);

        // ✅ Fetch the `outletLanding` entry directly
        $outletEntry = Entry::find()
            ->type($entryTypeHandle)
            ->siteId($entry->siteId)
            ->one();

        if (!$outletEntry) {
            Craft::error("Outlet Landing entry not found for entry type: $entryTypeHandle in site ID: {$entry->siteId}", __METHOD__);
            return;
        }

        // ✅ Fetch default byline IDs from `outletLanding`
        $defaultBylineEntries = $outletEntry->getFieldValue('defaultByline')->all();
        $defaultBylineIds = array_map(fn($byline) => $byline instanceof Entry ? (int) $byline->id : null, $defaultBylineEntries);

        // ✅ Fetch default tag IDs from `outletLanding`
        $defaultTagEntries = $outletEntry->getFieldValue('defaultTags')->all();
        $defaultTagIds = array_map(fn($tag) => $tag instanceof Entry ? (int) $tag->id : null, $defaultTagEntries);

        // ✅ Fetch default sport IDs from `outletLanding`
        $defaultSportEntries = $outletEntry->getFieldValue('defaultSports')->all();
        $defaultSportIds = array_map(fn($sport) => $sport instanceof Entry ? (int) $sport->id : null, $defaultSportEntries);

        // ✅ Log: Found default IDs
        Craft::info("Default Tags (from Outlet): " . json_encode($defaultTagIds), __METHOD__);
        Craft::info("Default Sports (from Outlet): " . json_encode($defaultSportIds), __METHOD__);
        Craft::info("Default Byline (from Outlet): " . json_encode($defaultBylineIds), __METHOD__);

        // ✅ Apply default tags to the post
        if (!empty($defaultTagIds)) {
            $entry->setFieldValue($tagFieldHandle, $defaultTagIds);
            Craft::info("Applied Default Tags: " . json_encode($defaultTagIds), __METHOD__);
        }

        // ✅ Apply default sports to the post
        if (!empty($defaultSportIds)) {
            $entry->setFieldValue($sportFieldHandle, $defaultSportIds);
            Craft::info("Applied Default Sports: " . json_encode($defaultSportIds), __METHOD__);
        }

        // ✅ Apply default byline to the post
        if (!empty($defaultBylineIds)) {
            $entry->setFieldValue($bylineFieldHandle, $defaultBylineIds);
            Craft::info("Applied Default Byline: " . json_encode($defaultBylineIds), __METHOD__);
        }
    }

}

Could it that something happens with feedme data that my module wouldn't properly add the defaults? It works perfectly if I manually create a post, but just not with feed-me content.

JayBox325 avatar Apr 11 '25 15:04 JayBox325

Thanks for providing extra info, @JayBox325 and apologies for the delay.

The default byline entry that you’re adding via the module - does it actually exist on theMoonraker site?

i-just avatar Aug 12 '25 12:08 i-just