9

Using the Migrate module: I understand that prepareRow() runs a filter on the row and should return TRUE or FALSE based on some conditions, which allows a row to be migrated or not, but could someone clarify:

  • when to use prepare()
  • when to use prepareRow()
  • why you wouldn't add a filter in the initial sql query to filter row results that you might remove/include in either of the above

Thanks!

1
  • 1
    One reason to not filter at sql query is to add a mapping for the rows you decide to skip. For example I'm importing users onto an existing site. I want to skip users that already exists on destination, and I want to add a mapping as if the user was actually imported, so other migrations depending on this works smothly.
    – jonhattan
    Sep 13, 2016 at 7:08

3 Answers 3

10

This is all covered in-depth in the Migrations classes documentation provided by the project. Specifically in the Commononly Implemented Migration methods page which says the following and includes further simple example function implementations. From the docs ...

function prepare_row($row)

The prepareRow() method is called by the source class next() method, after loading the data row. The argument $row is a stdClass object containing the raw data as provided by the source. There are two primary reasons to implement prepareRow():

  1. To modify the data row before it passes through any further methods and handlers: for example, fetching related data, splitting out source fields, combining or creating new source fields based on some logic.
  2. To conditionally skip a row (by returning FALSE).

function prepare($entity, stdClass $row)

The Migration class prepare() method is called by the destination class prepare() method, after it has called all field-level prepare() methods and immediately before the destination object is saved. The $entity argument is the destination object as populated by the initial field mappings and manipulated by the field-level methods; the $row argument is an object containing the data after prepareRow() and any callbacks have been applied. The prepare() method is the last chance to manipulate the destination object before it is saved to the Drupal database. It is important to remember that, since it is called after the field handlers, fields will be in their fully-expanded forms (i.e., in Drupal 7 a text field value will be at $entity->field_textual_data['und'][0]['value'] rather than simply $entity->field_textual_data).

The Migrate module is a framework which allows you to encapsulate a migration process from a source piece of data to a destination location and configuration. A migration consists of:

  • define where the data is
  • define where the data should go
  • fetch a piece of data (row)
  • sanitize the data
  • begin to move the data (say into an Entity)
  • actually move the data
  • after moving the data perform additional action(s)

The API provides hooks to affect the data being moved in this life cycle of a migration. By excluding data from the migration via your initial query you're limiting how much control you have over the total data you could move. For sub-migrations you may find this useful. But in a general content migration you would want your migration to be as all-encompassing as possible.

1
  • Thanks tenken, exactly what I was looking for. Appreciate the thoughts on removing elements from the initial query as well.
    – user4984
    Jul 15, 2014 at 13:57
6

If you can select the right row by writing it in a query go for it, however preprareRow() can be used in more complex systems where several parameters might be required before the row gets migrated. In such a case it is easier to run through all the rows and do the logic on a per-row basis.

prepare() is ran after prepareRow() and is your last chance to alter the entity before it is saved to the database.

Some more information on this can be found here: https://www.drupal.org/node/1132582

1
  • I found this to be concise and understandable Jul 14, 2014 at 14:59
3

This is a part answer and in no way complete. I'd also keen to find out more about both of these. So this may be part of a discussion; although I have written as an answer rather than comment because of the following code snippets and examples of how I've used the above classes.

Let me illustrate some of my uses prepareRow() as - which does as it says.

A recently I was giving some data to import from a non drupal database. The entity I am adding to requires fields to be entered that I do not have in my data import.

So before my source class is created I can add

  $source_fields = array(
    'changed' => t('Timestamp of when the change was made.'),
    'created' => t('Timestamp of when the node was Created.'),
 );

and then in the function prepareRow I can do the following

$nowtimestamp = mktime(date('Y-m-d'));
$row->changed = $nowtimestamp;
$row->created = $nowtimestamp;

you can also run php if/else statements here if necessary.

I've also used the prepare function in my code and am using it to assign values to the entity.

$account->field_job_location [und][0]['tid'] = $row->job_location_tid;

I've only had to use this in this scenario as I made my own custom node plugin.

Also if you need to make calculations on that then you can do it in prepareRow which runs before prepare()

For example in the import I had a value labelled 'Town' - and could turn this into a Term Id.

 if ($TownCity == 'London' ){
            $row->job_location_tid = '10';
      } else {
        $row->job_location_tid = '11';
      } 

I hope this helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.