この文章は Salesforce 機械翻訳システムを使用して翻訳されました。詳細はこちらをご参照ください。
英語に切り替える

$ObjectType を使用したスキーマ詳細への動的参照

$ObjectType グローバル変数を使用すると、組織のオブジェクトに関するさまざまなスキーマ情報にアクセスできます。たとえば、オブジェクトの項目の名前、表示ラベル、データ型の参照に使用します。
$ObjectType は、「深い」グローバル変数であり、次のような「二重に動的」な参照に使用することができます。
1$ObjectType[sObjectName].fields[fieldName].Type
次の例では、動的グローバル変数を使用して一般的なオブジェクトビューアを提供します。最初に、DynamicObjectHandler という名前で新しいコントローラ (拡張ではない) を作成します。
1swfobject.registerObject("clippy.codeblock-1", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class DynamicObjectHandler {
18
19    // This class acts as a controller for the DynamicObjectViewer component
20    
21    private String objType;
22    private List<String> accessibleFields;
23
24    public sObject obj { 
25        get; 
26        set {
27	          setObjectType(value);
28	          discoverAccessibleFields(value);
29	          obj = reloadObjectWithAllFieldData();
30        } 
31    }
32    
33    // The sObject type as a string
34    public String getObjectType() {
35    	  return(this.objType);
36    }
37    public String setObjectType(sObject newObj) {
38        this.objType = newObj.getSObjectType().getDescribe().getName();
39        return(this.objType);
40    }
41    
42    // List of accessible fields on the sObject
43    public List<String> getAccessibleFields() {
44     	return(this.accessibleFields);
45    }
46    
47    private void discoverAccessibleFields(sObject newObj) {
48        this.accessibleFields = new List<String>();
49        Map<String, Schema.SobjectField> fields = 
50            newObj.getSObjectType().getDescribe().fields.getMap();
51        for (String s : fields.keySet()) {
52            if ((s != 'Name') && (fields.get(s).getDescribe().isAccessible())) {
53                this.accessibleFields.add(s);
54            }
55        }
56    }
57    
58    private sObject reloadObjectWithAllFieldData() {
59        String qid = ApexPages.currentPage().getParameters().get('id');
60        String theQuery = 'SELECT ' + joinList(getAccessibleFields(), ', ') + 
61                          ' FROM ' + getObjectType() + 
62                          ' WHERE Id = :qid';
63        return(Database.query(theQuery));    	
64    }
65    
66    // Join an Apex List of fields into a SELECT fields list string
67    private static String joinList(List<String> theList, String separator) {
68
69        if (theList == null)   { return null; }
70        if (separator == null) { separator = ''; }
71
72        String joined = '';
73        Boolean firstItem = true;
74        for (String item : theList) {
75            if(null != item) {
76                if(firstItem){ firstItem = false; }
77                else { joined += separator; }
78                joined += item;
79            }
80        }
81        return joined;
82    }
83}
このコントローラでは、次の点に留意してください。
  • Visualforce コンポーネントはコントローラ拡張を使用できません。代わりに、このクラスはコントローラとして記述されます。コンストラクタは定義されないため、このクラスではデフォルトのコンストラクタが使用されます。
  • オブジェクトのメタデータを収集するには、コントローラでオブジェクトを把握している必要があります。Visualforce コンストラクタは引数を取れないため、インスタンス化時に目的のオブジェクトを知る方法がありません。代わりに、公開プロパティ obj を設定することで、メタデータ検出がトリガされます。
  • このクラスでは複数のメソッドが、前の例より若干異なる方法でシステムスキーマ検出メソッドを使用しています。
次の例は、オブジェクトに関するスキーマ情報と、クエリされるレコードの特定の値を表示する Visualforce コンポーネントです。次のコードを使用し、DynamicObjectViewer という名前で新規 Visualforce コンポーネントを作成します。
1swfobject.registerObject("clippy.codeblock-2", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<apex:component controller="DynamicObjectHandler">
18    <apex:attribute name="rec" type="sObject" required="true"
19        description="The object to be displayed." assignTo="{!obj}"/>
20
21    <apex:form >
22    <apex:pageBlock title="{!objectType}">
23        <apex:pageBlockSection title="Fields" columns="1">
24            <apex:dataTable value="{!accessibleFields}" var="f">
25                <apex:column >
26                    <apex:facet name="header">Label</apex:facet>
27                    <apex:outputText value="{!$ObjectType[objectType].fields[f].Label}"/>
28                </apex:column>
29                <apex:column >
30                    <apex:facet name="header">API Name</apex:facet>
31                    <apex:outputText value="{!$ObjectType[objectType].fields[f].Name}"/>
32                </apex:column>
33                <apex:column >
34                    <apex:facet name="header">Type</apex:facet>
35                    <apex:outputText value="{!$ObjectType[objectType].fields[f].Type}"/>
36                </apex:column>
37                <apex:column >
38                    <apex:facet name="header">Value</apex:facet>
39                    <apex:outputText value="{!obj[f]}"/>
40                </apex:column>
41            </apex:dataTable>
42        </apex:pageBlockSection>
43        
44        <apex:pageBlockSection columns="4">
45            <apex:commandButton value="View"
46                action="{!URLFOR($Action[objectType].View, obj.Id)}"/>
47            <apex:commandButton value="Edit"
48                action="{!URLFOR($Action[objectType].Edit, obj.Id)}"/>
49            <apex:commandButton value="Clone"
50                action="{!URLFOR($Action[objectType].Clone, obj.Id)}"/>
51            <apex:commandButton value="Delete"
52                action="{!URLFOR($Action[objectType].Delete, obj.Id)}"/>
53        </apex:pageBlockSection>
54    </apex:pageBlock>
55    </apex:form>
56    
57</apex:component>
次の点を確認してください。
  • このコンポーネントを使用するページでは、レコードを検索する必要があります。これを行うには、そのオブジェクトに標準コントローラを使用し、URL でレコードの Id を指定します。たとえば、https://<Salesforce_instance>/apex/DynamicContactPage?id=003D000000Q5GHE です。
  • 選択したレコードはすぐにコンポーネントの obj 属性に渡されます。このパラメータは、すべてのオブジェクトメタデータ検出に使用されます。
  • この 3 つの二重に動的な参照が、$ObjectType[objectType].fields[f] で開始し、各項目のメタデータを表示するのに対し、通常の動的参照は項目の実際の値を表示します。
  • データ値の場合、値は、より自然な {!rec[f]} (コンポーネントへのパラメータ) ではなく {!obj[f]} で、コントローラ内で getter メソッドが使用されます。その理由は単純で、obj 属性はすべての項目のデータを読み込むように更新されていますが、rec は標準コントローラで読み込まれたときと同じ状態のままであり、読み込まれるのが Id 項目のみであるためです。
最後に、新しいコンポーネントを使用して、任意の数の単純な Visualforce ページを作成できます。このページは、コンポーネントを使用して、次の 2 つのページのようなレコード詳細およびスキーマ情報ページを表示します。
1swfobject.registerObject("clippy.codeblock-3", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<apex:page standardController="Account"> 
18    <c:DynamicObjectViewer rec="{!account}"/>
19</apex:page>
1swfobject.registerObject("clippy.codeblock-4", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<apex:page standardController="Contact">
18    <c:DynamicObjectViewer rec="{!contact}"/>
19</apex:page>