はじめに
Salesforceのオブジェクトの外部IDとして、usersのような会員IDを使っていますでしょうか?
その際に、Salesforce外のシステムでSalesforceのレコード詳細へのリンクを生成したいけど
APIを使わないといけない??と思っている方への一つの選択肢として今回はVisualforce
+ Apex
を使ってSalesforceのレコード詳細にアクセスできるリンクを作ろうと思います。
検証に使う環境は、Trailheadのハンズオン組織です。
データに関してもデモデータ + 検証で作ったデータしか入っていません
使うもの
- Visualforce
- Apex
最終的にどうなるの?
こんな感じで、
- 作成したVisualforceページへのリンクに外部IDをパラメータに付与してアクセス
- Apexで外部IDからレコードを検索し、リダイレクト設定
- 外部IDを持つレコード詳細ページにリダイレクト
事前準備
外部ID項目の作成
Account オブジェクトにExternalId__c
という外部ID項目を作成しました。
データの準備
外部ID 1のデータを生成しました。
Apexの作成
- 受け取るパラーメータ
- id
- 外部IDの値
- type
- リクエストのタイプ、検索するオブジェクトと外部ID項目のAPI参照名取得に利用
- id
public with sharing class RedirectObjectViewController {
private Map<String, Map<String, String>> keyMap = new Map<String, Map<String, String>>{
'users' => new Map<String, String>{
'object_key' => 'ExternalId__c',
'object_name' => 'Account'
}
};
public Pagereference doOpenObjectView() {
try {
String id = ApexPages.currentPage().getParameters().get('id');
String type = ApexPages.currentPage().getParameters().get('type');
String objectName = '';
String errorMessage = getErrorParameters(id, type);
if (!String.isBlank(errorMessage)) {
ApexPages.addMessage(
new ApexPages.Message(ApexPages.Severity.WARNING, errorMessage)
);
return null;
}
List<Sobject> records = Database.query(
'SELECT Id ' +
'FROM ' +
String.escapeSingleQuotes(this.keyMap.get(type).get('object_name')) +
' ' +
'WHERE ' +
String.escapeSingleQuotes(this.keyMap.get(type).get('object_key')) +
' = \'' +
String.escapeSingleQuotes(id) +
'\' LIMIT 1'
);
if (records.isEmpty()) {
ApexPages.addMessage(
new ApexPages.Message(
ApexPages.Severity.WARNING,
createApexMessage(id, type)
)
);
return null;
}
ApexPages.StandardController stdCon = new ApexPages.StandardController(
records[0]
);
Pagereference redirectTo = stdCon.view();
redirectTo.setRedirect(true);
return redirectTo;
} catch (Exception ex) {
ApexPages.addMessages(ex);
return null;
}
}
private String getErrorParameters(String id, String type) {
if (!this.keyMap.containsKey(type)) {
return '正しいリクエストタイプを指定してください。';
}
if (String.isBlank(id)) {
return '外部IDを指定ください。';
}
return '';
}
private String createApexMessage(String id, String type) {
return '該当のレコードはSalesforceに存在しません。\n\n' +
'オブジェクト: ' + this.keyMap.get(type).get('object_name') + '\n\n' +
'外部ID: ' + id;
}
}
コードについて
外部システムのテーブル名と、Salesforceのオブジェクト名・外部ID項目名のマッピングを作っています。
private Map<String, Map<String, String>> keyMap = new Map<String, Map<String, String>>{
'users' => new Map<String, String>{
'object_key' => 'ExternalId__c',
'object_name' => 'Account'
}
};
取得したレコード情報でStandardControllerをインスタンス化
+ ApexPages.StandardController stdCon = new ApexPages.StandardController(
+ records[0]
+ );
Pagereference redirectTo = stdCon.view();
redirectTo.setRedirect(true);
return redirectTo;
Pagereferenceへ詳細ページの PageReference オブジェクトを入れる
ApexPages.StandardController stdCon = new ApexPages.StandardController(
records[0]
);
+ Pagereference redirectTo = stdCon.view();
redirectTo.setRedirect(true);
return redirectTo;
クライアント側のリダイレクトでリダイレクトが実行されるようにsetRedirect(true)
ApexPages.StandardController stdCon = new ApexPages.StandardController(
records[0]
);
Pagereference redirectTo = stdCon.view();
+ redirectTo.setRedirect(true);
+ return redirectTo;
Visualforceの作成
- 作詞した
RedirectObjectViewController
をセット - apex:pageMessagesでApexからのエラーメッセージを表示
<apex:page
controller="RedirectObjectViewController"
showHeader="true"
sidebar="true"
action="{!doOpenObjectView}"
>
<apex:form>
<apex:pageMessages escape="false" />
</apex:form>
</apex:page>
動かしてみる
パラメータなし
利用しているSalesforceのドメイン/apexdoOpenObjectView
にアクセス
リクエストタイプのみ指定
利用しているSalesforceのドメイン/apexdoOpenObjectView?type=users
にアクセス
リクエストタイプ&外部ID(レコードなし)
利用しているSalesforceのドメイン/apexdoOpenObjectView?type=users&id=100
にアクセス
リクエストタイプ&外部ID(レコードあり)
利用しているSalesforceのドメイン/apexdoOpenObjectView?type=users&id=1
にアクセス
ユーザID 1のAccountページにリダイレクトされました!
さいごに
Salesforceと外部アプリケーションを連携している場合に、外部IDを元に外部アプリケーションへのURLを作るのは、
Salesforceでは簡単。外部アプリケーションから関連するSalesforceへのURLを作るときにどうやって実装をしよう??となると思いますが、
1つの解決策としての Visualforceページ + Apex でリダイレクトパターンでした。
すでに、Salesforceを開いている場合はこのままだとSalesforeがリロードされてしまうので
微妙な点はあるかもですが、初回表示や業務上Visualforceページ にアクセスするタイミングがSalesforce上でなにか作業している途中ではないパターンでは有効だと思います。
参考