サイト名で SiteId を解決する(GetClosestSiteId)
API やサーバースクリプトで操作するサイトは SiteId(数値)で指定しますが、SiteId は環境ごとに違います。サイトに「サイト名」(SiteName)を付けておき、実行時に名前から SiteId を引くようにすると、スクリプトや連携定義を書き換えずに別の環境へ持っていけます。このページでは、名前から SiteId を引く仕組みと、その注意点をまとめます。
INFO
実装の根拠は、確認時のソースへの固定リンクで示しています。
サイト名(SiteName)
サイトの編集画面の「サイト名」に入れた値が Sites.SiteName に入ります。フォルダ・期限付きテーブル・記録テーブル・Wiki・ダッシュボードのどれでも入力できます(SiteUtilities.cs#L6248-L6256)。
| 項目 | 値 |
|---|---|
| 型 | nvarchar(32)(最大 32 文字。Sites_SiteName.json) |
| 一意制約 | なし。同じテナントに同名のサイトを作れる |
| タイトルとの違い | タイトルは画面に出す名前、サイト名はプログラムから引くための識別名 |
サイトパッケージのエクスポート・インポートでは、SiteName はそのまま引き継がれます(SiteId は採番し直されます。Utilities.cs#L228)。移行元でサイト名を付けておけば、移行先でも同じ名前で引けます。
名前から SiteId を引く 3 つの方法
| 使う場所 | 書き方 | 戻り値 |
|---|---|---|
| Web API | POST /api/items/{起点のサイト ID}/GetClosestSiteId | 名前ごとの SiteId(見つからなければ -1) |
| サーバースクリプト | items.GetClosestSite(サイト名, 起点のサイト ID) | サイトの apiModel(見つからなければ null) |
| スクリプト | $p.apiGetClosestSiteId({ id: 起点のサイト ID, data: {...} }) | Web API と同じ |
Web API
{
"ApiVersion": 1.1,
"ApiKey": "your-api-key",
"FindSiteNames": ["CustomerMaster", "Projects"]
}{
"StatusCode": 200,
"SiteId": 12345,
"Data": [
{ "SiteName": "CustomerMaster", "SiteId": 67890 },
{ "SiteName": "Projects", "SiteId": -1 }
]
}URL の {id} は探索の起点になるサイトで、操作対象ではありません。レスポンスの SiteId には起点の ID がそのまま返ります。FindSiteNames がないと 400 です(SiteUtilities.cs#L20127-L20179)。次の場合、その名前の SiteId は -1 になります。
- 名前が空
- 起点のサイトに読み取り権限も作成権限もない
- 名前に一致するサイトが見つからない
- 見つかったサイトに読み取り権限も作成権限もない
サーバースクリプト
// 起点を省略すると、サーバースクリプトを実行しているサイトが起点になる
const site = items.GetClosestSite('CustomerMaster');
if (site !== null) {
const records = items.Get(site.SiteId, JSON.stringify({
View: { ColumnFilterHash: { ClassA: model.ClassA } }
}));
if (records.Length > 0) {
model.ClassB = records[0].ClassB;
}
}引数は「サイト名」「起点のサイト ID(省略可)」の順です(ServerScriptModelApiItems.cs#L77-L86)。見つかったサイトを items.GetSite() と同じ形の apiModel で返し、名前が空・見つからない・起点か見つかったサイトの権限がない場合は null を返します(ServerScriptUtilities.cs#L1534-L1565)。
スクリプト
$p.apiGetClosestSiteId は /api/items/{id}/getclosestsiteid を呼ぶだけのラッパーです(_api.js#L164-L166)。画面のセッションで認証するので ApiKey は要りません。
$p.apiGetClosestSiteId({
id: $p.siteId(),
data: { FindSiteNames: ['CustomerMaster'] },
done: function (data) {
console.log(data.Data[0].SiteId);
}
});同名のサイトがあるときの探索順
名前の解決は、テナントのサイト情報キャッシュに持っている SiteNameTree が行います。サイト情報が更新されるたびに作り直されます(SiteInfo.cs#L536-L547)。
SiteNameTree.Find() の動きは次のとおりです(SiteNameTree.cs#L40-L110)。
図を読み込み中…
- テナント内に同名のサイトが 1 件しかなければ、どこにあってもそのサイトを返します。
- 複数あるときは、起点から近いフォルダにあるものが選ばれます。起点に指定したサイトが存在しないと
-1です。 - 探索結果はキャッシュされます(1,024 件を超えると最も古く記録したものから消します)。
- 権限の確認は、探索で選ばれた 1 件に対してだけ行います。選ばれたサイトに権限がないと、ほかの同名サイトを探し直さずに「見つからない」扱いになります。
運用の目安
同名サイトの扱いに頼らず、テナント内でサイト名が重ならないように命名規則を決めておくのが安全です(例: SYS_CustomerMaster のように用途の接頭辞を付ける)。
統合サイト(IntegratedSites)での名前指定
一覧で複数サイトのレコードをまとめて表示する統合サイトの設定でも、サイト名が使えます(SiteSettings.cs#L5470-L5492)。こちらは GetClosestSiteId とは違い、近さでは選びません。
- テナント内のサイトのうち、
SiteNameかSiteGroupName(サイトグループ名)が一致するものをすべて対象にする - 名前で 1 件も一致しなければ、値を数値として
SiteIdとみなす
関連ページ
- API ラッパーの対応表 —
items.GetSiteByNameなど、サーバースクリプトのサイト検索メソッド - サイトの移動抑止・アーカイブ管理・サイト構成一覧