craft-content-modeling について
craft-content-modelingは、Craft CMS 5のコンテンツアーキテクチャを設計するスキルです。開発者やコンテンツ設計者がセクション、エントリータイプ、フィールド、関連付けを選ぶ際に、エントリー中心のモデルを踏まえて案内します。
主な機能
- 01コンテンツに応じたセクションタイプの選択
- 02再利用可能なエントリータイプとフィールドの設計
- 03コンテンツ関連とMatrix利用の計画
- 04Craft 5のエントリー中心モデルの解説
- 05エディションと権限の考慮
- 06予約済みフィールドハンドルの確認
活用シーン
- 01ブログ、階層ページ、サイト全体設定の設計
- 02エントリーとセクションによる分類体系の計画
- 03コンテンツエントリー間の関連方法の選択
- 04コンテンツモデル定義前のフィールドハンドル確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ michtio/ craftcms-claude-skills --skill craft-content-modelingインストール後、Claude Code で/craft-content-modelingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/content-patterns.mdelement-index-sources.mdfield-types.mdinfrastructure.mdobject-templates.mdrelations-and-eager-loading.mdusers-and-permissions.md詳細
Craft CMS 5 — コンテンツモデリング
Craft CMS 5 でのコンテンツ構造の設計方法。セクション、エントリータイプ、フィールド、Matrix、 リレーション、アセット管理、実際のプロジェクトに役立つ戦略的なパターンを扱います。
このスキルでは、コンテンツアーキテクチャ、つまり CP に何を配置し、どのように整理し、テンプレートからどうアクセスするかを扱います。PHP(プラグイン、モジュール、カスタムエレメントタイプ)で Craft を拡張する方法については、craftcms スキルを参照してください。
関連スキル — 必ず一緒に読み込む
このスキルが適用される場合は、以下も読み込んでください。
craft-site— テンプレートアーキテクチャ、コンポーネントのパターン、ルーティング。コンテンツに関する決定がテンプレートでのデータ表示に影響する場合に必須です。craft-twig-guidelines— Twig のコーディング標準。コンテンツモデリングと併せて Twig の例やテンプレートコードを書く場合に必須です。ddev— すべてのコマンドは DDEV 経由で実行します。プロジェクト設定コマンド、Craft CLI、コンテンツのマイグレーションの実行に必須です。
ドキュメント
- エントリー:https://craftcms.com/docs/5.x/reference/element-types/entries.html
- セクション:https://craftcms.com/docs/5.x/reference/element-types/entries.html#sections
- フィールド:https://craftcms.com/docs/5.x/system/fields.html
- フィールドタイプ:https://craftcms.com/docs/5.x/reference/field-types/
- Matrix:https://craftcms.com/docs/5.x/reference/field-types/matrix.html
- リレーション:https://craftcms.com/docs/5.x/system/relations.html
- 先行読み込み:https://craftcms.com/docs/5.x/development/eager-loading.html
- プロジェクト設定:https://craftcms.com/docs/5.x/system/project-config.html
参照ファイルで詳細が不十分な場合は、WebFetch を使って該当するドキュメントページを参照してください。
Craft 5 の基本的な考え方
すべてがエントリーになりつつあります。 エントリータイプはグローバルであり(セクション間や Matrix フィールド間で共有されます)、フィールドはグローバルプールから使用します。これは Craft の「エントリー化」です。カテゴリー、タグ、グローバルは、3つのバージョンをかけて統合されます。
- Craft 4.4 — カテゴリー、タグ、グローバルをエントリーに変換する
entrifyCLI コマンドが追加されました - Craft 5 — カテゴリー、タグ、グローバルセットは非推奨となり、新規プロジェクトでは推奨されません。新しいカテゴリーグループ、タググループ、グローバルセットも引き続き CP で作成できます(
allowAdminChangesによる制限のもと、「新規」ボタンは引き続き表示されます)。既存のものも引き続き動作します。分割されていたエントリービューは、統合された「コンテンツ」セクションに置き換わります。カスタムエントリーインデックスページ(5.9.0)により、サイドバーの整理に関する懸念が解消されます。 - Craft 6 — カテゴリー、タグ、グローバルセットは完全に削除されます
新規プロジェクトでは、常にエントリーを使用してください。階層型の分類には Structure セクション、フラットな分類には Channel セクション、サイト全体の設定には Singles を使います。既存プロジェクトでは、entrify コマンドを使って、自分のペースで移行してください。
コンテンツアーキテクチャを決める要素は、次の3つです。
- コンテンツを整理するセクションタイプ(Single、Channel、Structure)
- コンテンツの形を定義するエントリータイプ(グローバルで、さまざまなコンテキストで再利用可能)
- コンテンツ同士をつなぐリレーション戦略(Entries フィールド、Matrix、CKEditor のネストされたエントリー、またはこれらの組み合わせ)
CMS エディション
Craft CMS には4つのエディション(Solo、Team、Pro、Enterprise)があり、コンテンツモデリングに影響します。重要な違いは、複数のカスタムユーザーグループを作成し、グループごとに編集・閲覧の制限を設定する必要がある場合、Pro または Enterprise が必要になる点です(複数のカスタムユーザーグループを利用できるのは Pro 以上です)。Team では、管理者以外の権限をカスタマイズできる固定の「Team」グループが1つ含まれ、ユーザー数は5人までです。エディション一覧と権限アーキテクチャの詳細は、references/users-and-permissions.md を参照してください。
モデリングを始める前にエディションを選択してください。エディションによって、ユーザーグループごとにコンテンツへのアクセスを制限できるかどうかが決まり、セクションやフィールドの設計にも影響します。
セクションタイプの決定
| 必要なもの | セクションタイプ | URI の例 |
|---|---|---|
| 単独ページ(ホームページ、概要、問い合わせ先) | Single | __home__、about |
| サイト全体の設定(フッター、ヘッダー設定) | Single(URI なし、preloadSingles) | — |
| フラットなコレクション(ブログ、ニュース、イベント) | Channel | blog/{slug} |
| 階層型ページ(ドキュメント、サービス) | Structure | {parent.uri}/{slug} |
| タクソノミー(トピック、カテゴリ) | Structure(カテゴリを置き換えます) | topics/{slug} |
| フラットなタグ | Channel(タグを置き換えます) | — |
セクションのプロパティ
タイプに加えて、セクションにはコンテンツアーキテクチャに関わる設定があります。
maxAuthors(デフォルトは 1) — エントリーに複数の作成者を設定できます(5.0.0 で追加)。共同制作コンテンツでは値を大きく設定します。minAuthors(デフォルトは 1、5.10 で追加) — エントリーの保存に必要な作成者の最小人数です。すべてのエントリーに少なくとも 1 人の作成者を必須にするには、1に設定します。保存時に検証されます。minAuthors > maxAuthorsの設定は、Craft のセクションバリデーターによって拒否されます。maxAuthorsと組み合わせると、範囲を厳密に定義できます(min: 1, max: 3=「作成者が 1~3 人必要」)。enableVersioning(デフォルトは true) — エントリーのバージョン履歴です。defaultPlacement— ストラクチャーで新しいエントリーを配置する位置として、'beginning'または'end'を指定します。previewTargets— エントリーのプレビュー先を定義する{label, urlFormat}オブジェクトの配列です。デフォルトはメインのエントリーページです。ヘッドレスフロントエンド、ステージング URL、PDF プレビュー用にカスタムターゲットを追加します。
シングルでグローバルを置き換える
config/general.php で preloadSingles => true を設定すると、シングルにハンドル名でグローバルな
Twig 変数としてアクセスできます。これは、下書き、
リビジョン、ライブプレビュー、予約公開に対応した、従来のグローバルと同じ動作です。
{# With preloadSingles enabled #}
{{ siteSettings.footerText }}
{{ siteSettings.socialLinks.all() }}
注意点: シングルは常にすべてのサイトに伝播します。これはコードにハードコーディングされています。
ナビゲーション用のストラクチャークエリ
{% set topLevel = craft.entries.section('pages').level(1).all() %}
{% set children = craft.entries.descendantOf(entry).descendantDist(1).all() %}
{% set breadcrumbs = craft.entries.ancestorOf(entry).all() %}
{% set siblings = craft.entries.siblingOf(entry).all() %}
Craft 5 のエントリータイプ
エントリータイプはグローバルに定義し(Settings → Entry Types)、その後セクションや Matrix フィールドに割り当てます。1 つのエントリータイプを複数のコンテキストで使用できます。
主な影響:
- エントリータイプのフィールドレイアウトを変更すると、それを使用するすべてのセクションと Matrix フィールドに影響します。
- フィールドはグローバルプールから取得され、同じフィールド定義をどこでも再利用します。
- コンテキストごとに名前/ハンドル/説明を上書きできます(5.6.0 以降)。同じエントリータイプを異なるセクションで別の目的に使う場合に便利です。
- グローバルプールでは、フィールド名を慎重に付ける必要があります。具体的なハンドルを使用してください。
エントリータイプのビジュアルアイデンティティ(Craft 5 の新機能)
エントリータイプには、編集作業を快適にするビジュアルプロパティがあります。
icon— カスタムアイコン識別子です。エントリータイプセレクターや Matrix の「+」メニューに表示されます。color— 20 色の選択肢(red、orange、amber、yellow、lime、green、emerald、teal、cyan、sky、blue、indigo、violet、purple、fuchsia、pink、rose、white、gray、black)から選択します。description(5.8.0) — このエントリータイプの用途を説明するヘルプテキストです。group(5.8.0) — セクション/Matrix のエントリータイプ割り当てで折りたたみ可能なグループを作成します。uiLabelFormat(5.9.0) — 要素インデックスに表示されるラベルをカスタマイズします(デフォルトは'{title}')。hasTitleField/titleFormat— タイトルフィールドを無効にし、ほかのフィールドから自動生成します。showSlugField(5.0.0) /showStatusField(4.5.0) — 編集者にスラッグまたはステータスを表示しないようにします。allowLineBreaksInTitles(5.9.0) — 長文形式のタイトルに使用します。
これらの設定は Settings → Entry Types で構成し、エントリータイプが使用されるすべてのコンテキストに影響します。
予約済みハンドル — 提案するすべてのフィールドハンドルをこのリストと照合してください
Craft には、Field::RESERVED_HANDLES を通じてすべての要素タイプにわたる83 個以上の予約済みハンドルがあります。検証では大文字と小文字が区別されません。これらをカスタムフィールドのハンドルとして使用すると、検証エラーが発生するか、ネイティブ属性がカスタムフィールドをシャドーイングしてテンプレートで衝突が発生します。
コンテンツモデルでフィールドハンドルを提案する前に、必ず以下のリストと照合してください。 ユーザーがネイティブ属性名と一致するフィールドを求めた場合は、必ずドメイン固有の同義語を使ってください。たとえば、ユーザーが「タイトルフィールドが必要です」と言った場合、そのエントリにはすでにネイティブの title があるため、文脈に応じて heading、headline、または pageTitle を使います。
特に衝突しやすいもの(実際に使おうとしがちなもの):
| 予約済み | 代わりに使用 | 理由 |
|---|---|---|
title | heading、headline、label、pageTitle | ネイティブ要素のタイトル |
slug | urlSlug、handle | ネイティブ URL スラッグ |
status | state、phase、condition | ネイティブ要素のステータス |
url | externalUrl、targetUrl、websiteUrl | ネイティブ要素の URL |
link | targetLink、ctaLink、primaryLink | ネイティブの getLink() メソッド |
icon | entryIcon、menuIcon、featureIcon | ネイティブ要素のアイコン(5.0.0) |
parent | parentEntry、parentItem、belongsTo | ネイティブ構造の親 |
children | childEntries、subItems、nestedItems | ネイティブ構造の子 |
owner | entryOwner、ownerElement | ネイティブのネストされたエントリの所有者 |
site | location、branch、region | ネイティブのサイトオブジェクト |
level | depth、tier、nestingLevel | ネイティブ構造のレベル |
ancestors | parentChain、breadcrumbEntries | ネイティブ構造の祖先 |
siblings | peerEntries、relatedSiblings | ネイティブ構造の兄弟要素 |
enabled | isActive、isPublished、isVisible | ネイティブの有効/無効状態 |
language | locale、contentLanguage | ネイティブのサイト言語 |
localized | translations、localizedVersions | ネイティブのローカライズ済みエントリのクエリ |
next / prev | nextEntry / prevEntry | ネイティブ構造のナビゲーション |
ref | reference、referenceCode | ネイティブの参照タグ |
type | entryType、category、variant | ネイティブのエントリタイプ |
author / authors | writer、creator、contributor | ネイティブのエントリ作成者 |
postDate | publishDate、releaseDate、goLiveDate | ネイティブのエントリ投稿日 |
すべての要素タイプで共通する予約済みハンドルの完全なリスト(Field::RESERVED_HANDLES より):
ancestors、archived、attributes、behaviors、canonical、children、contentTable、dateCreated、dateDeleted、dateLastMerged、dateUpdated、descendants、draftId、enabled、enabledForSite、error、errors、fieldLayoutId、fieldValue、fieldValues、firstSave、icon、id、language、level、lft、link、localized、next、nextSibling、owner、parent、parents、prev、prevSibling、ref、revisionId、rgt、root、searchScore、siblings、site、siteId、siteSettingsId、slug、sortOrder、status、structureId、title、trashed、uid、uri、url、viewMode
要素タイプごとの追加の予約済みハンドル:
| 要素タイプ | 追加の予約済みハンドル |
|---|---|
| エントリ | author、authorId、authorIds、authors、section、sectionId、type、postDate |
| アセット | alt、extension、filename、folder、height、kind、size、volume、width |
| ユーザー | active、addresses、admin、affiliatedSiteId、email、firstName、friendlyName、fullName、groups、lastName、locked、name、password、pending、photo、suspended、username |
| カテゴリ | group |
| タグ | group |
| 住所 | address、countryCode、fullName、latLong、organization、organizationTaxId |
グローバルに予約済みの語句(HandleValidator::$baseReservedWords より。すべてのハンドルに適用):attribute、attributeLabels、attributeNames、attributes、dateCreated、dateUpdated、errors、false、fields、handle、id、n、name、no、rules、this、true、uid、y、yes
フィールドインスタンス — 重複ではなく再利用
フィールドはグローバルに一度だけ定義し、フィールドレイアウトにインスタンス化します。各インスタンスでは、グローバル定義に影響を与えずに、次の4つのプロパティを上書きできます。
- ラベル — コンテキストごとに異なる表示名
- ハンドル — コンテキストごとに異なるテンプレートハンドル(5.0.0+)
- 説明 — コンテキスト固有のヘルプテキスト
- 必須 — あるレイアウトでは必須、別のレイアウトでは任意
つまり、1つの heroImage Assets フィールドを、Blog Post、Service Page、Project エントリータイプに配置し、それぞれ異なるラベル(「ヒーロー画像」、「バナー」、「カバー写真」)や必須設定にできます。フィールドの定義、タイプ、設定は共有されます。
ルール:フィールド定義はインスタンスを使って再利用してください。新しいフィールドを作成するのは、タイプや設定が異なる場合だけです(例:使用可能なボリューム、ソースの制限、文字数制限が異なる場合)。blogHeroImage、serviceHeroImage、projectHeroImageを作成するのではなく、heroImageを1つ作成してインスタンス化してください。
ただし、現時点で2つのフィールドが似ているからといって、安易に再利用しないでください。 単一責任の原則(SRP)に照らして判断してください。文字数制限、翻訳方法、使用可能なボリュームなどについて、いずれかのインスタンスで異なる設定が必要になる妥当なケースはあるでしょうか? あるなら、その類似性は本質的なものではなく、偶然のものです。フィールドは分けてください。過度な再利用には、あとから変更しにくい次のようなコストが伴います。
- 検索ではインスタンスを区別できません。 インデックスにはインスタンスではなくフィールドに対してキーワードが記録されるため、
summary::daisyで同じフィールドのbylineインスタンスが一致することがあります(ドキュメントを参照)。フィールドごとに異なる検索結果が必要な場合は、フィールドを分ける必要があります。(上書きされたハンドルによるエレメントクエリのフィルタリング —.summary(x).byline(y)— は機能します。インスタンスを区別できないのは検索インデックスだけです。) - 一部のリレーショナルフィールドや
relatedToのケースでは、元のハンドルが必要になるとコミュニティから報告されています。再利用したフィールドの結果がおかしい場合は、ケースごとに確認してください。
マルチインスタンスフィールドとシングルインスタンスフィールド
フィールドのisMultiInstance()メソッドは、異なるハンドルを使って同じレイアウトに複数回配置できるかどうかを制御します。これはdbType()によって決まり、nullを返すフィールドはシングルインスタンスです。
| カテゴリー | フィールドタイプ | マルチインスタンス | レイアウト間で再利用可能 |
|---|---|---|---|
| リレーショナル | Entries、Assets、Categories、Tags、Users | はい | はい |
| シンプル | Plain Text、Number、Email、URL、Color、Lightswitch、Money、Range、Time、Date/Time | はい | はい |
| オプション | Dropdown、Checkboxes、Multi-Select、Radio Buttons、Button Group | はい | はい |
| 構造化 | Table、Link、Icon、Country | はい | はい |
| ネストされたエレメント | Matrix、Content Block、Addresses | いいえ | はい(注意点あり) |
シングルインスタンスの注意点: Matrix、Content Block、Addressesフィールドは、異なるエントリータイプ間で再利用(複数のフィールドレイアウトに配置)できますが、各レイアウトに配置できるのは1回だけであり、設定は完全に共有されます。Matrixフィールドのエントリータイプや設定を変更すると、そのフィールドを使用するすべてのエントリータイプに影響します。コンテキスト間で同じ構造を共有する場合は、これらのフィールドを再利用してください。ネストされたエントリータイプや設定がコンテキストごとに異なる場合は、フィールドを分けてください。
エントリータイプへのフィールド追加 — 既存フィールドの再利用を優先するワークフロー
コンテンツモデルの変更でフィールドを提案する前に、必ず以下を行ってください。
- 既存のフィールド一覧を確認します。
config/project/fields/(または「CP Settings → Fields」)を読み込みます。各フィールドのタイプ、ハンドル、主要な設定をすべて一覧にします。 - 提案する各フィールドを、次の3つのカテゴリのいずれかに分類します。
- 再利用 — タイプが一致し、設定に互換性のある既存フィールドです。レイアウトにインスタンス化し、必要に応じてラベル、ハンドル、説明、必須設定を上書きします。
- 設定を確認して再利用 — 正しいタイプですが、設定が少し異なる既存フィールドです(例:許可されるボリュームや文字数制限が異なる)。1つの定義で両方の用途に対応できるよう、設定を統一できるかを提案します。判断事項としてユーザーに提示してください。
- 新規作成 — タイプまたは機能上の用途が一致する既存フィールドがありません。新しいフィールドが必要な理由を説明してください。
- 単一インスタンスのフィールド(Matrix、Content Block、Addresses)について — 同じネスト構造を持つ既存フィールドがある場合は、それを再利用します。用途ごとに異なるネストされたエントリータイプや設定が必要な場合は、新規作成が妥当です。判断理由には共有設定に関する注意点を記載してください。
- 計画を表として提示します。 提案するフィールドごとに1行を設け、再利用の判断、再利用する既存フィールド(該当する場合)、新規フィールドを作成する場合はその理由を示します。この表を作成せずに新しいフィールドを作成してはいけません。
既存フィールドと機能が重複するフィールドを作成することは、コンテンツモデリングで最もよくある間違いです。グローバルなフィールド一覧が煩雑になり、編集者を混乱させ、将来のリファクタリングを難しくします。
エントリ化 — レガシーコンテンツの移行
CLI コマンド
ddev craft entrify/categories <categoryGroupHandle> # → Structure section
ddev craft entrify/tags <tagGroupHandle> # → Channel section
ddev craft entrify/global-set <globalSetHandle> # → Single section
3つのコマンドすべてで --section を指定すると、新しいセクションを作成せず、既存のセクションを対象にできます。entrify/categories と entrify/tags では、さらに --entry-type と --author も指定できますが、entrify/global-set では指定できません。
5.9.0 以降、これらのコマンドは対話形式になっており、ハンドル引数は省略できます。
各コマンドの動作
- 要素タイプをエントリーに変換します
- すべてのコンテンツとフィールドデータを移行します
- Categories/Tags フィールドを Entries フィールドに変換します
- 既存のリレーションを維持します
- 新しく作成したセクションを、適切なエントリーインデックスページに割り当てます
階層選択用の Entries フィールド
Categories フィールドを Entries フィールドに置き換える場合は、Entries フィールドで 階層を維持 を有効にしてください。これにより、ネストされたエントリーを選択したときに祖先も自動選択され、カテゴリフィールドと同じ動作を再現できます。
Tags を置き換える場合の注意点
編集者が用語をその場で作成していたフラットなタクソノミーでは、Entries フィールドでその場で作成する UX はまだ利用できません。これは、レガシーの Tags フィールドが UX 上の利点を保っている唯一の領域です。Channel セクションを使用し、エントリーを別途作成してから関連付ける2段階のワークフローを受け入れてください。
CKEditor と Matrix と Content Block
エントリー内の構造化コンテンツを扱う3つのツールです。編集体験に応じて選択してください。
- Matrix — 並べ替え可能なブロック、ページビルダー、データグリッド、メディアギャラリーに適しています。複数の表示モード(blocks、cards、cards-grid、index)があります。
- ネストされたエントリーを使う CKEditor — リッチテキストの中に構造化コンテンツ(画像ブロック、コードブロック、CTA など)をときどき挿入する場合に適しています。自然な文章作成の流れを保てます。
- Content Block(5.8.0)— 再利用可能なフィールドグループ(SEO メタデータ、バナー設定など)用の、繰り返し不可の単一ネストエントリーです。
詳しい判断表、ネストされたエントリータイプのパターン、CKEditor のチャンク描画パターンについては、references/content-patterns.md をお読みください。
セクション作成後 — Entries 要素のインデックスを整理する
Entries のソースをカスタマイズすると(ソースのカスタマイズ)、Craft はソースの完全なリストを config/project/project.yaml の elementSources.craft\elements\Entry に保存し、新しく作成したセクションを汎用的な列とともにリストの末尾に追加します。これはコンテンツモデルをリリースするうえで不完全な状態です。(ソースを一度もカスタマイズしていない場合、セクションはデフォルトの順序で表示されるため、整理は不要です。前提条件については element-index-sources.md を参照してください。)
必要な後続作業(セクションと同じ PR/変更セットで行ってください):
- 正しいサイドバー見出し(インデックス、カテゴリ、インクルードなど)の下で、同じ役割のセクションの隣にソースを配置します。
- 類似するセクション(例:FAQ インデックスとニュースインデックス、FAQ カテゴリとニュースカテゴリ)に合わせて、
tableAttributesとdefaultSortを設定します。 - セクションに公開 URL がある場合に限り
linkを含め、空のheading: ''の残りは削除します。
チェックリスト全体、役割別の表、および列のキーに関するルール(field: と fieldInstance:)については、references/element-index-sources.md をお読みください。
よくある落とし穴
- 新しいセクションのソースをエントリーのインデックスの末尾に置いたままにする — セクション/シングルの作成後は、
elementSourcesの配置とカラムを既存のものに合わせて整理してください。element-index-sources.mdを参照してください。未完成のモデルとは、FAQ Index がほかの Index と並んでいないまま FAQ を公開するモデルです。 - Matrix を使いすぎる — コンテンツに独自の URL、個別のクエリ、または権限が必要な場合は、Matrix ブロックではなく、Entries リレーションフィールドを持つ個別のセクションにする必要があります。
- グローバルプールを確認せずに新しいフィールドを作成する — フィールドを追加する前に、必ず上記の Reuse-First Workflow を実行してください。
config/project/fields/で既存のフィールドをすべて確認し、デフォルトではインスタンスを使って再利用します。新しいフィールドを作る正当な理由は、型が異なるか、設定に実質的な互換性がない場合のみです。 - 異なるニーズを持つインスタンス間で同じフィールドを再利用しすぎる — これは逆の間違いです。検索インデックスでは、再利用されたフィールドのインスタンスを区別できません(
summary::daisyがbylineのインスタンスに一致することがあります。ドキュメント)。また、一部のrelatedToのケースでは元のハンドルが必要です。インスタンスが実質的に同じフィールドである場合に限って再利用してください。異なる設定が妥当なケースがあり得るなら(単一責任の原則)、分けてください。まず再利用するのであって、常に再利用するわけではありません。 - 曖昧なフィールドハンドルや予約済みのフィールドハンドル —
image、text、linkは汎用的すぎます(また、linkは実際に予約されています)。コンテンツモデル内の各フィールドハンドルについて、次の手順で確認してください。(1)ハンドルが予約済みリストに含まれていますか?含まれている場合は、表から類義語を選びます。(2)グローバルフィールドプールで使うには汎用的すぎますか?そうであれば、featuredImage、bodyContent、primaryLinkのようにドメインの文脈を加えます。(3)過度に具体化しないでください。blogFeaturedImageを新しく作るより、featuredImageのインスタンスにラベルの上書きを設定できます。 - 最初からマルチサイトを計画しない — コンテンツが存在する前に、伝播方法、フィールドの翻訳方法、サイト設定を構成する必要があります。伝播方法を後から変更すると、すべてのエントリーが再保存されます。
- 新しいプロジェクトでカテゴリ/タグ/グローバルを使う — これらは Craft 5 で非推奨となり、推奨されていません(CP では引き続き作成できます)。Craft 6 で削除される予定です。代わりにエントリーを使ってください。
preloadSinglesを設定し忘れる — 設定しないと、シングルはグローバル変数として利用できず、明示的なクエリが必要になります。- 何でも Matrix にする — 1 つの Matrix フィールドに 15 種類以上のエントリータイプがあるのは危険信号です。Matrix の深いネストは
max_input_varsの制限に達し、CP のパフォーマンスを低下させます。 .eagerly()を使わない — ループ内でリレーショナルフィールドにアクセスする場合は毎回.eagerly()を使い、N+1 クエリを防いでください。- プロジェクト設定の YAML を手動で編集する —
config/project/の管理は Craft に任せてください。必要に応じて、ddev craft project-config/rebuildを使い、DB から再生成します。 - URI 形式にデータベース ID を使う — ID は環境によって異なります。
{slug}、{canonicalUid}、またはカスタムフィールドを使ってください。 - 本番環境で
allowAdminChanges => falseを設定しない — 設定しないと、本番環境でのスキーマ変更が開発環境に同期されません。 - ファイルシステムの URL に
@webを使う —@webは HTTP リクエストから自動検出されるため、偽装されたり、コンソール/キューのコンテキストでは空になったりする可能性があります。ファイルシステムの URL には、環境変数($ASSETS_URL)を使ってください。パスに@webrootを使う場合のリスクはより低いものの、環境変数が推奨されます。 - エントリータイプの視覚的な個性を無視する — 編集者はアイコン、色、説明を頼りに移動します。これらの設定に力を入れることで、コンテンツモデルの拡大に応じて CP が使いやすくなります。
- CMS のエディションを考慮しない — グループごとのコンテンツ権限が必要な場合は、Pro または Enterprise が必要です。これはセクションとフィールドの設計に影響します。
参考ファイル
タスクに関連する参考ファイルを読んでください。
タスクの例:
- 「既存のエントリータイプにフィールドを追加する」→ この SKILL.md の再利用優先ワークフロー
- 「エントリータイプのフィールドレイアウトを変更する」→ この SKILL.md の再利用優先ワークフロー
- 「ブログのコンテンツアーキテクチャを計画する」→
content-patterns.mdを読む - 「X にはどのフィールドタイプを使えばよいですか?」→
field-types.mdを読む - 「relatedTo クエリを設定する」→
relations-and-eager-loading.mdを読む - 「ネストされたエントリーを含む Matrix を設定する」→
field-types.md(Matrix セクション)を読む - 「マルチサイトのコンテンツモデルを計画する」→
content-patterns.mdとinfrastructure.md(プロパゲーション)を読む - 「ユーザー、グループ、権限を設定する」→
users-and-permissions.mdを読む - 「プロジェクト設定のワークフローを理解する」→
infrastructure.md(プロジェクト設定の基本)を読む - 「Craft がコンテンツを内部的にどのように保存するかを理解する」→
infrastructure.md(ストレージモデル)を読む - 「アセットボリュームとファイルシステムを設定する」→
infrastructure.md(アセットセクション)を読む - 「ストラクチャーセクションの URI 形式を設定する」→
object-templates.md(ストラクチャー URI パターン)を読む - 「動的なアセットアップロードのサブパスを設定する」→
object-templates.md(アセットサブパスパターン)を読む - 「フィールドを Matrix に移動した後、アセットサブパスが機能しなくなった」→
object-templates.md(Matrix の注意点)を読む - 「FAQ セクションを作成した後、エントリーのインデックスを整理する」→
element-index-sources.mdを読む - 「新しいセクションがエントリーの一番下に表示され、列も正しくない」→
element-index-sources.mdを読む - 「FAQ インデックス/カテゴリーのソースをニュースインデックス/カテゴリーのソースに合わせる」→
element-index-sources.mdを読む
| 参考資料 | 対象範囲 |
|---|---|
references/field-types.md | すべての組み込みフィールドタイプ:設定、Twig のアクセスパターン、クエリ構文、注意点。Matrix の設定、表示モード、ネスト。 |
references/relations-and-eager-loading.md | relatedTo() の形式(4 種類)、.with() による先行読み込み、.eagerly() による遅延先行読み込み、ネストされた先行読み込み、ネイティブの先行読み込み可能な属性。 |
references/content-patterns.md | ブログ、ポートフォリオ、マルチサイトの企業サイト向けの戦略的パターン。各パターンのセクション/フィールド/リレーションのアーキテクチャ。エントリー化の移行。CKEditor と Matrix の使い分け。 |
references/users-and-permissions.md | ユーザー、ユーザーグループ、CMS エディション、住所、権限アーキテクチャ、フィールドレイアウトの UI 要素。 |
references/infrastructure.md | マルチサイトのプロパゲーション方法、フィールドの翻訳方法、プロジェクト設定のワークフロー、Craft のコンテンツ保存方法(5 テーブルモデル、JSON フィールド値、リレーション、ネストセット)、アセットボリューム/ファイルシステム/変換。 |
references/object-templates.md | オブジェクトテンプレートの構文:{attribute} と {{ twig }}、URI 形式、アセットサブパス、プレビューターゲット、owner/rootOwner のネスト、ストラクチャーパターン、Matrix の注意点。 |
references/element-index-sources.md | プロジェクト設定におけるエントリーの CP インデックスソース:見出しの下への配置、同じ階層のセクションに合わせた tableAttributes/defaultSort、セクション追加後のチェックリスト。 |