Craft CMS プラグインの作法(Matrixフィールド内にSuperTableフィールドがある場合の新規ブロック追加)

番外編。

Matrixフィールド内にSuperTableフィールドをレイアウトしている場合、プラグインから新規ブロックを追加するのが、結構わかりにくいです。

'sampleMatrix'フィールドに、'sampleBlock'というブロックがあり、そのブロックに'superTableField'というSuperTableフィールドがあるとします。
$matrix["new1"] = [
'type' => 'sampleBlock',
'enabled' => true,
'fields' => [
'textField' => 'abcdefg',
'numField' => 123456,
'superTableField' => [
'new1' => [
'type' => 0,
'enabled' => true,
'fields' => [
'columnOne' => 'sample one',
'columnTwo' => 'sample two',
],
],
],
],
];
$entry->setContentFromPost(array('sampleMatrix' => $matrix));
$success = craft()->entries->saveEntry($entry);
本当は、こう書きたいところですが、これではエラーになります…。
問題は、ブロック内のsuperTableFieldのtypeに設定するブロックタイプIDが決定していない点にあります。

ということで、ブロックタイプIDを取得するメソッドを作ってみます。
public function getSuperTableFieldId($ownerId, $matrixFieldHandle, $blockHandle, $tableFieldName) {
$criteria = craft()->elements->getCriteria(ElementType::MatrixBlock);
$criteria->ownerId = (int)$ownerId;
$criteria->type = $blockHandle;
$criteria->fieldId = (int)craft()->fields->getFieldByHandle($matrixFieldHandle)->id;
$blocks = $criteria->find();
if (!empty($blocks)) {
$blockTypes = craft()->superTable->getBlockTypesByFieldId($blocks[0]->$tableFieldName->fieldId);
if (!empty($blockTypes)) {
return $blockTypes[0]->id;
}
}
return false;
}
ただし、このメソッドはentryにmatrixブロックが1つ以上、存在する状態でないと機能しません。

以上を踏まえて、作成したメソッドを利用して新規ブロック追加をしてみます。
// 一旦superTableFieldは空にしておく
$matrix["new1"] = [
'type' => 'sampleBlock',
'enabled' => true,
'fields' => [
'textField' => 'abcdefg',
'numField' => 123456,
'superTableField' => [],
],
],
];

$entry->setContentFromPost(array('sampleMatrix' => $matrix));
// ブロックを追加するために、一旦保存
$success = craft()->entries->saveEntry($entry);

// superTableFieldを追加
$table["new1"] = [
'type' => $this->getSuperTableFieldId($entry->id, 'sampleMatrix', 'sampleBlock', 'superTableField'),
'enabled' => true,
'fields' => [
'columnOne' => 'sample one',
'columnTwo' => 'sample two',
],
];
$matrix['new1']['fields'][] = $table;

$entry->setContentFromPost(array('sampleMatrix' => $matrix));
$success = craft()->entries->saveEntry($entry);

一旦saveEntry()を実行してブロックを保存していますが、ブロックだけ更新するような場合は、MatrixServiceのsaveBlock()でも良いと思います。ただ、エントリーの他のフィールドも一緒に更新する場合は、saveEntry()でまとめて保存してしまったほうが良い気もするので、お好みで。
コメント
トラックバック
この記事のトラックバックURL