この問題のコメント#222にあるパッチ( https://drupal.org/node/1175082#comment-7625869 )を使用して、データを複数値フィールドコレクションに移行しようとしています。
PrepareRow()でオブジェクトの配列を作成しますが、移行が完了してノードを確認すると、配列の最初の項目のみがフィールドコレクションに入力されており、後続の項目は追加されていません。重要なものが欠けていますか?
<?php
class IngredientsMigration extends BasicMigration {
public function __construct($arguments) {
parent::__construct($arguments);
$this->description = t('Migrate recipe ingredients from the source database into field collections.');
$this->dependencies = array('Recipe');
$query = Database::getConnection('default', 'legacy')
->select('recipes', 'r')
->fields('r', array('id', 'ingredients'))
->condition('r.id', array(2), 'IN');
$this->source = new MigrateSourceSQL($query);
$this->destination = new MigrateDestinationFieldCollection(
'field_collection_ingredients',
array('Host_entity_type' => 'node')
);
$this->map = new MigrateSQLMap($this->machineName,
array(
'id' => array('type' => 'int',
'length' => 11,
'not null' => TRUE,
'description' => 'Recipe ID',
'alias' => 'r',
),
),
MigrateDestinationFieldCollection::getKeySchema()
);
$this->addFieldMapping('Host_entity_id', 'id')
->sourceMigration('Recipe')
->issueNumber(16);
$this->addFieldMapping('field_ingredient_text', 'ingredients')
->description(t('See prepareRow method'))
->issueNumber(16);
$this->addUnmigratedDestinations(array(
'path',
)
);
}
public function prepareRow($row) {
// Always include this fragment at the beginning of every prepareRow()
// implementation, so parent classes can ignore rows.
if (parent::prepareRow($row) === FALSE) {
return FALSE;
}
$ingredients_array = preg_split('/$\R?^/m', $row->ingredients);
$row->ingredients = array();
foreach ($ingredients_array as $ingredient) {
$row->ingredients[] = $ingredient;
}
return TRUE;
}
}
移行前に実行するDrushコマンドを記述して、ソースデータベースから「材料」フィールドを取得し、それぞれが独自の行とデルタ列に解析された状態で新しいテーブルを作成して、順序を維持しました。次に、レシピテーブルではなく、このテーブルを指すように食材の移行を設定しました。
この移行のための私のDB接続は、次のようになりました。
$query = Database::getConnection('default', 'legacy')
->select('_recipe_ingredients', 'i')
->fields('i', array('id', 'recipe_id', 'ingredient'))
->orderBy('i.recipe_id')
->orderBy('i.delta');
これを試すこともできます(この質問にも回答: フィールドコレクションへの移行 ):
もう1つのオプションは、complete
クラスのMigration
メソッドを実装し、プログラムでフィールドコレクションにデータを入力することです。
次のコードは、単一のフィールドコレクションアイテムをノードに保存します。
public function complete($entity, $row) {
// load the newly created node (just in case entity isn't fully populated).
$node = node_load($entity->nid);
// set the values of all field collection fields
$values = array(
'field_name' => 'FIELD_COLLECTION_ITEM_FIELD_NAME',
'field1' => array(LANGUAGE_NONE => array(array('value' => 'VALUE'))),
'field3' => array(LANGUAGE_NONE => array(array('value' => 'VALUE'))),
);
// create the field collection item entity
$item = entity_create('field_collection_item', $values);
// attach it to the node loaded above
$item->setHostEntity('node', $node);
// save the entity
$item->save();
}
これを変更して、複数のフィールドコレクション項目をかなり簡単に保存できます。
public function complete($entity, $row) {
// load the newly created node (just in case entity isn't fully populated).
$node = node_load($entity->nid);
// loop values to add as field collection items (assumes you have them in a $values array).
foreach ($values as $key => $value) {
// set the values of all field collection fields
$values = array(
'field_name' => 'FIELD_COLLECTION_ITEM_FIELD_NAME',
'field1' => array(LANGUAGE_NONE => array(array('value' => 'VALUE'))),
'field3' => array(LANGUAGE_NONE => array(array('value' => 'VALUE'))),
);
// create the field collection item entity
$item = entity_create('field_collection_item', $values);
// attach it to the node loaded above
$item->setHostEntity('node', $node);
// save the entity
$item->save();
}
}
[〜#〜]注[〜#〜]:フィールドコレクションアイテムにファイルを追加する場合、ファイルはロールバック時に削除されませんあなたはそれを明示的に行います。