カスタムコントローラーの作成と使用
学習の目的
この単元を完了すると、次のことができるようになります。
- カスタムコントローラーとその主な属性について説明する。
- カスタムコントローラークラスを作成する。
- Visualforce ページでカスタムコントローラーを使用する。
カスタムコントローラーの概要
<apex:page>
controller
属性でコントローラークラスの名前を参照して、カスタムコントローラーを Visualforce ページに追加します。
ページでカスタムコントローラーを使用する場合、標準コントローラーは使用できません。カスタムコントローラーの設定には、異なる属性がページで使用されます。
- 新しい Visualforce ページを作成するには、開発者コンソールを開き、[File (ファイル)] | [New (新規)] | [Visualforce Page (Visualforce ページ)] をクリックします。ページ名に
ContactsListWithController
と入力します。
- エディターで、任意のマークアップを次のように置き換えます。このページを保存しようとすると、
<apex:page controller="ContactsListWithController"> <apex:form> <apex:pageBlock title="Contacts List" id="contacts_list"> <!-- Contacts List goes here --> </apex:pageBlock> </apex:form> </apex:page>
ContactsListWithController
がまだ存在しないため、エラーになります。これについては、次で対処しますので問題ありません。
カスタムコントローラー Apex クラスを作成する
カスタムコントローラーは、開発者コンソールを使用して自分で記述できる Apex クラスにすぎません。
カスタムコントローラーロジックの記述に役立つ数多くのシステムクラスとユーティリティクラスがありますが、カスタムコントローラーとして使用するクラスの唯一の要件は、それが存在するということです。
- 新しい Apex クラスを作成するには、開発者コンソールを開き、[File (ファイル)] | [New (新規)] | [Apex Class (Apex クラス)] をクリックします。クラス名に
ContactsListWithController
と入力します。
エディターで、任意のコードを次のコードで置き換えます。
public class ContactsListWithController { // Controller code goes here }
Visualforce ページの場合と同様に、変更を加えた場合は変更内容を Apex に保存する必要があります。それほど大きな変更ではなく、まだ何の処理も行われませんが、Visualforce ページでのエラーがなくなります。
- Visualforce ページに戻り、再度保存します。エラーメッセージがなくなり、ページが正常に保存されています。
-
[Preview (プレビュー)] をクリックして、変更処理中に確認できるページのプレビューを開きます。新しいウィンドウが開き、標準の Salesforce ページヘッダーとサイドバー要素が表示されますが、コンテンツはまだありません。
作成した 2 つの新しい項目では物足りないことが一見してわかります。Visualforce ページと Apex コントローラーという 2 つの項目は 90% がプレースホルダーコードですが、互いにリンクされています。他のコードをコントローラーに追加すると、ページでそれを使用できるようになります。
高度な操作
このカスタムコントローラークラスは、別のクラスから継承せず、Visualforce コントローラーの要件を満たすインターフェースも実装しません。継承するクラスや実装するインターフェースは存在しないため、複雑なコントローラーでもこのような処理は行われません。このため、Apex の使用経験を積んでいくと、独自のクラスやインターフェースを自由に作成できるようになります。
レコードを取得するメソッドを追加する
ページに表示するレコードを返す SOQL クエリを実行する getter メソッドを作成します。
ほとんどのコントローラーの主な目的は、表示するデータを取得するか、データ更新を処理することです。この簡単なコントローラーでは、取引先責任者レコードを検索する基本の SOQL クエリを実行し、そのレコードを Visualforce ページで使用できるようにするだけで十分です。
-
ContactsListWithController
クラスで、// Controller code goes here
コメント行を次のコードで置き換えます。このコードは、1 つの非公開メンバー変数、private String sortOrder = 'LastName'; public List<Contact> getContacts() { List<Contact> results = Database.query( 'SELECT Id, FirstName, LastName, Title, Email ' + 'FROM Contact ' + 'ORDER BY ' + sortOrder + ' ASC ' + 'LIMIT 10' ); return results; }
sortOrder
という名前の文字列、1 つの公開メソッドgetContacts()
を追加します。sortOrder
は非常にわかりやすく、単に取引先責任者の並び替え基準になる項目の名前を示します。getContacts()
も単純ですが、これまでに Apex を見たことがない場合は、最初は解析しにくいこともあります。このメソッドの結果、取引先責任者レコードのリストを取得する SOQL クエリが実行され、取引先責任者のリストがメソッドのコール元に返されます。コール元になるのは、もちろん Visualforce ページです。
-
ContactsListWithController
ページで、<!-- Contacts List goes here -->
コメント行を次のマークアップで置き換えます。このページを保存すると、取引先責任者情報の見慣れた表が表示されます。<!-- Contacts List --> <apex:pageBlockTable value="{! contacts }" var="ct"> <apex:column value="{! ct.FirstName }"/> <apex:column value="{! ct.LastName }"/> <apex:column value="{! ct.Title }"/> <apex:column value="{! ct.Email }"/> </apex:pageBlockTable>
ContactsListWithController
ページのマークアップは、かなり見慣れたものです。<apex:page>
タグの controller
属性を除き、標準コントローラーを使用してページを作成する場合に使用するコードとほぼ同じです。
異なる点は、{!contacts }
式が評価されたときの処理です。このページでは、Visualforce により、その式がコントローラーの getContacts()
メソッドのコールに変換されます。このメソッドにより、<apex:pageBlockTable>
で期待される取引先責任者レコードのリストが返されます。
getContacts()
メソッドは getter メソッドと呼ばれます。その一般的なパターンでは、Visualforce マークアップの {!someExpression }
により、コントローラーで getSomeExpression()
という名前のメソッドに自動的に接続されます。これは、表示する必要があるデータにページからアクセスする最も簡単な方法です。
新しいアクションメソッドを追加する
ページ上のユーザー入力に応答するカスタムコントローラーでアクションメソッドを作成します。
Web アプリケーションでは、データの表示も重要ですが、ユーザーアクションに応答することが不可欠です。カスタムコントローラーでは、ユーザー活動に応答するアクションメソッドを記述することによって、ページでサポートするカスタムアクションをいくつでも作成できます。
-
getContacts()
メソッドの下にあるContactsListWithController
クラスで、次の 2 つのメソッドを追加します。この 2 つのメソッドは、public void sortByLastName() { this.sortOrder = 'LastName'; } public void sortByFirstName() { this.sortOrder = 'FirstName'; }
sortOrder
非公開変数の値を変更します。sortOrder
は取引先責任者を取得する SOQL クエリで使用され、sortOrder
を変更すると結果の順序が変更されます。
-
ContactsListWithController
ページで、ct.FirstName
とct.LastName
の 2 つの<apex:column>
タグを次のマークアップで置き換えます。視覚的な外観に変化はありませんが、[名] と [姓] の列ヘッダーをクリックすると、取引先責任者リストの並び替え順が変更されるようになりました。すばらしいですね。<apex:column value="{! ct.FirstName }"> <apex:facet name="header"> <apex:commandLink action="{! sortByFirstName }" reRender="contacts_list">First Name </apex:commandLink> </apex:facet> </apex:column> <apex:column value="{! ct.LastName }"> <apex:facet name="header"> <apex:commandLink action="{! sortByLastName }" reRender="contacts_list">Last Name </apex:commandLink> </apex:facet> </apex:column>
新しいマークアップにより、ネストされた 2 つのコンポーネントが各 <apex:column>
コンポーネントに追加されます。<apex:column>
自体はプレーンテキストヘッダーですが、ヘッダーをクリック可能にしてみます。<apex:facet>
を使用すると、列ヘッダーの内容を自由に設定できます。ここでは、正しいアクションメソッドをコールするリンクにしてみます。リンクの作成には <apex:commandLink>
コンポーネントを使用し、コントローラーでアクションメソッドを参照する式に action
属性を設定します。(getter メソッドとは異なり、アクションメソッドは、それらを参照する式と同じように指定されます)。
リンクをクリックすると、コントローラーでアクションメソッドが起動します。アクションメソッドにより並び替え順の非公開変数が変更され、表が再表示されます。表が再表示されると、{!contacts }
が再評価され、直前に設定された並び替え順でクエリが返されます。最終結果の表は、ユーザークリックによって要求された順序で再度並び替えられます。
高度な操作
このマークアップでは、[名] と [姓] の列のヘッダーテキストがハードコードされています。英語を使用しないユーザーがいる場合はどうなるでしょうか。標準の Salesforce ユーザーインターフェースには、すべての標準オブジェクトの項目名の翻訳バージョンがあり、カスタムオブジェクトには独自の翻訳を指定できます。これらにアクセスするには、プレーンテキストの代わりに <apex:outputText value="{!$ObjectType.Contact.Fields.FirstName.Label }"/>
というマークアップを使用してください。項目名が変更されると自動的に更新されるため、組織のすべてのユーザーが同じ言語を使用している場合でも、この方法は項目の表示ラベルを参照する方法として適切です。
もうひとこと...
カスタムコントローラーと Apex 言語では、Visualforce ページで考えられるほぼすべてのことを実行できます。
getter メソッドは、コントローラーのデータをページに渡します。対応する setter メソッドでは、ページの値をコントローラーに戻すことができます。getter メソッド同様、setter には「set」プレフィックスを使用します。それ以外はこれらは単に引数を取るメソッドです。
getter と setter の代わりに、Apex のプロパティを使用できます。プロパティは、getter メソッドと setter メソッドを含む変数と、それらのメソッドをより明確にグループ化する構文との組み合わせです。カスタムオブジェクトを参照する単一プロパティは、次のように宣言できます。
public MyObject__c myVariable { get; set; }
プロパティは、公開または非公開にすることができ、get または set を省略することで読み取り専用か書き込み専用にできます。さらに、単なる値の保存や取得に加えて追加ロジックを実行する場合、get または set メソッドの実装を作成できます。
プロパティは Apex の一般機能で、Visualforce に固有のものではありません。Apex は完全なプログラミング言語で、複雑な Visualforce ページの作成に使用できるだけでなく、その他の多くの Lightning Platform 開発コンテキストでも使用されます。Apex をフル活用するさまざまな方法についての詳細は、他の場所にある Apex トピック、およびこのページの最後にあるリソースを参照してください。
Visualforce 要求と応答のライフサイクルは、最初は複雑に思えるかもしれません。特に、getter または setter (または使用している場合はプロパティ) のコールに特定の順序はないため、実行順序の連動関係は使用しないことを理解することが重要です。『Visualforce 開発者ガイド』の関連セクション、特に「カスタムコントローラーとコントローラー拡張」の章に多数の詳細情報があります。
リソース
- Visualforce 開発者ガイド: Creating Your First Custom Controller (初めてのカスタムコントローラーの作成)
- Visualforce 開発者ガイド: Custom Controllers and Controller Extensions (カスタムコントローラーとコントローラー拡張)
- Apex 開発者ガイド
- Salesforce 開発者ブログ: Apex Template: Visualforce Controller (Apex テンプレート: Visualforce コントローラー)
- Salesforce 開発者ブログ: A Real Controller for Visualforce Charting (Visualforce Charting の実際のコントローラー)
- Visualforce 開発者ガイド: apex:outputLink コンポーネント
- Visualforce 開発者ガイド: apex:repeat コンポーネント