diff --git a/docs/5.x/reference/element-types/categories.md b/docs/5.x/reference/element-types/categories.md index c3e491d7e..9a1480042 100644 --- a/docs/5.x/reference/element-types/categories.md +++ b/docs/5.x/reference/element-types/categories.md @@ -35,17 +35,17 @@ Read more about this [transition](https://craftcms.com/blog/entrification) on ou Every category belongs to a _category group_, which defines… - …a name; -- …a handle (used when referencing the group in queries and templates); +- …a handle (used when referencing the group in [queries](#querying-categories) and templates); - …the maximum number of levels categories can be nested, within the group; -- …the format of category URIs; -- …which template should be rendered when a category’s URL is accessed; +- …the format of category URIs used for [routing](#routing-and-templates); +- …which [template](#routing-and-templates) should be rendered when a category’s URL is accessed; - …which [fields](../../system/fields.md) categories in the group should have; -To create a new category group, go to **Settings** → **Categories** and click **New Category Group**. +To create a new category group, go to and click **New Category Group**. ## Category Field Layout -Each category group has its own _field layout_, which allows you to customize the data that’s associated with each category in the group. By default, every category will have a **Title** field (the category name). Any available field type can be added to a category group’s field layout. +Each category group has its own _field layout_, which allows you to customize the data that’s associated with each category in the group. By default, categories only have a **Title** and **Slug**, but you can add as many other [custom fields](../../system/fields.md) as necessary to satisfy your content architecture. @@ -74,18 +74,36 @@ When you create a category, you have the following options: - Fill out the category fields (if you didn’t define any, the only field available will be **Title**) - Edit the slug (it’s automatically populated based on the title). -- Choose a Parent category. The new category will have a hierarchical relationship with its parent. This is helpful for creating taxonomies with multiple levels. You also have the option of creating a new category while assigning the Parent. +- Choose a **Parent** category. The new category will have a hierarchical relationship with its parent. This is helpful for creating taxonomies with multiple levels. You also have the option of creating a new category while assigning the Parent. ::: tip -You can only nest categories up to the level specified in the **Max Level** field Category Group settings. If it’s empty, the nesting level is unlimited. +You can only nest categories up to the level specified in the **Max Level** field Category Group settings. By default, there is no limit to how deeply-nested categories can be. ::: ## Assigning Categories -To assign categories to things (entries, assets, users, etc.), you must first create a [Categories field](../field-types/categories.md). +To assign categories to things (entries, assets, users, etc.), you must first create a [categories field](../field-types/categories.md). Each Categories field is connected to a single category group. Whatever you attach the field to will store [relations](../../system/relations.md) to categories selected from that group. +## Routing and Templates + +Category groups’ **URI Format** setting is equivalent to that of [entries](entries.md), so any of the [object template](../../system/object-templates.md) strategies discussed in [this section](entries.md#entry-uri-formats) apply to categories, as well. + +When a category’s URL is requested, Craft renders the template defined by its group, and makes a special `category` variable available. Supposing a _Flavors_ category group had a **URI Format** of `flavors/{slug}` and was configured to use `_categories/flavors.twig` as its **Template**: + +```twig +{{ category.title }} +{# -> "Sour Aromatics" #} + +{{ category.ancestors.collect() + .select('title') + .join(' / ') }} +{# -> "Sour & Fermented / Sour" #} +``` + +Custom fields attached to the group’s field layout are also available via the `category` variable. + ## Querying Categories You can fetch categories in your templates or PHP code using **category queries**. @@ -107,17 +125,17 @@ Once you’ve created a category query, you can set [parameters](#parameters) on ### Example -We can display a navigation for all the categories in a category group called “Topics” by doing the following: +We can display a navigation for all the categories in a _Flavors_ category group by doing the following: 1. Create a category query with `craft.categories()`. -2. Set the [group](#group) parameter on it. +2. Set the [group](#group) parameter on it using its handle. 3. Fetch the categories with `.all()`. 4. Loop through the categories using a [nav](../twig/tags.md#nav) tag to create the navigation HTML. ```twig {# Create a category query with the 'group' parameter #} {% set myCategoryQuery = craft.categories() - .group('topics') %} + .group('flavors') %} {# Fetch the categories #} {% set categories = myCategoryQuery.all() %} @@ -137,11 +155,13 @@ We can display a navigation for all the categories in a category group called ``` +Keep in mind that this only holds value for category groups with multiple hierarchical levels. If you were working with a “flat” taxonomy, the template above can use a `{% for %}` tag in lieu of Craft’s `{% nav %}` tag. + ::: tip To maintain the exact order you see in the control panel, add `orderBy('lft ASC')` to your query: ```twig {% set myCategoryQuery = craft.categories() - .group('topics') + .group('flavors') .orderBy('lft ASC') %} ``` ::: @@ -150,19 +170,33 @@ To maintain the exact order you see in the control panel, add `orderBy('lft ASC' When you’ve attached a [categories field](../field-types/categories.md) to another type of element, you can query for those elements when you have a reference to a category. -For example, if we were building a blog with dedicated “Topic” (category) pages, we might build a query like this to look up posts: +For example, if we were building a “Tasting Notes” database with dedicated _Flavor_ (category) pages, we might build a query like this to look up records: ```twig -{% set posts = craft.entries() +{% set records = craft.entries() .relatedTo({ targetElement: category, - field: 'topics', + field: 'flavors', }) .all() %} ``` +::: tip +Here, `flavors` also happens to be the handle of the relational field. _You do not need to follow any kind of convention when naming relational fields_; the groups available for selection in a given categories field are explicitly defined on that field. +::: + +You can also use the field’s query method to set up the relational constraint, automatically: + +```twig +{% set records = craft.entries() + .flavors(category) + .all() %} +``` + +In both cases, we’re assuming the `category` variable comes from Craft, when loading an individual category’s [template](#routing-and-templates). + ### Parameters Category queries support the following parameters: diff --git a/docs/5.x/reference/element-types/entries.md b/docs/5.x/reference/element-types/entries.md index 656e1d950..9c8ef0373 100644 --- a/docs/5.x/reference/element-types/entries.md +++ b/docs/5.x/reference/element-types/entries.md @@ -156,12 +156,32 @@ You can supplement the automatic [sources](../../system/elements.md#sources) pre ### Entry URI Formats -Channel and structure sections can choose whether their entries should be assigned URLs in the system by filling in the **Entry URI Format** setting. Singles have a “URI” setting, but it is typically defined statically or omitted (if it doesn’t need its own URL). +Channel and structure sections can choose whether their entries should be given URLs in the system by filling in the **Entry URI Format** setting. Singles also have this setting, but it is typically a static path or omitted (if it doesn’t need its own URL, like a [global set](globals.md)). The entry URI format is an [object template](../../system/object-templates.md), which gets evaluated each time an entry in the section is saved. The result is saved as the entry’s **URI** in the system, and is used to generate URLs (i.e. via `entry.url`) and when Craft is determining how to [route](../../system/routing.md) a request. When Craft matches a request to an entry, its section’s designated **Template** is rendered. That template is automatically provided an `entry` variable, set to the resolved object, and ready to output any of its attributes or custom field data. +#### URI Recipes + +Consider these tips for creating special URIs: + +- A URI that evaluates to `__home__` (and nothing more) will be available at your site’s base path; +- An empty URI means the entry does not get a route and will not have a public URL—unless you define one manually via `routes.php`; +- Any Twig statement can be used to output values in a URI template—including ones that query for other elements, e.g. `{{ craft.entries().section('mySingle').one().slug }}/news` (see note below); +- [Aliases](../../configure.md#aliases-and-environment-variables) can be evaluated with the [`alias()` function](../twig/functions.md#alias): `{{ alias('@basePressUri') }}/news`, `{{ alias('@mySectionUri') }}`. +- The [null-coalescing operator](https://twig.symfony.com/doc/3.x/templates.html#other-operators) (`??`) can silently swallow undefined variable errors (like `parent.uri`, above); + +::: warning +Elements accessed via the current `object` (like authors or relational fields) will be loaded in the appropriate site, but _new_ element queries (like the example above that uses `craft.entries()`), must explicitly use `.site()` to avoid loading elements in the default site: + +``` +{craft.entries().section('mySingle').site(object.siteId).one().slug} +``` + +The current element’s site ID can always be accessed via `object.siteId`. +::: + #### Hierarchical URIs Structure sections may benefit from nested paths, for child entries: @@ -186,21 +206,15 @@ The above template could also be expressed with this syntax: With the above Entry URI Format, a top-level entry’s URI would be `earth/south-america`, with a nested entry having `earth/south-america/chile`. -::: tip -Consider these tips for creating special URIs: - -- A URI that evaluates to `__home__` (and nothing more) will be available at your site’s base path; -- An empty URI means the entry does not get a route and will not have a public URL—unless you define one manually via `routes.php`; -- Any Twig statement can be used to output values in a URI template—including ones that query for other elements, e.g. `{{ craft.entries().section('mySingle').one().slug }}/news`; -- [Aliases](../../configure.md#aliases-and-environment-variables) can be evaluated with the [`alias()` function](../twig/functions.md#alias): `{{ alias('@basePressUri') }}/news`, `{{ alias('@mySectionUri') }}`. -- The [null-coalescing operator](https://twig.symfony.com/doc/3.x/templates.html#other-operators) (`??`) can silently swallow undefined variable errors (like `parent.uri`, above); -::: - #### Nested Entry URLs -[Nested entries](#nested-entries) in Matrix fields can also be configured to have URLs—but the settings are part of the field, not a section. +[Nested entries](#nested-entries) in [Matrix fields](../field-types/matrix.md) can also be configured to have URLs—but the settings are part of the field, not a section. As a result, entries of a given [type](#entry-types) may have URLs in some contexts, and not in others! -A single entry type may have URLs in some contexts, and not in others! +In a nested entry’s URI format, you can access the _owner_’s attributes using `{owner.someAttribute}`: + +``` +{owner.uri}/steps/{slug} +``` ### Preview Targets Team Pro