3

I am using drupal 7 and have the data module managing/adopting a table I have manually added to my drupal db. What I was hoping was that when a csv file is uploaded via a specific content type I could use rules to execute some custom php and import the csv into the table (as feedsdataprocessor no longer exists from what I can see). I see there is a drupal_write_record function but the problem is first how do I get the array out of the file and secondly my file can be different to the table in structure - for example, sometimes the csv will have columns 1,2,3,4 and sometimes 3,4,5,6,7. How can I check the headers and import into the managed table?

  • Few questions. All the CVS's go into the same table? Are the field names in the CVS's heading row? Why use rules? Have you considered a custom module? – drewish Jan 17 '12 at 4:38
  • Yes the field names are in the headings row. The reason I wanted to use rules is twofold. One, im not that great at php (yet!) and two, it seemed likes rules already did half the job with its event based functionality. That being said, im definitely open to the idea of a custom module but I would need someone to hold my hand along the way! – 7wonders Jan 17 '12 at 11:14
  • How many of these import do you need to do? Is it a one-off or something that'll be happening repeatedly? Will you be running them or will it be your users? – drewish Jan 17 '12 at 21:12
  • Repeatedly by users hopefully :) – 7wonders Jan 17 '12 at 21:55
9

So conceptual steps:

  1. Extract CSV file path from the node.
  2. Open CSV file, read fields from header.
  3. Read each row, convert the keys, save row using drupal_write_record().
  4. Close the CSV.

I'm not sure how the rules integration will work I'm assuming you can pass the node into it some how.

So for step one assuming it's stored into $node and your field is named field_csv_file we can hand the URL to fopen():

$csv_uri = $node->field_csv_file['und'][0]['uri'];

So now we can open fopen() to get a file handle:

$handle = fopen($csv_uri, 'r');

If there's no value we don't want to procede.

Read the header row:

$row = fgetcsv($handle);
$columns = array();
foreach ($row as $i => $header) {
  $columns[$i] = trim($header);
}

Then load each row and convert the format:

while ($row = fgetcsv($handle)) {
  $record = array();
  foreach ($row as $i => $field) {
    // This is pretty brittle... if someone screws up the field 
    // names the data won't be written. 
    $record[$columns[$i]] = $field;
  }
  drupal_write_record('your_table', $record);
}

Close the file:

fclose($handle);

So issues with this:

  • All this code it totally un-test.
  • What happens if someone re-uploads the file? You'll probably get duplicates.
  • What happens if someone messes with the headers?
  • This works well including all the issues you mention (so thats the next challenge!). The trick is to add a file variable in rules actions to get the file first, then in the code you have provided above use this $csv_uri = '[variable-added:path]'; I consider this answered and I will add a new question regarding the issues once I have tried to fix them myself first! – 7wonders Jan 18 '12 at 20:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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