Skip to content

Commit 1cb3540

Browse files
authored
Merge pull request #667 from craftcms/five-tutorial
Getting Started: 5.x
2 parents 700b130 + f0de52d commit 1cb3540

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+615
-500
lines changed

docs/.vuepress/components/Poi.vue

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ export default {
4848
methods: {
4949
activatePoi() {
5050
this.isActive = true;
51+
52+
const $browser = document.getElementById(this.target);
53+
54+
$browser.scrollIntoView({ behavior: 'smooth' });
5155
},
5256
deactivatePoi() {
5357
this.isActive = false;

docs/.vuepress/theme/global-components/Badge.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,15 @@ export default {
6262
border-width: 1px;
6363
border-color: var(--border-color);
6464
color: var(--sidebar-link-color);
65-
padding: 4px calc(5px - 0.1em) 4px 5px;
65+
padding: 4px calc(4px - 0.1em) 4px 5px;
6666
}
6767
6868
&.edition {
6969
@apply uppercase bg-transparent text-xs tracking-widest leading-none h-auto text-center font-medium;
7070
border-width: 1px;
7171
border-color: var(--text-color);
7272
color: var(--text-color);
73-
padding: 0.3em 0.4em 0.1em;
73+
padding: 0.35em 0.3em 0.2em 0.4em;
7474
}
7575
7676
& + & {

docs/.vuepress/theme/global-components/BrowserShot.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<template>
22
<component
33
class="browser-shot"
4+
:id="id"
45
:is="link ? 'a' : 'div'"
56
:href="link ? url : null"
67
:target="link ? '_blank' : null"

docs/4.x/installation.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,7 @@ While we [strongly recommend](#why-ddev) DDEV for new Craft projects, [alternate
4343
ddev composer create -y --no-scripts "craftcms/craft:^4"
4444
```
4545

46-
1. Run the Craft setup wizard, and accept all defaults (in `[square brackets]`):
47-
48-
```bash
49-
ddev craft install
50-
```
46+
The setup wizard will start automatically! Accept all defaults (in `[square brackets]`), and note your chosen username and password.
5147

5248
::: tip
5349
Our [First-Time Setup](kb:first-time-setup) guide in the Knowledge Base has more information about what to expect during setup.

docs/5.x/install.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,10 @@ While we [strongly recommend](#why-ddev) DDEV for new Craft projects, [alternate
3838
1. Scaffold the project from the official [starter project](https://github.com/craftcms/craft):
3939

4040
```bash
41-
ddev composer create -y --no-scripts "craftcms/craft"
41+
ddev composer create -y "craftcms/craft"
4242
```
4343

44-
1. Run the Craft setup wizard, and accept all defaults (in `[square brackets]`):
45-
46-
```bash
47-
ddev craft install
48-
```
44+
The setup wizard will start automatically! Accept all defaults (in `[square brackets]`), and note your chosen username and password.
4945

5046
::: tip
5147
Our [First-Time Setup](kb:first-time-setup) guide in the Knowledge Base has more information about what to expect during setup.

docs/commerce/5.x/development/cart.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ This is generally not necessary, and can have significant performance impacts on
6161

6262
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.
6363

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.
6565

6666
## Displaying Cart Contents
6767

@@ -93,9 +93,9 @@ Craft includes a powerful [internationalization engine](guide:tutorial-i18n#plur
9393

9494
### Line Items
9595

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. <Since product="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. <Since product="commerce" ver="5.1.0" feature="Custom, ad-hoc line items" />
9797

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.
9999

100100
::: tip
101101
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
116116
</ul>
117117
```
118118

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.
120122

121123
#### Prices
122124

docs/getting-started-tutorial/README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ If you get stuck, [join us on Discord](https://craftcms.com/discord)! We all wan
2121

2222
Craft is a flexible, user-friendly <abbr title="Content management system">CMS</abbr> for creating custom digital experiences on the web—and beyond.
2323

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.
2525

2626
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 <Badge type="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 <Badge type="edition" vertical="text-bottom">Team</Badge> or <Badge type="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)._

docs/getting-started-tutorial/build/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Craft supports two fundamentally different approaches to building a front-end:
1616
::: tip
1717
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!
1818

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.
2020
:::
2121

2222
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.

docs/getting-started-tutorial/build/blog-templates.md

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ Create `templates/blog/_entry.twig` and paste this code to it:
7272
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`.
7373

7474
::: 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!
7676
:::
7777

7878
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
120120

121121
#### Feature Image
122122

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:
124124

125125
```twig{4,15-19}
126126
{% extends '_layout' %}
@@ -171,6 +171,8 @@ If you would prefer to build the image element yourself, you can get the individ
171171
height="{{ featureImage.height }}" />
172172
```
173173

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+
174176
</Block>
175177

176178
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
241243

242244
Let’s output the [post content](../configure/resources.md#post-content) stored in our Matrix field. This process starts in a familiar way:
243245

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;
247249

248250
After the line that declares our `topics` variable, add a new `set` tag:
249251

@@ -254,7 +256,7 @@ After the line that declares our `topics` variable, add a new `set` tag:
254256
{% set postContent = entry.postContent.all() %}
255257
```
256258

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:
258260

259261
```twig{2,4,7,12,17,22}
260262
<div class="post-content">
@@ -290,9 +292,9 @@ With the content loaded into a `postContent` variable, we can start outputting d
290292

291293
Looking at the highlighted lines in this block of code…
292294

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;
296298
- “Image” blocks contain an asset field that can be used exactly the same way as the `featureImage` field is on the main entry;
297299
- 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;
298300
- 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?
305307

306308
Back in the control panel:
307309

308-
1. Visit **Settings** &rarr; **Fields** &rarr; **Post Content**;
309-
1. Click **New Block Type**;
310-
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 <Journey path="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;
313315

314316
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:
315317

@@ -321,9 +323,9 @@ In `templates/blog/_entry.twig`, add a new `elseif` comparison tag in the conten
321323
{# ... #}
322324
{% elseif blockType == 'quote' %}
323325
<div class="content-block quote">
324-
<blockquote>{{ contentBlock.quote | md }}</blockquote>
326+
<blockquote>{{ contentBlock.text | md }}</blockquote>
325327
</div>
326-
{% else %} {# This `else` tag is what outputs our “unsupported” message! #}
328+
{% else %} {# This `else` tag already exists, and is what outputs our “unsupported” message. #}
327329
{# ... #}
328330
```
329331

@@ -378,19 +380,25 @@ Create a new template at `templates/blog/index.twig`, with the following content
378380
{% endblock %}
379381
```
380382

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+
381385
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.
382386

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.
384388

385389
Element queries are designed to be written and read in relatively plain language. Let’s break this one down:
386390

387391
1. `craft` is a global variable that collects a number of functions and features;
388392
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);
390394
1. `.all()` executes the query and returns _all_ matching entries;
391395

392396
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!
393397

398+
::: tip
399+
Craft sorts entries by their `postDate` (newest to oldest), by default.
400+
:::
401+
394402
### Topic Pages
395403

396404
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
435443

436444
Like the blog index, we get a list of posts that each link out to their individual pages.
437445

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.
439447

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:
441449

442450
```twig
443451
{% set posts = craft.entries().section('blog').postCategories(category).all() %}

0 commit comments

Comments
 (0)