I have a long list of donations that I want to import. My first step was to ensure that all the contacts in the list exist in CiviCRM - that's done, and I spent a while deduplicating the records. Next, I imported all the donations that mapped cleanly using email addresses. That worked well.

Now I have a couple hundred donations left where the only identifying information is the contact's First Name and Last Name field. It seems like the right thing to do now is to write a script that determines whether each of my First/Last pairs is unique among all contacts, and if so, pull the Contact ID so that I can put an ID in each line of the import data, and finally import the donations. After this, I think there should only be a handful of donations to add manually.

I was initially trying to write a script like so:

if (($handle = fopen($argv[1], "r")) !== FALSE) {
    $header = fgetcsv($handle, 1000);
    fputcsv(STDOUT, $header);
    echo ",contact_id\n";
    while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
        $row = array_combine($header, $data);
        $result = civicrm_api4('Contact', 'get', [
            'select' => ['primary_contact_id'],
            'where' => [['first_name', '=', $row['Firstname']],
                        ['last_name', '=', $row['Lastname']]]]);

        if (count($result) != 1) {
        row[] = $result[0]['id'];
        fputcsv(STDOUT, $row);
        echo "\n";

However, I got stuck trying to load the API library, and eventually I found the page https://docs.civicrm.org/dev/en/latest/extensions/advanced/ , which tells me I shouldn't be attempting to write a script like this (but it also says that its own self is out of date...).

So what would be a good way to go about this? I don't anticipate needing to do this exact task again, so I don't need to make it repeatable, but it would be good to learn what the "paved path" is here because I'm sure there will be other tasks to perform at various times.

  • 2
    if you import your first/last and add to a Group, then use that group to 'dedupe' you might be able to quickly deduce which have multiple matching contacts. and then do an export of ID and use vlookup to add the ID to your import?
    – petednz - fuzion
    Commented Nov 2, 2021 at 4:00

1 Answer 1


If you are happy working with the command line, install cv then you can run cv scr /path/to/your/script.php

To use your script with cv add <?php as the first line.

You'll want 'select' => ['id'], not 'select' => ['primary_contact_id'],

Once you get that far, you could just create the contributions directly instead of outputting the id and doing a separate import process. And from there you'll see it is only a few short steps to doing your entire import via the script with all the logic in one place!

  • Very nice, thanks for the follow-on suggestions too. Commented Nov 3, 2021 at 4:38
  • Hmm, when I try to execute this I get a fatal error: Unable to write to the "/opt/bitnami/drupal/sites/default/files/civicrm/templates_c" directory. Is there some other configuration I need to perform? I'm not sure why it would be trying to write to the templates directory. Commented Nov 3, 2021 at 4:52
  • That's a permissions problem. The files in templates_c will (mostly...) be owned by the id running the webserver. Can you run your script as that user? If not, you'll need to open up permissions on that directory so your id can write there.
    – Aidan
    Commented Nov 3, 2021 at 12:25
  • Thanks, looks like I can do sudo -u daemon `which cv` scr myscript.php. It's still not finding my contacts though, I think I'll post a new question about that. Commented Nov 5, 2021 at 1:23
  • Followup question is civicrm.stackexchange.com/questions/40660/… . Commented Nov 5, 2021 at 1:41

Your Answer

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

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