Get-ForumUserName
Get-ForumUserName

Reputation: 89

Manipulate a PHP array to match array requirements of a function and call function recursively

I'm working on trying to automate the update of certain records in our SugarCRM system from a CSV file I will be receiving each month.

Background/Introduction

I am using the code below that is provided by Sugar to update/create records via REST.

<?php

include_once('parsecsv.lib.php');  // Include the parsecsv-for-php library

$csv = new parseCSV('myCSV.csv'); // Parse through the CSV and store results in $csv

$url = "http://{site_url}/service/v4/rest.php";
$username = "admin";
$password = "password";

//function to make cURL request
function call($method, $parameters, $url)
{
    ob_start();
    $curl_request = curl_init();

    curl_setopt($curl_request, CURLOPT_URL, $url);
    curl_setopt($curl_request, CURLOPT_POST, 1);
    curl_setopt($curl_request, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
    curl_setopt($curl_request, CURLOPT_HEADER, 1);
    curl_setopt($curl_request, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($curl_request, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl_request, CURLOPT_FOLLOWLOCATION, 0);

    $jsonEncodedData = json_encode($parameters);

    $post = array(
         "method" => $method,
         "input_type" => "JSON",
         "response_type" => "JSON",
         "rest_data" => $jsonEncodedData
    );

    curl_setopt($curl_request, CURLOPT_POSTFIELDS, $post);
    $result = curl_exec($curl_request);
    curl_close($curl_request);

    $result = explode("\r\n\r\n", $result, 2);
    $response = json_decode($result[1]);
    ob_end_flush();

    return $response;
}

//login -----------------------------------------------

$login_parameters = array(
     "user_auth"=>array(
          "user_name"=>$username,
          "password"=>md5($password),
          "version"=>"1"
     ),
     "application_name"=>"RestTest",
     "name_value_list"=>array(),
);

$login_result = call("login", $login_parameters, $url);

/*
echo "<pre>";
print_r($login_result);
echo "</pre>";
*/

//get session id
$session_id = $login_result->id;

//create contacts ---------------------------------------

$set_entries_parameters = array(
     //session id
     "session" => $session_id,

     //The name of the module from which to retrieve records.
     "module_name" => "Accounts",

     //Record attributes
     "name_value_list" => array(
         array(
            //to update a record, you will nee to pass in a record id as commented below
            array("name" => "id", "value" => "111111111"),
            array("name" => "jan_field_1", "value" => "Sample Value 1"),
            array("name" => "jan_field_2", "value" => "Sample Value 2"),
            // more fields could be added here
         ),
         array(
            //to update a record, you will nee to pass in a record id as commented below
            array("name" => "id", "value" => "222222222"),
            array("name" => "jan_field_1", "value" => "Sample Value 1"),
            array("name" => "jan_field_2", "value" => "Sample Value 2"),
            // more fields could be added here
         ),
     ),
);

$set_entries_result = call("set_entries", $set_entries_parameters, $url);

echo "<pre>";
print_r($set_entries_result);
echo "</pre>";

?>

Everything works fine if I hardcode the values in the $set_entries_parameters array like:

//Record attributes
     "name_value_list" => array(
         array(
            //to update a record, you will need to pass in a record id as commented below
            array("name" => "id", "value" => "111111111"),
            array("name" => "jan_field_1", "value" => "Sample Value 1"),
            array("name" => "jan_field_2", "value" => "Sample Value 2"),
         ),
         array(
            //to update a record, you will need to pass in a record id as commented below
            array("name" => "id", "value" => "222222222"),
            array("name" => "jan_field_1", "value" => "Sample Value 1"),
            array("name" => "jan_field_2", "value" => "Sample Value 2"),
         ),
     ),
);

Below is a printout of print_r($set_entry_parameters['name_value_list']) that is ultimately passed to the function call($method, $parameters, $url) as $paramaters -- everything works fine and the records each record is updated correctly.

Array
(
[0] => Array
    (
        [0] => Array
            (
                [name] => id
                [value] => 111111111
            )

        [1] => Array
            (
                [name] => jan_field_1
                [value] => Sample Value 1
            )

        [2] => Array
            (
                [name] => jan_field_2
                [value] => Sample Value 2
            )

    )

[1] => Array
    (
        [0] => Array
            (
                [name] => id
                [value] => 222222222
            )

        [1] => Array
            (
                [name] => jan_field_1
                [value] => Sample Value 1
            )

        [2] => Array
            (
                [name] => jan_field_2
                [value] => Sample Value 2
            )

    )

)

The CSV file I am working with comes in the following form where id is the id of the record in the CRM and each additional column header is what field will be updated along with what the value should be set at:

id,field_1,field_2,field_3,field_4,field_5,field_6
111111111,21,10,8,0,1,1
222222222,32,8,7,0,0,1
333333333,17,11,7,0,0,4

As time goes on, multiple new columns/headers will be added to the spreadsheet for each new month.

I am currently using the parsecsv-for-php library from http://code.google.com/p/parsecsv-for-php/ to parse the CSV file. The library creates the following array in $csv->data' via $csv = new parseCSV('myCSV.csv');:

Array
(
[0] => Array
    (
        [id] => 111111111
        [field_1] => 21
        [field_2] => 10
        [field_3] => 8
        [field_4] => 0
        [field_5] => 1
        [field_6] => 1
    )

[1] => Array
    (
        [id] => 222222222
        [field_1] => 32
        [field_2] => 8
        [field_3] => 7
        [field_4] => 0
        [field_5] => 0
        [field_6] => 1
    )
)

Question/Problem

Finally to the problem that I am struggling with.

I need to find a way to take the array that is created from the parsecsv-for-php libary and make that the $set_entry_paramaters['name_value_list'] that is ultimately passed into the function that updates all records.

In my example above, everything works fine if I hardcode each sub-array that needs to be updated with the ID of the record and each field that needs to be updated.

But the $csv->data array will change each month with new records that need to be updated as well as new fields that need to be updated.

I'm guessing that I need to somehow recursively add whatever is in the $csv->data array into the $set_entry_parameters['name_value_list'] but the key/index of the $csv->data does not match what needs to be sent.

As you can (hopefully) see, each account that is to be updated is it's own array: the id of the record to be updated is a sub-array, and each field that is to be updated is a sub-array as well, but my parsed CSV array does not come close to that.

So it seems to me like I have two problems that I need to solve:

  1. The array that holds the parsed CSV needs to match the structure of the array that the function call($method, $parameters, $url) accepts as $paramaters.
  2. The function call($method, $parameters, $url) needs to be called once for every record that needs to be updated.

I've looked into trying to use the array_walk or call_user_func_array methods in PHP, but I'm not certain if that is correct or how I would go about doing it.

I am still learning PHP but I think this is really beyond my understanding at this point in time, but hoping that I can learn how to do this. I hope I have provided enough information, and hopefully there is a kind soul out there who can give me a helping hand. I will be happy to provide any additional information if it would help.

Thank you so much in advance!

Upvotes: 4

Views: 566

Answers (1)

i Code 4 Food
i Code 4 Food

Reputation: 2154

First of all, props to you for writing such a nicely presented first question!

You are correct in that the answer to your problem is to transform your $csv->data array into the format you want, but it doesn't have to be recursive since you know its depth and everything. You'll probably just want to build your own array side by side with it, as basically what you need is to convert the $name => $value pairs from your $csv->data into arrays of their own.

Here's an example of how you can do it, bear with me here as my php syntax skills are as rusty as they can get, so take it with a grain of pseudo-code if needed:

$params = array();
foreach ($csv->data as $i => $pairs) {
    $csvline = array();
    foreach ($pairs as $name => $value) {
        $csvline[] = array('name'  => $name,
                           'value' => $value)
    }
    $params[$i] = $csvline; // in your case you may also do $params[] =...
}
$set_entry_parameters['name_value_list'] = $params;

voilá, $params is in your expected format :)

Edit:

For your additional funcionality from the comment below, a simple way to do it is to put the above code into a function that receives a $start parameter, so you can limit the amount of lines to be parsed, and where to start. For example:

function parse($start) {
    $params = array();
    foreach ($csv->data as $i => $pairs) {
        if($i < $start) continue; // skip it
        if($i == $start+10000) break; // we reached our limit, stop here
        $csvline = ...
    ...
    }
    return $params; // has at most 10000 entries
}

and then you would use a loop such as

for($i = 0; $i < (total_lines); $i = $i + 10000) {
    $set_entry_parameters['name_value_list'] = parse($i);
    // call update
}

However, if it is actually your initial CSV file parsing that is running out of memory, you might find it simpler to just manually (or programatically) split the data into multiple files instead. Or increase the memory limit you allow PHP to use!

Upvotes: 1

Related Questions