You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/commerce/5.x/development/cart.md
+6-4Lines changed: 6 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -61,7 +61,7 @@ This is generally not necessary, and can have significant performance impacts on
61
61
62
62
To see what cart information you can use in your templates, take a look at the [Order](commerce5:craft\commerce\elements\Order) class reference. You can also refer to the example templates’ [`shop/cart/index.twig`](https://github.com/craftcms/commerce/blob/5.x/example-templates/dist/shop/cart/index.twig) file.
63
63
64
-
Once a cart is completed and turned into an order, accessing the current cart via either method starts this process over.
64
+
Once a cart is completed and becomes an order, accessing the current cart via either method starts this process over.
65
65
66
66
## Displaying Cart Contents
67
67
@@ -93,9 +93,9 @@ Craft includes a powerful [internationalization engine](guide:tutorial-i18n#plur
93
93
94
94
### Line Items
95
95
96
-
A cart’s contents are represented by _line items_. Line items are typically populated from [purchasables](../system/purchasables.md) when they are added to the cart, but [custom line items](#custom-line-items) can also be created on-the-fly. <Sinceproduct="commerce"ver="5.1.0"feature="Custom, ad-hoc line items" />
96
+
A cart’s contents are represented by _line items_. Line items are typically populated and refreshed from [purchasables](../system/purchasables.md) when they are added to the cart, but [custom line items](#custom-line-items) can also be created on-the-fly. <Sinceproduct="commerce"ver="5.1.0"feature="Custom, ad-hoc line items" />
97
97
98
-
Out-of-the-box, line items [variant](../system/products-variants.md), and have a quantity, description, notes, a calculated subtotal, options, adjustments (like tax and shipping costs), and other metadata. Most importantly, though, the line item retains a reference to its purchasable so that it can be refreshed with the latest information from your store while the customer is shopping.
98
+
Out-of-the-box, most line items represent a [variant](../system/products-variants.md), and have a quantity, description, notes, a calculated subtotal, options, adjustments (like tax and shipping costs), and other metadata. Most importantly, though, the line item retains a reference to its purchasable so that it can be refreshed with the latest information from your store while the customer is shopping. [Donations](../system/donations.md) are also added to the cart as line items.
99
99
100
100
::: tip
101
101
In the event a product or variant is altered or deleted after a customer checks out, enough information is memoized on each line item to reconstruct what was purchased, and how much was paid. Some of this is recorded directly on the line item (like [prices](#prices) and its [physical attributes](#physical-properties)), and some is stored as metadata (like [options](#line-item-options-and-notes) and [snapshots](../system/purchasables.md#snapshots)).
@@ -116,7 +116,9 @@ Line items are always returned as an array, even if there is only a single item
116
116
</ul>
117
117
```
118
118
119
-
You can get a line item’s source [purchasable](../system/purchasables.md) by calling `item.purchasable`. Let’s take a closer look at some other data available via line items.
119
+
You can get a line item’s source [purchasable](../system/purchasables.md) (most often a [variant](../system/products-variants.md#variants)) by calling `item.purchasable`, and the product a variant belongs to via `item.purchasable.product` or `item.purchasable.owner`.
120
+
121
+
Let’s take a closer look at some other data available via line items.
Copy file name to clipboardExpand all lines: docs/getting-started-tutorial/README.md
+7-1Lines changed: 7 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -21,6 +21,12 @@ If you get stuck, [join us on Discord](https://craftcms.com/discord)! We all wan
21
21
22
22
Craft is a flexible, user-friendly <abbrtitle="Content management system">CMS</abbr> for creating custom digital experiences on the web—and beyond.
23
23
24
-
You have a _ton_ of options when it comes to choosing a CMS. Craft is uniquely equipped to deliver high-quality, content-driven experiences to your clients and their audiences, in large part due to its blank-slate approach to content modeling.
24
+
You have a _ton_ of options when it comes to choosing a CMS. Craft is uniquely equipped to deliver high-quality, content-driven experiences to your clients and their audiences, in large part due to its blank-slate approach to content modeling and front-end development.
25
25
26
26
To demonstrate Craft’s agility, we’ll build a basic blog—and in doing so, touch a number of powerful tools that let you design, build, and manage _any_ kind of content.
27
+
28
+
## Editions + Licensing
29
+
30
+
Craft’s <Badgetype="edition"vertical="text-bottom">Solo</Badge> edition is free to use for personal projects. Everything we’ll cover in this tutorial is available in Solo, and you won’t be asked to sign up for accounts or add payment info. If you want to explore features of Craft’s <Badgetype="edition"vertical="text-bottom">Team</Badge> or <Badgetype="edition"vertical="text-bottom">Pro</Badge> editions, you are welcome to upgrade and test locally for as long as you like!
31
+
32
+
_Please note that installing any version of Craft binds you to our [Terms of Service](https://craftcms.com/terms-of-service) and [Acceptable Use Policy](https://craftcms.com/acceptable-use-policy)._
Copy file name to clipboardExpand all lines: docs/getting-started-tutorial/build/README.md
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -16,7 +16,7 @@ Craft supports two fundamentally different approaches to building a front-end:
16
16
::: tip
17
17
Both methods give you complete access to your content. You are free to choose one of these approaches, combine aspects that suit your project, switch between them at a later date, deploy both for different audiences, or come up with your own hybrid architecture!
18
18
19
-
Craft doesn’t dictate anything about how you consume your content—in fact, it can be used as a back-end for a native application or kiosk, a bare API… or have no front-end at all, and exist solely as a warehouse for structured data.
19
+
Craft doesn’t dictate _anything_ about how you consume your content—in fact, it can be used as a back-end for a native application or kiosk, a bare API… or have no front-end at all, and exist solely as a warehouse for structured data.
20
20
:::
21
21
22
22
This tutorial will focus on a “monolithic” architecture, due to its lack of external dependencies—however, we will touch on the [GraphQL API](../more/graphql.md) in the _More_ section.
Copy file name to clipboardExpand all lines: docs/getting-started-tutorial/build/blog-templates.md
+28-20Lines changed: 28 additions & 20 deletions
Original file line number
Diff line number
Diff line change
@@ -72,7 +72,7 @@ Create `templates/blog/_entry.twig` and paste this code to it:
72
72
The first highlighted line connects our post template with the layout template, using the `{% extends %}` tag. The second highlight defines a `{% block ... %}`, the content of which will be output in the corresponding region of `_layout.twig`.
73
73
74
74
::: tip
75
-
When using layouts, all output must be within `block` tag pairs—but you may have as many `block` tags as you wish!
75
+
When extending a layout, all output must be within `block` tag pairs—but you may have as many `block` tags as you wish!
76
76
:::
77
77
78
78
Now that the blog section’s template is ready, you can visit the URL for a published post:
@@ -120,7 +120,7 @@ If you were to go back into the control panel and create some more posts, you co
120
120
121
121
#### Feature Image
122
122
123
-
Let’s output the image we attached via [the “Feature Image” asset field](../configure/resources.md#feature-image). That field had a handle of `featureImage`, so it will be available on the `entry` variable as `entry.featureImage`, just like the title was:
123
+
Let’s display the image we attached via [the “Feature Image” asset field](../configure/resources.md#feature-image). When we attached the assets field to the _Post_ field layout, we gave it a handle of `featureImage`—so it will be available on the `entry` variable as `entry.featureImage`, just like its title was:
124
124
125
125
```twig{4,15-19}
126
126
{% extends '_layout' %}
@@ -171,6 +171,8 @@ If you would prefer to build the image element yourself, you can get the individ
171
171
height="{{ featureImage.height }}" />
172
172
```
173
173
174
+
Note the use of `featureImage.alt`! Craft automatically adds this attribute when building the tag itself—but it will be empty unless you add the **Alternative Text** field layout element to the volume’s field layout (and populate it with a description of the image).
175
+
174
176
</Block>
175
177
176
178
Refresh the page to see your changes:
@@ -241,9 +243,9 @@ If you pasted this into `templates/blog/_entry.twig` and the indentation got mes
241
243
242
244
Let’s output the [post content](../configure/resources.md#post-content) stored in our Matrix field. This process starts in a familiar way:
243
245
244
-
1. Load matrix blocks via the `postContent` field handle and store them in a variable;
245
-
1. Loop over those blocks with a `{% for %}` tag;
246
-
1. Render different content based on the blocks’ types, using an `{% if %}` tag;
246
+
1. Load the nested entries via the `postContent` field handle and store them in a variable;
247
+
1. Loop over those entries with a `{% for %}` tag;
248
+
1. Render different content based on the entries’ types, using an `{% if %}` tag;
247
249
248
250
After the line that declares our `topics` variable, add a new `set` tag:
249
251
@@ -254,7 +256,7 @@ After the line that declares our `topics` variable, add a new `set` tag:
254
256
{% set postContent = entry.postContent.all() %}
255
257
```
256
258
257
-
With the content loaded into a `postContent` variable, we can start outputting data for each block. Below the topics list, add a new `for` loop:
259
+
With the content loaded into a `postContent` variable, we can start outputting data for each block. Below the topics list and feature image, add a new `for` loop:
258
260
259
261
```twig{2,4,7,12,17,22}
260
262
<div class="post-content">
@@ -290,9 +292,9 @@ With the content loaded into a `postContent` variable, we can start outputting d
290
292
291
293
Looking at the highlighted lines in this block of code…
292
294
293
-
- Our `for` loop uses the `postContent` variable defined at the top of the template, and makes each block available in turn as `contentBlock`;
294
-
- We capture the “type” of block in a variable named `blockType` so we can compare against it later;
295
-
- The `if`, `elseif`, and `else` tags test the value of `blockType` each time through the loop and render different sections of the template;
295
+
- Our `for` loop uses the `postContent` variable defined at the top of the template, and makes each nested entry available in turn as `contentBlock`;
296
+
- We capture the “type” of entry in a variable named `blockType` so we can compare against it later;
297
+
- The `if`, `elseif`, and `else` tags test the value of `blockType` each time through the loop and render different parts of the template;
296
298
- “Image” blocks contain an asset field that can be used exactly the same way as the `featureImage` field is on the main entry;
297
299
- An `else` tag is used to provide some debugging information for us—but it will only show up if we’ve gotten our block type handles mixed up;
298
300
- A final `else` tag actually belongs to the main `for` loop, and allows us to output a message when there are no blocks to display;
@@ -305,11 +307,11 @@ How could we add a new _Quote_ block type?
1. Name it _Quote_, and give it a handle of `quote`;
311
-
1. Add a **Plain Text** field named _Quote_ (also with a handle of `quote`), and mark it as **Required**;
312
-
1. Save the field;
310
+
1. Visit <Journeypath="Settings, Fields, Post Content" />;
311
+
1.In the **Entry Types** selector, click **+ Create**;
312
+
1. Name the new entry type “Quote”, and give it a handle of `quote`;
313
+
1. Add our plain text field (_Text_) to its field layout, leaving the name and label as-is;
314
+
1. Save the entry type;
313
315
314
316
At this point, return to one of your blog entries’s edit screens, and add a **Quote** block to the **Post Content** matrix field. Reload that post’s page in the front-end, and you should see something like this:
315
317
@@ -321,9 +323,9 @@ In `templates/blog/_entry.twig`, add a new `elseif` comparison tag in the conten
{% else %} {# This `else` tag is what outputs our “unsupported” message! #}
328
+
{% else %} {# This `else` tag already exists, and is what outputs our “unsupported” message. #}
327
329
{# ... #}
328
330
```
329
331
@@ -378,19 +380,25 @@ Create a new template at `templates/blog/index.twig`, with the following content
378
380
{% endblock %}
379
381
```
380
382
383
+
In your browser, navigate to `https://tutorial.ddev.site/blog`, and verify you see all the posts you created via the control panel!
384
+
381
385
Notice that this template makes no reference to an `entry` variable. This is because it won’t be rendered based on an element’s URI format—Craft is just matching the request to `/blog` with a template.
382
386
383
-
That doesn’t mean we can’t access our content, though! The first highlighted line uses what’s called an _element query_. Element queries are different from the automatically-injected `entry` variable: instead of containing a _specific_ entry object, they define some _criteria_ for loading one or more entries from the database.
387
+
That doesn’t mean we can’t access our content, though! The first highlighted line uses what’s called an _element query_. Element queries are different from the automatically-injected `entry` variable: instead of containing a _specific_ entry object, they define some _parameters_ for loading one or more entries from the database.
384
388
385
389
Element queries are designed to be written and read in relatively plain language. Let’s break this one down:
386
390
387
391
1.`craft` is a global variable that collects a number of functions and features;
388
392
1.`.entries()` creates a new element query with specific functionality for fetching entries;
389
-
1.`.section()` configures the query to select only entries from the passed section(s);
393
+
1.`.section()` configures that query to select only entries from the passed section(s);
390
394
1.`.all()` executes the query and returns _all_ matching entries;
391
395
392
396
Most element queries will have steps 1 and 4 in common, but steps 2 and 3 are specific to our need to fetch _entries_ in a particular _section_. We’ll have a chance to use some more element query features in the next step!
393
397
398
+
::: tip
399
+
Craft sorts entries by their `postDate` (newest to oldest), by default.
400
+
:::
401
+
394
402
### Topic Pages
395
403
396
404
Now that our blog index displays a list of posts, let’s implement the topic index pages. Much of the display logic will remain consistent between them, so this template will look pretty familiar.
@@ -435,9 +443,9 @@ From the blog index, click through to one of your posts, then click the topic li
435
443
436
444
Like the blog index, we get a list of posts that each link out to their individual pages.
437
445
438
-
_Unlike_ the blog index, our topic template automatically has access to a `category` variable. This is because every topic page is backed by a category element, just like our individual post pages. It’s still up to us, though, to decide what other data should be displayed—and to fetch it with element queries.
446
+
_Unlike_ the blog index, our topic template automatically has access to a `category` variable. This is because every topic page is backed by a category element, just like our post entries. It’s still up to us, though, to decide what other data should be displayed—and to fetch it with element queries.
439
447
440
-
We’ve used the `category` variable in a new entry element query, near the top of the template:
448
+
We’ve used the `category` variable in a new entry query, near the top of the template:
441
449
442
450
```twig
443
451
{% set posts = craft.entries().section('blog').postCategories(category).all() %}
0 commit comments