4

I am easily able to add a Matrix. I am also easily able to add a BlockType to that matrix. → I am fine so far.

But I have no clue what I am missing when I try to add fields to my blocks using the following example (excerpt from a custom plugin).

/**
 * Performs any actions that should occur after the plugin is installed.
 */
public function onAfterInstall() {
    //  create new group
    $fieldGroup = new FieldGroupModel();
    $fieldGroup->name = 'Awesome Field Group';
    //  save group
    craft()->fields->saveGroup($fieldGroup);

    //  create matrix field
    $matrixField = new FieldModel();
    $matrixField->handle = 'myMatrixField';
    $matrixField->name = 'Awesome Matrix';
    $matrixField->type = 'Matrix';
    $matrixField->required = true;
    $matrixField->translatable = true;
    $matrixField->groupId = $fieldGroup->id;
    //  save matrix field
    craft()->fields->saveField($matrixField);

    //  create block type
    $blockType = new MatrixBlockTypeModel();
    $blockType->handle = 'myAwesomeBlock';
    $blockType->name = 'Awesome Block';
    $blockType->fieldId = $matrixField->id; //  also craft()->fields->getFieldByHandle('myMatrixField') possible

    //  save it
    if (craft()->matrix->saveBlockType($blockType)) {

        //  UNTIL HERE EVERYTHING WORKS PRETTY FINE.

        //  on saveField() in fields service the given field's context value is ignored because it's overwritten with "craft()->content->fieldContext"
        //  so, after saving the field's context is "global", but we want something like "matrixBlockType:<id>"
        //  --> temporarily change this value to ensure we cann passe the block type id
        $tmp = craft()->content->fieldContext;
        craft()->content->fieldContext = 'matrixBlockType:' . $blockType->id;

        //  create field
        $field = new FieldModel();
        $field->handle = 'myTestField';
        $field->name = 'Awesome Field';
        $field->type = 'PlainText';
        $field->required = true;
        $field->translatable = true;
        //$field->context = 'matrixBlockType:' . $blockType->id;
        //  … last line is commented out because Craft ignores this value --> see implementation of FieldsService::saveField();

        //  save field
        craft()->fields->saveField($field);

        //  FIELD IS ADDED TO DATABASE BUT I CAN'T SEE IT IN MY MATRIX BLOCK

        //  restore original value of "craft()->content->fieldContext"
        craft()->content->fieldContext = $tmp;
    }
}

I hoped this is enough to add fields to block types. But as you can see in the screenshot below my "Awesome Field" is missing. :(

field is missing for block

When adding this field manually in Craft's admin panel the field definitions in my database look exactly the same. So, any other important step is missing here. I have no idea which one.

What do I have to do to add fields to matrix blocks?

I hope someone can lead me into the right direction. Thanks in advance. :)

2

I'm assuming that you're attempting to create the Matrix, with one or more blocks each containing one or more fields, from scratch? I.e. you're not simply trying to populate content into an already defined Matrix?

Going off of that assumption:

PS: Sorry, this code is not based on your code - I simply took working code from one of my other projects.

// Create a field-group to store our Matrix in
$fieldGroup       = new FieldGroupModel();
$fieldGroup->name = 'My Field Group';
craft()->fields->saveGroup($fieldGroup);

// Create the matrix-field itself
$field          = new FieldModel();
$field->groupId = $fieldGroup->getAttribute('id');
$field->name    = 'My Matrix';
$field->handle  = 'myMatrix';
$field->type    = 'Matrix';

// Create a rich-text field which we will need later
$textField = ['name' => 'Text Field',
              'handle'       => 'label',
              'required'     => TRUE,
              'instructions' => '',
              'type'         => 'RichText',
              'typesettings' => ['configFile'            => 'Standard.json',
                                 'cleanupHtml'           => 1,
                                 'purifyHtml'            => 1,
                                 'columnType'            => 'text',          
                                 'availableAssetSources' => '',
                                 'availableTransforms'   => '']];

// Define block-types for our Matrix-field
$blockTypes = ['new1' => ['name'   => 'My text field',
                          'handle' => 'myTextField',
                          'fields' => ['new1' => $textField]];

// Assign block-types to the Matrix-field
$field->settings = ['blockTypes' => $blockTypes];

// Finish the creation of the Matrix-field by saving it
craft()->fields->saveField($field)

I've had to adjust the code slightly to not give you the full 125 lines of code I use (mostly due to having a LOT of different block-types with a lot of different fields) - but hopefully you can get the gist of how it's working and solve your issue based on this :)

PPS: It seems like your code should work fine if you only tweak the order in which you do things slightly.

  1. Create Field Group
  2. Create Matrix Field
  3. Define Block Fields
  4. Create Block Types using defined Block Fields
  5. Assign Block Types to Matrix Field
  6. Save Matrix Field
| improve this answer | |

Your Answer

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

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