1

I am writing an importer that pulls from a separate MySQL database into Craft 3, and for the most part it's been quite simple to do.

However, I set myself up for some complication by having a Super Table field inside a Matrix field, which required some acrobatics to retrieve the field information to use when saving the entry.

The code below does work, but I wanted to check if it could be simpler, or if there are any obvious problems with this approach. It could also be helpful to someone else trying to achieve the same thing, as I didn't find anything similar when searching around.

// Get our "quotes" Super Table field (inside "mediaBlocks" matrix field)
if (empty($this->superTableQuotesField)) {
    $mediaBlockField = Craft::$app->getFields()->getFieldByHandle('mediaBlocks');
    $blockTypes = Craft::$app->getMatrix()->getBlockTypesByFieldId($mediaBlockField->id);
    foreach($blockTypes as $blockType) {
        if ($blockType->handle=='quotes') {
            $matrixFields = Craft::$app->fields->getFieldsByLayoutId($blockType->fieldLayoutId);
            // Cache this for future use
            $this->superTableQuotesField = SuperTable::$plugin->service->getBlockTypesByFieldId($matrixFields[0]->id);
        }
    }
}
// For some reason we couldn't find the Super Table field
if (empty($this->superTableQuotesField)) {
    Craft::warning('Could not find Super Table field for quotes in mediaBlocks!');
    return [];
}

$blockType = $this->superTableQuotesField[0]; // There will only ever be one SuperTable_BlockType

... then a for loop with $q++ on each item from the other db:

$related_quotes['new'.$q] = [
    'type' => $blockType->id,
    'fields' => [
        'quote'         => $quote,
        'personName'    => $personName,
        'personCompany' => $personCompany,
    ]
];

... and then if any found, merge with matrix array:

if (!empty($related_quotes)) {
    $i++;
    $media_blocks = array_merge(['new'.$i => [
        'type' => 'quotes',
        'fields' => [
            'quotes' => $related_quotes,
        ]
    ]], $media_blocks);
}

Is there a better way to do this?

Update:

For comparison, this is the (much simpler) code I'm using to find the $blockType for a Super Table field when it's not an embedded field:

// Get our Super Table field
$field = Craft::$app->getFields()->getFieldByHandle('quotes');
$blockTypes = SuperTable::$plugin->service->getBlockTypesByFieldId($field->id);
$blockType = $blockTypes[0];

... but since this is inside a Matrix field, it doesn't work.

Here's a snapshot of what the field looks like in CP:

quotes super table field in mediaBlock matrix field

  • Could you maybe explain the first code snipped? I don't really see why this is important or what it should be good for. You could use this as reference. It's without a super table field but they work similar craftcms.stackexchange.com/questions/21864/… – Robin Schambach May 23 '18 at 20:09
  • Sure, it is pretty confusing. I'm trying to find the $blockType for the Super Table field that's inside a Matrix field. It's much easier to just find this info for a base Super Table field (that's not inside a matrix field). I'm guessing there's a simpler way to find that $blockType, but the code block at top was the only way I was successful. – natebeaty May 23 '18 at 20:57
  • Are you going to change/delete your fields because that's what calling by handle is good for. You can as well grab the field by id directly. It's not as dynamic as your approach but yours won't work anymore when you change the layout as well – Robin Schambach May 23 '18 at 21:20
  • There aren't any plans to change fields, and I did initially just use the field ID by checking the database directly. I sent this issue to the Super Table devs also in case they wanted to chime in — I was just wondering if there was a more elegant way to find a Super Table's field info from inside a matrix field. – natebeaty May 24 '18 at 20:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.