10

I'm developing a plugin which requires certain sections and fields to exist so I'm currently creating them in the onAfterInstall() method of the plugin.

I can create individual fields, sections, entry types and even a Matrix field + block type fine. I'm having trouble with creating the Matrix sub-field and attaching that field to the Matrix block type.

I have created the matrix field:

$field = new FieldModel();
$field->groupId      = $group->id;
$field->name         = Craft::t('Field Name');
$field->handle       = 'handleName';
$field->translatable = false;
$field->type         = 'Matrix';
craft()->fields->saveField($fieldContentRSS);

And this is the block type:

$blockType = new MatrixBlockTypeModel();
$blockType->fieldId = $field->id;
$blockType->name = Craft::t('Block Name');
$blockType->handle = 'handleName';
craft()->matrix->saveBlockType($blockType);

I know that I will need to create a field/set of fields for this block type. Is this exactly the same as the new field above? How do I then attach these fields to the block type?

9

Creating the field/block types manually is only part of the equation - you would also need to create the new content table for your Matrix field.

All you need to do is assign all of your block types and their sub-fields’ settings to $field->settings before calling saveField():

$field = new FieldModel();
$field->groupId      = 1;
$field->name         = Craft::t('Field Name');
$field->handle       = 'handleName';
$field->translatable = false;
$field->type         = 'Matrix';

$field->settings = array(
    'blockTypes' => array(
        'new1' => array(
            'name' => 'My Block Type 1',
            'handle' => 'myBlockType1',
            'fields' => array(
                'new1' => array(
                    'name' => 'My Sub-Field 1',
                    'handle' => 'mySubField1',
                    'required' => true,
                    'translatable' => false,
                    'type' => 'PlainText',
                    'typesettings' => array(
                        'multiline' => false,
                    )
                ),
                'new2' => array(
                    'name' => 'My Sub-Field 2',
                    'handle' => 'mySubField2',
                    'required' => false,
                    'translatable' => false,
                    'type' => 'PlainText',
                    'typesettings' => array(
                        'multiline' => true,
                    )
                ),
            )
        )
    )
);

craft()->fields->saveField($field);
  • Thanks Brandon! When I install the plugin, I get an CDbException on the SQL statement: Base table or view already exists: 1050 Table 'craft_matrixcontent_handlename' already exists. – Anthony Aug 7 '14 at 0:35
  • Well, try removing that DB table first ;) – Brandon Kelly Aug 7 '14 at 1:01
  • Yes I've tried that. Even with brand new unique handles, it throws the same error. It looks like the saveSettings method is trying to save the matrix field which was originally created with: craft()->fields->saveField($field); – Anthony Aug 7 '14 at 1:05
  • Any chance your code is getting run twice? – Brandon Kelly Aug 7 '14 at 1:19
  • I don't think so, my test is just a straight copy & paste of the 3 code blocks provided in the onAfterInstall method. – Anthony Aug 7 '14 at 1:27
4

I got the code working by using the following, without using the saveSettings method:

$field = new FieldModel();
$field->groupId      = 1;
$field->name         = Craft::t('Field Name');
$field->handle       = 'handleName';
$field->translatable = false;
$field->type         = 'Matrix';

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

$settings = new MatrixSettingsModel($field);

$blockType = new MatrixBlockTypeModel();
$blockType->fieldId = $field->id;
$blockType->name = Craft::t('blockTypeName');
$blockType->handle = 'blockTypeHandle';

$mySubField1 = new FieldModel();
$mySubField1->name         = 'My Sub-Field 1';
$mySubField1->handle       = 'mySubField1a';
$mySubField1->required     = true;
$mySubField1->translatable = false;
$mySubField1->type         = 'PlainText';
$mySubField1->settings     = array('multiline' => false);

$mySubField2 = new FieldModel();
$mySubField2->name         = 'My Sub-Field 2';
$mySubField2->handle       = 'mySubField2a';
$mySubField2->required     = true;
$mySubField2->translatable = false;
$mySubField2->type         = 'PlainText';
$mySubField2->settings     = array('multiline' => true);

$blockType->setFields(array($mySubField1, $mySubField2));

craft()->matrix->saveBlockType($blockType);
$settings->setBlockTypes(array($blockType));
$success = craft()->matrix->saveSettings($settings);
  • 1
    Yeah that would work as well. The MySQL error you were getting was because I forgot saveField() is already going to end up calling MatrixService::saveSettings() for you, which will create the content table, albeit without any actual columns yet. – Brandon Kelly Aug 7 '14 at 10:14
4

FYI, this is how it's done in Craft 3:

use craft\fields\Matrix;
use craft\fields\PlainText;

//Create the matrix field 
$field = Craft::$app->getFields()->createField([
    'type' => Matrix::class,
    'groupId' => 1,
    'name' => 'My Matrix Field',
    'handle' => 'myMatrixField',
    'settings' => array (
        'minBlocks' => '1',
        'maxBlocks' => '',
        'localizeBlocks' => false,
    )
]);

try {
    Craft::$app->getFields()->saveField($field);
}
catch (\Throwable $e){
    echo $e->getMessage();
}

//Set new block type(s) and add sub-fields to it
$field->setBlockTypes(array(
    'new1' => array(
        'name' => "A Block",
        'handle' => "aBlock",
        'fields' => array(
            'new1' => array(
                'type' => PlainText::class,
                'name' => 'First Subfield',
                'handle' => 'firstSubfield',
                'instructions' => '',
                'required' => false,
                'typesettings' => array (
                    'multiline' => ''
                )
            ) 
        )
    )
);

//Save field with new block type and sub-fields settings
try{
    Craft::$app->matrix->saveSettings($field);
}
catch(\Throwable $e){
    echo $this->failed;
}

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.