Снова возвращаемся к migrate. Довольно удобный фреймворк для импорта данных в Друпал.
Один из распространенных форматов источника для импорта - CSV. Поддерживается migrate из коробки. Описание и примеры работы с классом MigrateSourceCSV можно найти на d.org.
Есть один большой недостаток при импорте из CSV - подготовка файла для импорта:
- при сохранении в CSV из Excell Вы не получите необходимую нам кодировку utf-8;
- если в поле длинный текст (например, описание товара), то неодходимо перед сохранением заменить встречающиеся символы перевода строки, иначе можно получить вместо 5000 строк с товарами - 65000. Проверено на личном опыте...;
В принципе, в сети есть довольно много программ, для корректной конвертации из xls в csv c дополнительными опциями. Все решаемо :-) Осталось только научить "человека" подготавливать файлы для импорта...
Итак, давайте попробуем делать импорт прямо из xls.
Незнаю, может я просто разучился пользоваться поиском, но ничего путно найти не смог. День ходил, обдумывал возможные решения. Решил, что стоит написать свой плагин для migrate, так сказать, научить его считывать данные из xls. Начал изучать source-плагины "из коробки". И, о чудо - class MigrateSourceSpreadsheet. В принципе, на этом моменте можно закончить статью...
/** * @file * Define a MigrateSource for importing from spreadsheet files. * * Requires the PHPExcel library to be installed. * - Download PHPExcel at http://phpexcel.codeplex.com/. * - Extract the archive to a temporary folder. * - Ensure the hosting environment fulfills the requirements found in * install.txt. * - Copy the contents of the Classes folder to an appropriate location * (sites/all/libraries/PHPExcel). */
Данный класс работает с библиотекой PHPExcel.
Зависимости:
- Модуль libraries
- Модуль phpexcel. (Для справки - Описание API)
- Библиотека PHPExcel
Модуль phpexcel предоставляет API для работы с xls файлами в своих модулях. Кстати, в реализации класса MigrateSourceSpreadsheet я не увидел использования этих методов, но вот проверку на наличие данного модуля нашел. Возможно, это связано с настройками кеширования. Дело в том, что у библиотеки PHPExcel есть один известный недостаток - большое потребление памяти во время обработки файлов. Для решения этой проблемы были разработаны различные механизмы кеширования. Модуль phpexcel предоставляет возможность из админки сайта ('admin/config/system/phpexcel') менять режим кеширования.
Самый простой пример использования класса MigrateSourceSpreadsheet:
$this->source = new MigrateSourceSpreadsheet('путь к файлу xls или xlsx', 'имя листа');
В Вашем файле для импорта переименуйте лист в какое-то удобное название, например "import", в первой строке листа задайте имена колонкам на английском языке. Migrate считает эти имена и создат на их основе список полей, доступных для импорта.
class ProductsMigration extends Migration { public function __construct($arguments) { parent::__construct($arguments); $columns = array(); //Укажем, что в первой строке таблицы находятся заголовки //Данные заголовки станут ключами в массиве с данными $options = array( 'header_rows' => 1, ); //Имя листа $sheet_name = 'imp'; // $this->source = new MigrateSourceCSV('http://uber.new/import.csv', $columns, $options); $this->source = new MigrateSourceSpreadsheet(DRUPAL_ROOT . '/import.xlsx', $sheet_name, $columns, $options); // Destination $this->destination = new MigrateDestinationProductNode('product'); // Key schema $source_key_schema = array( 'model' => array( 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'description' => 'Source ID', ) ); $this->map = new MigrateSQLMap($this->machineName, $source_key_schema, MigrateDestinationProductNode::getKeySchema()); // Mapping $this->addFieldMapping('title', 'title'); $this->addFieldMapping('body', 'body')->defaultValue(NULL); $this->addFieldMapping('body:format')->defaultValue('full_html'); $this->addFieldMapping('status')->defaultValue(TRUE); $this->addFieldMapping('promote')->defaultValue(FALSE); $this->addFieldMapping('sticky')->defaultValue(FALSE); $this->addFieldMapping('uid')->defaultValue(1); $this->addFieldMapping('field_brand', 'brand')->separator(','); $this->addFieldMapping('field_brand:source_type')->defaultValue('name'); $this->addFieldMapping('field_brand:create_term')->defaultValue(TRUE); $this->addFieldMapping('taxonomy_catalog', 'catalog'); $this->addFieldMapping('taxonomy_catalog:source_type')->defaultValue('tid'); $this->addFieldMapping('taxonomy_catalog:create_term')->defaultValue(TRUE); $this->addFieldMapping('sell_price', 'price')->defaultValue(0); $this->addFieldMapping('model', 'model')->defaultValue(0); } }
Актуально для:
migrate7.x-2.8
Комментарии
HHвт, 14/06/2016 - 09:09 #1
Друг, объясни как это работает. Ничего не смог понять куда тут что?
Модули все поставил.
Пробовал тупо через девел код воткнуть (так можно?), не получилось. Ну, со своими настройками. Не знаю как там маппинг у меня дело в том что еще карточка товара а в ней виджет товара (исп. коммерц). Как они вообще, но все равно не получилось ни чего.
Можешь разжевать?
Frantsuzzzпт, 01/07/2016 - 00:49 #2
http://xandeadx.ru/blog/drupal/502
Тут подробнее описано, как использовать migrate. Нужно свой модуль создавать.
Пункт 2 - Реализация класса миграции. Сам класс миграции уже брать из моей статьи.
HHвт, 16/08/2016 - 11:38 #3
Приветствую! Спасибо за внимание.
Настроил импорт. Все поля импортируются кроме терминов таксономии (одноуровневого).
пробую настроить маппинг таким образом:
$this->addFieldMapping('taxonomy_p_group', 'p_group');
$this->addFieldMapping('taxonomy_p_group:source_type')->defaultValue('tid');
$this->addFieldMapping('taxonomy_p_group:create_term')->defaultValue(TRUE);
Если термин существует, он создает материал, но название термина кидает в описание.
Если термина не существует, выдает ошибку и материал не создает.
Не подскажите в чем проблема?
Frantsuzzzср, 17/08/2016 - 19:46 #4
Скорее всего в параметре source_type. Он указывает, что Вы подаете на входе. Можно передавать tid (номер термина) или name (имя термина).
Если Вы установили
$this->addFieldMapping('taxonomy_p_group:source_type')->defaultValue('tid');
то в источнике у Вас должны быть номера терминов....
Если передаете название, то должно быть указано:
$this->addFieldMapping('taxonomy_p_group:source_type')->defaultValue('name');
Уточните, какое значение для термина в источнике
Добавить комментарий