Help us understand the problem. What is going on with this article?

LaravelからSalesforceへのデータ連携入門

これはなに

LaravelからSalesforceにデータを同期する方法について紹介します。

別システムで管理してるデータをSalesforceに同期させることで、
営業やカスタマーサクセスなど他部署でのデータ活用が可能になり、業務効率化が期待できます。

そういうわけでやってくれと依頼されたのでやってみました。
Salesforce何もわからない状況から始まってようやくデータ同期の道筋ができた状況です。

Salesforceにデータを同期する方法

別システムからSalesforceにデータを同期する方法にはいくつかありますが、
今回はおそらく一番一般的であろうREST APIを使います。

Lightning Platform REST API

ドキュメントはこちら https://developer.salesforce.com/docs/atlas.ja-jp.api_rest.meta/api_rest/intro_what_is_rest_api.htm

Lightning Platformってなに? って感じですが、
最近のSalesforceプラットフォームのことで、昔のはSalesforce Classicというようです。
あまり気にせず行きましょう。

APIいろいろあるんですが、正直あまり見てません。
次に紹介するラッパーが便利だったからです。

LaravelからSalesfoceにデータ同期するのに便利なパッケージ

LaravelからSalesfoce REST APIを便利に使うパッケージを探したところ
omniphx/forrestというものを見つかりました。

Salesforce REST API Client for Laravel
https://github.com/omniphx/forrest
Forrest.png

Forrestの使い方

Installation

Laravel6前提です

composer.json

"omniphx/forrest": "2.*"

を追加して

composer update

インストールが完了するとconfig/app.phpに以下のコードが追加されるようです。
私は追加されてなかったので自分で追加しました。
それぞれprovidersaliasesに追加します。

config/app.php
Omniphx\Forrest\Providers\Laravel\ForrestServiceProvider::class
'Forrest' => Omniphx\Forrest\Providers\Laravel\Facades\Forrest::class

これでLaravelの他のFacade(LogやCache)と同じように、コードのどこでもForrestと書くとFacadeが実行できるようになりました。

設定ファイルの外出しと環境変数

このままではforrestの設定ファイルがvender配下にあって変更できないので、
以下のコマンドでconfig/配下に設定ファイルを移動させます。

php artisan vendor:publish

他にも設定ファイルの外出しができる場合はどれを外出しするか聞かれますが、configってやつを選べばよかったと記憶してます。

次に.envに環境変数を追加します。

.env
CONSUMER_KEY=123455
CONSUMER_SECRET=ABCDEF
CALLBACK_URI=https://test.app/callback
LOGIN_URL=https://login.salesforce.com
USERNAME=mattjmitchener@gmail.com
PASSWORD=password123

どんな値を設定するかはあとで説明します。

私の場合は、PASSWORDみたいな変数名だと他の変数と被りそうだったので
config/forrest.phpをいじってSALESFORCE_PASSWORDのように名前を変えました。

認証方法の設定

Salesforceに接続する方法はOAuthとパスワード認証の2種類ありますが、
今回はパスワード認証を使用します。

config/forrest.php
    /*
     * Options include WebServer, UserPassword, and UserPasswordSoap
     */
-    'authentication' => 'WebServer',
+    'authentication' => 'UserPassword',

アクセストークンの保存先をキャッシュにしておきます。 

