3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ほぼSalesforce !! Qiitan と カレンダーと 3年目のWebエンジニアAdvent Calendar 2022

Day 18

SalesforceのAPIを使わずに外部システムのIDから詳細ページのリンクを生成する

Last updated at Posted at 2022-12-17

はじめに

Salesforceのオブジェクトの外部IDとして、usersのような会員IDを使っていますでしょうか?
その際に、Salesforce外のシステムでSalesforceのレコード詳細へのリンクを生成したいけど
APIを使わないといけない??と思っている方への一つの選択肢として今回はVisualforce + Apexを使ってSalesforceのレコード詳細にアクセスできるリンクを作ろうと思います。

検証に使う環境は、Trailheadのハンズオン組織です。
データに関してもデモデータ + 検証で作ったデータしか入っていません

使うもの

  • Visualforce
  • Apex

最終的にどうなるの?

こんな感じで、

  • 作成したVisualforceページへのリンクに外部IDをパラメータに付与してアクセス
  • Apexで外部IDからレコードを検索し、リダイレクト設定
  • 外部IDを持つレコード詳細ページにリダイレクト

無題の図形描画 (22)

事前準備

外部ID項目の作成

Account オブジェクトにExternalId__cという外部ID項目を作成しました。

取引先-Salesforce

データの準備

外部ID 1のデータを生成しました。

テスト取引先1-Salesforce (2)

Apexの作成

  • 受け取るパラーメータ
    • id
      • 外部IDの値
    • type
      • リクエストのタイプ、検索するオブジェクトと外部ID項目のAPI参照名取得に利用
RedirectObjectViewController.cls
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からのエラーメッセージを表示
doOpenObjectView.page
<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ページにリダイレクトされました!

テスト取引先1-Salesforce (3)

さいごに

Salesforceと外部アプリケーションを連携している場合に、外部IDを元に外部アプリケーションへのURLを作るのは、
Salesforceでは簡単。外部アプリケーションから関連するSalesforceへのURLを作るときにどうやって実装をしよう??となると思いますが、
1つの解決策としての Visualforceページ + Apex でリダイレクトパターンでした。
すでに、Salesforceを開いている場合はこのままだとSalesforeがリロードされてしまうので
微妙な点はあるかもですが、初回表示や業務上Visualforceページ にアクセスするタイミングがSalesforce上でなにか作業している途中ではないパターンでは有効だと思います。

参考

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?