Salesforceのファイルはどこからトリガー出来る?
【5分で読了できます】
こんにちは!PROOF代表の阿部です。今回はファイルのトリガーについてです。
Salesforceのファイル関連オブジェクトの扱いの複雑さに悩まされていませんか?僕は何度か「あ、できますよぉ~~~」と、お客様に嘘をついてしまいました。ファイル周りは罠が沢山あります。
ファイル関連のトリガー動作について、簡単に、動作検証ベースで、まとめてみますのでよかったら読んでみてください。
ファイルは、2種類あります。
- 添付ファイル
- ファイル
です。
添付ファイル(Attachment)は、現在は新規構築で使用する事はほぼないと思うので、省きます。ファイル(ContentDocument)の劣化版くらいの認識で問題ないと思います。
容量が小さかったり、添付や共有などの柔軟な扱いが出来なかったります。
ファイル(ContentDocument)は、主に以下画像のレコードのコンポーネントから添付するファイルです。

その他に、ファイルオブジェクトの画面から、どのレコードにも紐づけず(厳密には共有先としてユーザーが紐づく)ファイル単品でアップロードすることも出来ます。
ファイルのオブジェクト構成
ファイルは主に3つのオブジェクトで構成されています。詳しくは他に良記事が沢山あるので、ご参照を!
- ContentDocument:ファイル自体の情報。最新バージョンのID(LatestPublishedVersionId)などを保持します。
- ContentVersion:ファイルのバージョン情報。バージョンごとにファイルの実態を持ち、VersionDataで保持します。
- ContentDocumentLink:ファイルのリンク先。共有先ユーザーや添付されたレコードの紐づき(LinkedEntityId)を保持します。
オブジェクト構成はContentDocumentとContentVersionが相互参照。ContentDocumentの子にContentDocumentLinkが存在しています。こちらも詳しくは他に良記事が沢山あります。

本題のトリガーについて
ここからが本題です!
ファイル周りのトリガーは、少し複雑で、知識を入れておかないと思わぬ罠が沢山潜んでます。
こちらで各挙動をまとめます。
まずは各操作でのファイル周りのレコードの挙動まとめ
本記事における必要最低限の情報のみ記載します。
作成・更新・削除と、各操作で更新されるレコード数について記載しています。
UI上の操作を以下4つにまとめます。
※共有先を増やすとか、ライブラリに入れるとかは省略!
以下略記
ContentDocument = CD
ContentVersion = CV
ContentDocumentLink = CDL
レコードへのファイル添付の場合
- CD:レコードが1つ作成される
- CV:ContentDocumentに紐づきレコードが1つ作成される
- CDL:LinkedEntityIdが投入ユーザーと関連レコード分のレコードが2つ作成される
レコードからのファイル削除の場合
- CD:レコードが削除される
- CV:すべてのバージョンレコードが削除される
- CDL:すべてのリンクレコードが削除される
レコードからファイルのバージョンを更新した場合
- CD:LatestPublishedVersionIdが更新される
- CV:新しいバージョンレコードが1つ作成される
- CDL:何も起こらない
ファイルを単一で投入した場合
- CD:レコードが1つ作成される
- CV:新しいバージョンレコードが1つ作成される
- CDL:LinkedEntityIdが投入ユーザーのレコードが1つ作成される
まとめると以下の表の通りです。

Apex Triggerについて
Apexトリガーでは、ContentVersion及び、ContentDocumentLinkのトリガーが想定とは違う動きをします。
ContentVersion
レコードの添付ファイルから、ファイルを削除してもContentVersionのDeleteトリガーが起動しません。
なぜ?
>before トリガーまたは after delete トリガーを ContentVersion オブジェクトと併用することはできません。
えっ。まじ?
ハッキリと書いてますよね?(間違えてたら教えて)
つまり単純にContentVersionにDeleteトリガーは使えないとのこと。
ContentDcumentLink
レコードの添付ファイルから、ファイルを削除してもContentDocumentLinkのDeleteトリガーが起動しません。
なぜ??
>ContentDocumentLink オブジェクトでは、挿入、更新、削除操作の前後のトリガーがサポートされます。ContentDocumentLink トリガーは、ContentDocumentLink に追加や削除があるたびに実行されます。ファイルが削除されると、ContentDocument の削除トリガーが実行されますが、カスケードされた ContentDocumentLink の削除では ContentDocumentLink トリガーは実行されません。
前述の「レコードへのファイル添付の場合」「レコードからのファイル削除の場合(バージョン1つ)」のContentDocumentLinkの削除レコードが2つになっている事に注目しながら上記の公式リファレンスを見ると原因がわかります。
そう、ContentDocumentLinkは、関連レコードを参照するものと、ユーザーを参照するものの2つがあり、同時に削除される為、カスケード削除扱いとなりトリガーが実行されないのです。(間違えてたら教えてください。でもたぶんあってる)
まとめ
レコードの添付ファイルを削除するときに動作させたいApexトリガーのDeleteは、基本的にContentDcumentによってトリガーさせます。ややこしすぎる。
そして認識間違えてたらこっそりおしえてください。
こっそりですよ。
レコードトリガーフローについて
疲れちゃったんで、続きは次の記事で出します。
お楽しみに!