config/forrest.php
    /*
     * Where do you want to store access tokens fetched from Salesforce
     */
    'storage'        => [
-        'type'          => 'session', // 'session' or 'cache' are the two options
+        'type'          => 'cache', // 'session' or 'cache' are the two options

Salesforceに接続アプリケーションを追加する

今回はパスワード認証を使う前提で進めます。
1. Salsesforceプラットフォームにログインする
2. 設定 > アプリケーションマネージャ(左のメニュー) からアプリケーションマネージャの画面を表示する
3. 新規接続アプリケーションをクリック
4. 必須項目を埋める

接続アプリケーションができると、CONSUMER_KEYなどが発行されるのでこれをコピーして.envに貼り付けます。

.env
CONSUMER_KEY=123455
CONSUMER_SECRET=ABCDEF
# CALLBACK_URI=https://test.app/callback パスワード認証の場合これはいらない
LOGIN_URL=https://test.salesforce.com # 本番環境の場合はhttps://login.salesforce.com
USERNAME=mattjmitchener@gmail.com # Salesforceのログインアカウントと同じ
PASSWORD=password123

使い方

認証

認証はこれだけです。

Forrest::authenticate();

データ取得

データの取得にはSQLライクなSOQLというのを使います。

Forrest::query('SELECT Id FROM Account');
{
    "totalSize": 2,
    "done": true,
    "records": [
        {
            "attributes": {
                "type": "Account",
                "url": "\/services\/data\/v30.0\/sobjects\/Account\/001i000000xxx"
            },
            "Id": "001i000000xxx"
        },
        {
            "attributes": {
                "type": "Account",
                "url": "\/services\/data\/v30.0\/sobjects\/Account\/001i000000xxx"
            },
            "Id": "001i000000xxx"
        }
    ]
}

1度に2000件しか取れないという制限がありますが、次のデータを取得する方法も簡単です。詳しくはREADMEを見てください。

ドキュメント: https://developer.salesforce.com/docs/atlas.ja-jp.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_select.htm

データ同期(Upsert)

データの同期は以下のpatchメソッドを使います。

$externalId = 'XYZ1234';

Forrest::sobjects('Account/External_Id__c/' + $externalId, [
    'method' => 'patch',
    'body'   => [
        'Name'  => 'Dunder Mifflin',
        'Phone' => '555-555-5555'
    ]
]);

Upsert(Salesfoce上にすでにデータがあれば上書き、なければ新規作成) をこれだけで実現できます。

そのためにはSalesforce上のオブジェクトに、外部ID属性のカラムを追加する必要があります。

外部IDとpatchを使った同期の例

Salesforceのオブジェクトには、外部IDという属性のカラムを追加することができます。
外部システムからは外部キーを使って簡単にオブジェクトを特定し、書き込むことができます。
外部IDには、外部システム上のオブジェクトのプライマリーキーを使うと、
外部システム上のレコードとSalesforce上のレコードが一対一の関係になって都合がいいと思います。

前提

Salesforceに同期したいLarave上のオブジェクトをUserというEloquentモデルだとします。
Userモデルはidというプライマリーキーを持つものとします。

Salesforce側の準備

  1. 設定 > オブジェクトマネージャ > 新規 からUserオブジェクトを作ります
  2. 設定 > オブジェクトマネージャ >User > 項目とリレーション > 新規から数値型の user_idという項目を作ります。
  3. 作成時のオプションでユニーク外部IDというフラグをONにします。
  4. これでオブジェクトの型ができました。

Laravel側からUpsertする

$user_id = $user->id;

Forrest::sobjects('User__c/user_id__c/' . $user_id, [
    'method' => 'patch',
    'body'   => [
        'Name'  => 'This is new user!',
    ]
]);

User__cは、UserオブジェクトのAPI参照名です。
user_id__cは、user_idカラムの項目名です。
$user_idはあなたが書き込みたいUserオブジェクトのIDです。
Salesforce上に$user->idと一致するuser_idを持つUserオブジェクトが存在しなければ新規追加し、存在すれば上書きをしてくれます。

patchメソッドを使うことで、データの同期を簡単に行うことができました。

参照の同期について

Salesforceには、オブジェクトの参照関係があり、「どのオブジェクトを参照するか」という情報の同期が必要なケースがあります。
どのオブジェクトを参照するかの指定も外部IDを使えば簡単にできます。
詳しくは述べませんが、以下の資料が参考になるはずです。
https://developer.salesforce.com/docs/atlas.ja-jp.api_rest.meta/api_rest/dome_upsert.htm

まとめ

  • LaravelからSalesforceへのデータ同期はForrestが便利です
  • Salesforceの外部IDという仕組みを使えばデータ同期(Upsert)が簡単です

以上、参考になりましたら幸いです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした