• Like
Импорт данных с фреймворком Migrate. Владислав Богатырев.
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

Импорт данных с фреймворком Migrate. Владислав Богатырев.

  • 1,254 views
Published

 

Published in Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
1,254
On SlideShare
0
From Embeds
0
Number of Embeds
1

Actions

Shares
Downloads
12
Comments
0
Likes
0

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Импорт данных с фреймворком Migrate Владислав Богатырев http://donetsk.drupal.ua
  • 2. Импорт данных с фреймворком Migrate Владислав Богатырев Ноябрь 2011
  • 3. Задача доклада
      • С какими проблемами я столкнусь при миграции данных на Drupal7?
      • Что из это может решить Migrate?
      • Использовать ли Migrate ?
  • 4. Структура доклада
      • Задача, что мигрируем.
      • Проблемы
      • Выбор платформы.
      • Что такое Migrate.
      • Пример кода миграции.
      • Миграция множественных значений и сложных полей.
      • Сохранение связей при изменении ИД элементов.
      • Что еще может Migrate
    •  
    •  
    •  
  • 5. Задача
    • Из некоторой структуры данных, (обычно это CMS на основе БД), скопировать в Drupal набор объектов.
    • Обычный набор, это :
      • ноды с их набором артибутов
      • термины таксономии
      • пользователи
      • комментарии
      • файлы
      • другие данные, как например оценки контента пользователями
      • связи между всем перечисленным
    •                                                                 Это значит, что ...
  • 6. Проблемы
    • - вам нужно изучить внутреннюю структуру старой БД
    • (скорее всего данные будут разбросаны по разным таблицам)
    • - вам нужно знать API Drupal и выполнять импорт через него.
    • - почти наверняка потребуется знание структуры хранения данных в Drupal
    • - вам нужно написать код по копированию данных
    • - вам нужно знать как изменились ИД объектов для сохранение связей
    • - возможно, вы захотите использовать Batch API 
  • 7. Решение Это же Drupal!  Давайте используем модуль для этого!
      • Feeds http://drupal.org/project/feeds  
      • Десятки плагинов для Feeds -)
      • Node Export (dev) http://drupal.org/project/node_export
      • Wordpress Migrate  http://drupal.org/project/wordpress_migrate
      • Joomla to Drupal http://drupal.org/project/joomla
      • phpBB2Drupal (dev) http://drupal.org/project/phpbb2drupal  
      • Blogger Importer http://drupal.org/project/blogger_importer   
      • TYPO3_migrate http://drupal.org/project/TYPO3_migrate
      • Migrate http://drupal.org/project/migrate  
  • 8. Migrate (7.x-2.2)
    • - вся работа происходит в коде, это фреймворк
    • - любой источник данных*
    • - любая entity назначения*
    • - работает с любыми полями*
    • - умеет переводить старые ИД в новые
    • - хорошая документация
    • - ООП
    • - много дополнительных классов на DO
    • - Кое в чем может помочь migrate_extras
    • * но иногда для этого придется определить свой класс :)
  • 9. Как выглядит Migrate
    • Немного вот так:
  • 10. Как выглядит Migrate
    • Но в основном так:
  • 11. Начало работы
    • 1. Устанавливаем модули: migrate, migrate_ui
    •  
    • 2. Создаем свой модуль: 
    3. Добавляем .inc файлы где будет располагаться код для миграции.  
        • /*
        •   * You must implement hook_migrate_api(), setting the API level to 2, for
        •   * your migration classes to be recognized by the Migrate module.
        •   */
        • function  migrate_example_migrate_api ()   {
        •    $api   =   array (
        •      'api'   =>   2 ,
        •    ) ;
        •    return   $api ;
        • }
        •  
    •  
  • 12. Пример. Миграция нод.
        • abstract  class  BasicExampleMigration  extends  Migration  {
        •    public   function  __construct ()   {
        •    
        •     parent :: __construct () ;
        •  
        •      $this -> team   =   array (
        •        new  MigrateTeamMember ( 'Liz Taster' ,   'ltaster@example.com' ,  t ( 'Product Owner' )) ,
        •        new  MigrateTeamMember ( 'Larry Brewer' ,   'lbrewer@example.com' ,  t ( 'Implementor' )) ,
        •      ) ;
        •  
        •      $this -> issuePattern   =   'http://drupal.org/node/:id:' ;
        •    }
        • }
        •  
    Определяем базовый класс с общими атрибутами и методами.
  • 13. Пример. Миграция нод.
        • class  BeerNodeMigration  extends  BasicExampleMigration  {
        •    public   function  __construct ()   {
        •     parent :: __construct () ;
        •      $this -> description   =  t ( 'Beers of the world' ) ;
        •      $this -> dependencies   =   array ( 'BeerTerm' ,   'BeerUser' ) ;
        •  
        •      // карта старых и новых ИД мигрируемых объектов
        •      $this -> map   =   new  MigrateSQLMap ( $this -> machineName ,
        •        array (
        •          'bid'   =>   array (
        •            'type'   =>   'int' ,
        •            'not null'   =>   TRUE ,
        •            'description'   =>   'Beer ID.' ,
        •            'alias'   =>   'b' ,
        •          )
        •        ) ,
        •       MigrateDestinationNode :: getKeySchema ()
        •      ) ;
        •  
        •    
    Класс миграции нод. (Начало)
  • 14.
      •  
      •      // объект выборки данных из источника
      •      $query   =  db_select ( 'migrate_example_beer_node' ,   'b' )
      •               -> fields ( 'b' ,   array ( 'bid' ,   'name' ,   ... )) ;
      •      $query ->...
      •  
      •      // определяем атрибут класса - источник данных
      •      $this -> source   =   new  MigrateSourceSQL ( $query ) ;
      •  
      •      // определяем атрибут класса - объект назначения данных
      •      $this -> destination   =   new  MigrateDestinationNode ( 'migrate_example_beer' ) ;
      •  
      •      // связываем поля источника и назначения
      •      $this -> addFieldMapping ( 'title' ,   'name' )
      •           -> description ( t ( 'Mapping beer name in source to node title' )) ;
      •    
      •      // другие простые поля определяются аналогично
      •      ...
      •  
      •    }
      • }
      •  
    Пример. Миграция нод. Класс миграции нод. (конец)
  • 15.
        • class  BeerUserMigration  extends  BasicExampleMigration  {
        •    public   function  __construct ()   {
        •     parent :: __construct () ;
        •      $this -> description   =  t ( 'Beer Drinkers of the world' ) ;
        •      $this -> map   =   new  MigrateSQLMap ( $this -> machineName ,
        •          array ( 'aid'   =>   array (
        •                  'type'   =>   'int' ,
        •                  'not null'   =>   TRUE ,
        •                  'description'   =>   'Account ID.'
        •                  )
        •               ) ,
        •         MigrateDestinationUser :: getKeySchema ()
        •      ) ;
        •  
        •      // объект выборки данных из источника
        •      $query   =  db_select ( 'migrate_example_beer_account' ,   'mea' )
        •      -> fields ( 'mea' ,   array ( 'aid' ,   'status' ,   'posted' ,   'name' ,   'nickname' ,   ... )) ;
        •    
        •      // определяем атрибут класса - источник данных
        •      $this -> source   =   new  MigrateSourceSQL ( $query ) ;
        •    
        •      // определяем атрибут класса - объект назначения данных
        •      $this -> destination   =   new  MigrateDestinationUser () ;
        •  
        •      // связываем поля источника и назначения
        •      $this -> addFieldMapping ( 'created' ,   'posted' ) ;
        •  
        •      ...
        •    }
        • }
        •  
    Пример. Миграция пользователей.
  • 16. Ключевые моменты. Карта ИД.
        •      $this -> map   =   new  MigrateSQLMap ( $this -> machineName ,
        •          array ( 'aid'   =>   array (
        •                  'type'   =>   'int' ,
        •                  'not null'   =>   TRUE ,
        •                  'description'   =>   'Account ID.'
        •                  )
        •               ) ,
        •         MigrateDestinationUser :: getKeySchema ()
        •      ) ;
        •  
  • 17. Ключевые моменты. Источник и назначение.
        • // определяем атрибут класса - источник данных
        • $this -> source   =   new  MigrateSourceSQL ( $query ) ;
        •  
        • // определяем атрибут класса - объект назначения данных
        • $this -> destination   =   new  MigrateDestinationUser () ;
        •  
  • 18.
        •   // связываем поля источника и назначения
        • $this -> addFieldMapping ( 'created' ,   'posted' ) ;
        •  
    Ключевые моменты. Связывание полей.
      • Маппинг сложных полей
      • Маппинг полей с множественными значениями
      • Значения по умолчанию
      • Обработка поля источника и поля назначения перед сохранением. 
        • Дополнительные обращение к БД 
        • Работа с объектом новой entity  
  • 19.
        • $query   =  db_select ( 'migrate_example_beer_node' ,   'b' )
        •  
        •    -> fields ( 'b' ,   array ( 'bid' ,   'name' ,   ...   )) ;
        •  
        • $query -> leftJoin ( 'migrate_example_beer_topic_node' ,
        •  
        •     'tb' ,   'b.bid = tb.bid' ) ;
        •  
        • $query -> groupBy ( 'tb.bid' ) ;
        •  
        • $query -> addExpression ( 'GROUP_CONCAT(tb.style)' ,   'terms' ) ;
        •  
        •  
        •  
        • $this -> addFieldMapping ( 'migrate_example_beer_styles' ,   'terms' )
        •  
        •    -> separator ( ',' ) ;
        •  
        •  
    Маппинг полей с множественными значениями на примере таксономии.
  • 20.
        • public   function  prepareRow ( $current_row )   {
        •  
        •     parent :: prepareRow ( $current_row ) ;
        •  
        •      // Добавляем разделенные запятой термины к объекту рядя источника
        •      // с помощью кастомного метода
        •      $current_row -> terms   =   $this -> get_node_term_names (
        •        $current_row -> nid ,
        •        array ( CRNAAccreditationTermMigration :: $source_vocabulary_vid )
        •      ) ;
        •  
        •      return   TRUE ;
        •    }
        • }
        •  
    Маппинг полей с множественными значениями на примере таксономии.
      • $this -> addFieldMapping ( 'migrate_example_beer_styles' ,   'terms' )
      •    -> separator ( ',' ) ;
      prepare(stdClass $account, stdClass $row)
  • 21. Маппинг полей.   prepare(stdClass $entity, stdClass $row)
  • 22. Перевод ИД.
        • // объявляем зависимость
        • $this -> dependencies   =   array ( 'BeerTerm' ,   'BeerUser' ) ;
        •  
        • // при маппинге поля просим фреймврок заменять значение 'aid' на новое,
        • // из таблицы карты миграции и устанавливаем значение по умолчанию
        • $this -> addFieldMapping ( 'uid' ,   'aid' )
        •    -> sourceMigration ( 'BeerUser' )
        •    -> defaultValue ( 1 ) ;
        •  
    В конструкторе класса миграции BeerNodeMigration:
  • 23. Перевод ИД.
        • $this -> addFieldMapping ( 'pid' ,   'cid_parent' )
        •  
        •    -> sourceMigration ( 'BeerComment' )
        •  
        •    -> description ( 'Parent comment.' ) ;
        •  
        •  
    В конструкторе класса миграции BeerCommentMigration:
  • 24. Миграция сложных полей на примере  addressfield.
    • Для миграции сложного поля, необходимо:
      • проверить существование соответвующего класса
      • создать класс в случае необходимости
      • использовать соответвующий синтаксис маппинга
    ИЛИ Использовать метод    prepare(stdClass $entity, stdClass $row)
  • 25. Миграция сложных полей на примере  addressfield.
        • $arguments   =   array (
        •    'administrative_area'   =>   array ( 'source_field'   =>   'province' ) ,
        •    'locality'   =>   array ( 'source_field'   =>   'city' ) ,
        •    'thoroughfare'   =>   array ( 'source_field'   =>   'street' ) ,
        •    'premise'    =>   array ( 'source_field'   =>   'additional' ) ,
        •    'postal_code'    =>   array ( 'source_field'   =>   'postal_code' ) ,
        • ) ;
        • $this -> addFieldMapping ( ‘field_address’ ,  ‘country’ )
        •    -> arguments ( $arguments )
        •    -> description ( t ( 'Mapping field_address' )) ;
        •  
    Маппинг поля в конструкторе. Кастомный класс для маппинга addrressfield >>>
  • 26. Миграция сложных полей на примере  addressfield.
        • class  MigrateAddressFieldHandler  extends  MigrateFieldHandler  {
        •    public   function  __construct ()   {
        •      $this -> registerTypes ( array ( 'addressfield' )) ;
        •    }
        •  
        •    public   function  prepare ( $entity ,   array   $field_info ,   array   $instance ,   array   $values )   {
        •      $arguments   =   array () ;
        •      if   ( isset ( $values [ 'arguments' ]))   {
        •        $arguments   =   array_filter ( $values [ 'arguments' ]) ;
        •        unset ( $values [ 'arguments' ]) ;
        •      }
        •      $language   =   $this -> getFieldLanguage ( $entity ,   $field_info ,   $arguments ) ;
        •  
        •      // Setup the standard Field API array for saving.
        •      $delta   =   0 ;
        •      foreach   ( $values   as   $value )   {
        •        $return [ $language ][ $delta ]   =   array ( 'country'   =>   $value )   +   array_intersect_key ( $arguments , $field_info [ 'columns' ]) ;
        •        $delta ++;
        •      }
        •  
        •      return   isset ( $return )  ?  $return   :   NULL ;
        •    }
        • }
        •  
  • 27. Что еще может Migrate
      • Работа с файлами
      • Поддержка XML, JSON, CSV,   
      • Поддержка с различных типов БД источника (MSSQL, Oracle)
      • Миграция alias'ов
      • Интеграция с Drush
      • Откат импорта 
      • Интерфейс для контроля прогресса и маппинга
      • and even more...
    •  
  • 28. Импорт данных с фреймворком Migrate Владислав Богатырев Ноябрь 2011 It is powerful. Use it!