4

毎月受け取る CSV ファイルから、SugarCRM システムの特定のレコードの更新を自動化しようと取り組んでいます。

背景/紹介

Sugar が提供する以下のコードを使用して、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>";

?>

次のように $set_entries_parameters 配列の値をハードコーディングすると、すべて正常に動作します。

//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"),
         ),
     ),
);

以下は最終的にasprint_r($set_entry_parameters['name_value_list'])に渡される出力です-- すべて正常に動作し、各レコードは正しく更新されています。function call($method, $parameters, $url)$paramaters

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
            )

    )

)

私が使用している CSV ファイルは次の形式になっています。ここで、id は CRM 内のレコードの ID であり、各追加の列ヘッダーは更新されるフィールドと値を設定する必要があるフィールドです。

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

時間が経つにつれて、新しい月ごとに複数の新しい列/ヘッダーがスプレッドシートに追加されます。

現在、 http: //code.google.com/p/parsecsv-for-php/ の parsecsv-for-php ライブラリを使用して CSV ファイルを解析しています。$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
    )
)

質問/問題

最後に、私が苦労している問題に。

parsecsv-for-php ライブラリから作成された配列を取得し、最終的にすべてのレコードを更新する関数に渡される $set_entry_paramaters['name_value_list'] を作成する方法を見つける必要があります。

上記の例では、更新が必要な各サブ配列をレコードの ID と更新が必要な各フィールドでハードコードすると、すべてが正常に機能します。

ただし、$csv->data更新が必要な新しいレコードと更新が必要な新しいフィールドによって、配列は毎月変更されます。

$csv->data配列にあるものを再帰的に追加する必要があると思います$set_entry_parameters['name_value_list']が、のキー/インデックスは$csv->data送信する必要があるものと一致しません。

(うまくいけば) ご覧のとおり、更新される各アカウントは独自の配列です。更新されるレコードの ID はサブ配列であり、更新される各フィールドもサブ配列です。しかし、解析された CSV 配列はそれに近づきません。

したがって、解決する必要がある2つの問題があるように思えます。

  1. 解析された CSV を保持する配列は、 がfunction call($method, $parameters, $url)として受け入れる配列の構造と一致する必要があります$paramaters
  2. function call($method, $parameters, $url)、更新が必要なレコードごとに 1 回呼び出す必要があります。

array_walkPHP でorメソッドを使用することを検討しましたがcall_user_func_array、それが正しいかどうか、またはどのように実行するかはわかりません。

私はまだPHPを学んでいますが、現時点ではこれは私の理解を超えていると思いますが、これを行う方法を学べることを願っています. 十分な情報を提供できたことを願っています。助けの手を差し伸べてくれる親切な人がいることを願っています。追加情報があれば喜んで提供します。

よろしくお願いします!

4

1 に答える 1

1

まず第一に、このように見事に提示された最初の質問を書いてくれたあなたへの小道具です!

あなたの問題に対する答えは、$csv->data配列を必要な形式に変換することであるという点で正しいですが、その深さとすべてを知っているので、再帰的である必要はありません。$name => $value基本的に必要なのは、ペアを独自の配列に変換することであるため、おそらくそれと並んで独自の配列を構築したいと思うでしょう$csv->data

これを行う方法の例を次に示します。私の php 構文のスキルはできる限り錆びているので、ここで我慢してください。必要に応じて、疑似コードを少し追加してください。

$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;

ほら、$params期待される形式です:)

編集:

以下のコメントからの追加の機能については、上記のコードを$startパラメーターを受け取る関数に入れるのが簡単な方法です。これにより、解析する行の量とどこから開始するかを制限できます。例えば:

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
}

そして、次のようなループを使用します

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

ただし、実際にメモリ不足になっているのが最初の CSV ファイルの解析である場合は、データを手動で (またはプログラムで) 複数のファイルに分割する方が簡単な場合があります。または、PHP に使用を許可するメモリ制限を増やしてください!

于 2013-05-20T22:57:42.333 に答える