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をコピーしました