Skip to content

Commit

Permalink
Merge branch 'main' into add-docker-hosting
Browse files Browse the repository at this point in the history
  • Loading branch information
shyim authored Nov 6, 2024
2 parents 776e886 + 970882a commit f4b95f5
Show file tree
Hide file tree
Showing 28 changed files with 469 additions and 161 deletions.
1 change: 1 addition & 0 deletions .github/scripts/format-adrs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as path from "https://deno.land/[email protected]/path/mod.ts";
const formattingPromises = [];
for await (const entry of walk("./resources/references/adr")) {
if (entry.isDirectory) continue;
if (!entry.path.endsWith('.md')) continue;
if (path.basename(entry.path).startsWith('_')) continue;
if (path.basename(entry.path) === 'index.md') continue;
if (path.basename(entry.path) === 'README.md') continue;
Expand Down
5 changes: 5 additions & 0 deletions .github/scripts/format-code-guidelines.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as path from "https://deno.land/[email protected]/path/mod.ts";
const formattingPromises = [];
for await (const entry of walk("./resources/guidelines/code/core")) {
if (entry.isDirectory) continue;
if (!entry.path.endsWith('.md')) continue;
if (path.basename(entry.path).startsWith('_')) continue;
if (path.basename(entry.path) === 'index.md') continue;
if (path.basename(entry.path) === 'README.md') continue;
Expand All @@ -14,6 +15,10 @@ for await (const entry of walk("./resources/guidelines/code/core")) {
await Promise.allSettled(formattingPromises);

function addHint(buffer, filePath) {
if (filePath.includes('/adr/assets/')) {
return buffer;
}

buffer += '\n';
buffer += '::: info\n';
buffer += 'This document represents core guidelines and has been mirrored from the core in our Shopware 6 repository.\n';
Expand Down
3 changes: 3 additions & 0 deletions .wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1468,6 +1468,8 @@ preprocessor
preprocessors
preselect
preselection
prettierrc
previewable
previewComponent
previewable
pricecollectionfacade
Expand Down Expand Up @@ -1506,6 +1508,7 @@ refundAmount
refundId
refundPositions
refundPrice
RegEx
regexes
reindex
reinitializing
Expand Down
7 changes: 0 additions & 7 deletions assets/adr/catalog-import/import-http-schema.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@


::: info
This document represents an architecture decision record (ADR) and has been mirrored from the ADR section in our Shopware 6 repository.
You can find the original version [here](https://github.com/shopware/shopware/blob/trunk/adr/assets/catalog-import/import-http-schema.yml)
:::

openapi: 3.0.3
info:
title: Catalog import API
Expand Down
Binary file modified assets/adr/content-management/example-cms-aware-admin-menu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/adr/message_queue_stats.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 0 additions & 7 deletions assets/adr/payment-flow/after-order-payment.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/adr/payment-flow/asynchronous-payment.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/adr/payment-flow/pre-created-payment.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/adr/payment-flow/synchronous-payment.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/adr/tideways_benchmark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
58 changes: 43 additions & 15 deletions concepts/framework/data-abstraction-layer.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ nav:

### Database guide

In contrast to most Symfony applications, Shopware uses no ORM, but a thin abstraction layer called the data abstraction layer \(DAL\). The DAL is implemented with the specific needs of Shopware in mind and lets developers access the database via pre-defined interfaces. Some concepts used by the DAL, like Criteria, may sound familiar to you if you know [Doctrine](https://symfony.com/doc/current/doctrine.html) or other ORMs. A reference to more in-depth documentation about the DAL can be found below.
In contrast to most Symfony applications, Shopware uses no ORM, but a thin abstraction layer called the data abstraction layer \(DAL\).
The DAL is implemented with the specific needs of Shopware in mind and lets developers access the database via pre-defined interfaces.
Some concepts used by the DAL, like Criteria, may sound familiar to you if you know [Doctrine](https://symfony.com/doc/current/doctrine.html) or other ORMs.
A reference to more in-depth documentation about the DAL can be found below.

Refer to [Shopware 6.6.5.0 entity relationship model](../../../assets/shopware6-erd.pdf) that depicts different tables and their relationships.

Expand All @@ -24,11 +27,13 @@ If you want to have it as an image: File → Export → Export as PNG

### CRUD operations

An EntityRepository is used to interact with the DAL. This is the recommended way for developers to interface with the DAL or the database in general.
An EntityRepository is used to interact with the DAL.
This is the recommended way for developers to interface with the DAL or the database in general.

### Provisioning code to use the repositories

Before using the repositories, you will need to get them from the [Dependency Injection Container (DIC)](../../guides/plugins/plugins/plugin-fundamentals/dependency-injection). This is done with [Constructor injection](https://symfony.com/doc/current/service_container/injection_types.html#constructor-injection), so you will need to extend your services constructor by expecting an EntityRepository:
Before using the repositories, you will need to get them from the [Dependency Injection Container (DIC)](../../guides/plugins/plugins/plugin-fundamentals/dependency-injection).
This is done with [Constructor injection](https://symfony.com/doc/current/service_container/injection_types.html#constructor-injection), so you will need to extend your services constructor by expecting an EntityRepository:

```php
// <plugin root>/src/Service/DalExampleService.php
Expand All @@ -55,35 +60,58 @@ You can read more about dependency injection and service registration in Shopwar

### Translations

The DAL was designed, among other things, to enable the special requirements of Shopware's translation system. When a record is read or searched, three language levels are searched.
The DAL was designed, among other things, to enable the special requirements of Shopware's translation system.
When a record is read or searched, three language levels are searched.

1. **Current language**: The first level is the current language that is set and displayed to the user.
1. **Parent language**: the second level is an optional parent language that can be configured. So it is possible to translate certain dialects faster.
1. **System language**: The third and last level is the system language that is selected during the installation. Each entity in the system has a translation in this language. This serves as a final fallback to ensure only one label for the entity in the end.
1. **Parent language**: the second level is an optional parent language that can be configured.
So it is possible to translate certain dialects faster.
1. **System language**: The third and last level is the system language that is selected during the installation.
Each entity in the system has a translation in this language.
This serves as a final fallback to ensure only one label for the entity in the end.

The translations for a record are stored in a separate table. The name of this table is always the same as the table for which the records are translated, with the additional suffix `_translation`.
The translations for a record are stored in a separate table.
The name of this table is always the same as the table for which the records are translated, with the additional suffix `_translation`.

### Versioning

Another feature of the DAL is the versioning it brings with it. This makes it possible to store multiple versions of an entity. All data subordinate to an entity is duplicated and made available under the new version. Multiple entities or changes to different entities can be stored for one version. The versioning was designed for previews, publishing, or campaign features, to prepare changes that are not yet live and to be able to view them in the store.
Another feature that the DAL offers is versioning.
This makes it possible to store multiple versions of a single entity.
All data assigned to an entity is duplicated and made available under the new version.
Multiple entities or changes to different entities can be stored for one version.
The versioning was designed for previews, publishing, or campaign features, to prepare changes that are not yet live and to be able to view them in the store.
Currently, it is not possible (yet) to create a completely new entity with another version than the default live version.
Means, you cannot "draft" the entity first and then update it into the live version.
A live version of your entity is always required, before deriving a new version from it.

The versioning is also reflected in the database. Entities that are versionable always have a compound foreign key: `id`, `version_id`. Also, the foreign keys, which point to a versioned record, always consist of two columns, e.g.: `product_id` and `product_version_id`.
The versioning is also reflected in the database.
Entities that are versionable always have a compound foreign key: `id`, `version_id`.
Also, the foreign keys, which point to a versioned record, always consist of two columns, e.g.: `product_id` and `product_version_id`.

### Context

The context `core/Framework/Context.php` defines important configuration of the shop system and is instantiated once per request. Depending on the passed parameters it can change the CRUD behavior of the DAL. For example when using the currency toggle in the storefront and selecting Dollar instead of Euro, the context currency ID is changed accordingly and all operations now refer to Dollar.
The context `core/Framework/Context.php` defines important configuration of the shop system and is instantiated once per request.
Depending on the passed parameters it can change the CRUD behavior of the DAL.
For example when using the currency toggle in the storefront and selecting Dollar instead of Euro, the context currency ID is changed accordingly and all operations now refer to Dollar.

### Inheritance

Another reason why the DAL was designed is to meet the requirements of the product and variant system. For this purpose, a parent-child inheritance system was implemented in the DAL. This allows variants to inherit records, properties, or even whole associations from the parent or container product. For example, if a variant has not been assigned any categories or images, those of the parent product are used.
Another reason why the DAL was designed is to meet the requirements of the product and variant system.
For this purpose, a parent-child inheritance system was implemented in the DAL.
This allows variants to inherit records, properties, or even whole associations from the parent or container product.
For example, if a variant has not been assigned any categories or images, those of the parent product are used.

### Indexing

The DAL was designed to be optimized for use in ecommerce. One principle has proven to be very effective so far: "The more time you put into indexing data, the faster it is possible to read it". This is reflected in Shopware as follows:
The DAL was designed to be optimized for use in ecommerce.
One principle has proven to be very effective so far: "The more time you put into indexing data, the faster it is possible to read it".
This is reflected in Shopware as follows:

* A product is written once every X minutes
* A product is called X times every X seconds by a customer.

This varies depending on the store, but the ratio is always the same. Data records are read way more often than they are written. Therefore it is worthwhile to spend a little more time on the writing process in order to minimize the effort required for the reading process. This is done in the DAL via the Entity Indexer pattern. As soon as a product record is written, the corresponding Product Indexer is triggered, which pre-selects certain aggregations and writes them away optimized for the later reading process.


This varies depending on the store, but the ratio is always the same.
Data records are read way more often than they are written.
Therefore, it is worthwhile to spend a little more time on the writing process in order to minimize the effort required for the reading process.
This is done in the DAL via the Entity Indexer pattern.
As soon as a product record is written, the corresponding Product Indexer is triggered, which pre-selects certain aggregations and writes them away optimized for the later reading process.
19 changes: 19 additions & 0 deletions guides/hosting/infrastructure/redis.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,29 @@ As the data is critical, it is important to use a key eviction policy that will

The cart, number range, lock store and increment data is what should be stored in this instance.

## Configuration

Starting with v6.6.8.0 Shopware supports configuring different reusable Redis connections in the`config/packages/shopware.yaml` file under the `shopware` section:

```yaml
shopware:
# ...
redis:
connections:
ephemeral:
dsn: 'redis://host1:port/dbindex'
persistent:
dsn: 'redis://host2:port/dbindex?persistent=1'
```
Connection names should reflect the actual connection purpose/type and be unique. Also, the names are used as part of the service names in the container, so they should follow the service naming conventions. After defining connections, you can reference them by name in the configuration of different subsystems.
<PageRef page="../performance/cart-storage" />
<PageRef page="../performance/number-ranges" />
<PageRef page="../performance/lock-store" />
<PageRef page="../performance/increment" />
<PageRef page="../performance/performance-tweaks#delayed-invalidation" />
16 changes: 9 additions & 7 deletions guides/hosting/infrastructure/reverse-http-cache.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,16 +177,18 @@ shopware:

### Fastly VCL Snippets

Additionally, we need to set up some VCL Snippets in the Fastly interface:
You can use the [Deployment Helper to automatically deploy Fastly VCL Snippets and keep them up to date](../installation-updates//deployments/deployment-helper.md).

<PageRef page="https://github.com/shopware/recipes/blob/main/shopware/fastly-meta/6.4/config/fastly/deliver/default.vcl" title="vcl_deliver" target="_blank" />
For manual deployment, you can find the VCL Snippets here:

<PageRef page="https://github.com/shopware/recipes/blob/main/shopware/fastly-meta/6.4/config/fastly/fetch/default.vcl" title="vcl_fetch" target="_blank" />
<PageRef page="https://github.com/shopware/recipes/blob/main/shopware/fastly-meta/6.6/config/fastly/deliver/default.vcl" title="vcl_deliver" target="_blank" />

<PageRef page="https://github.com/shopware/recipes/blob/main/shopware/fastly-meta/6.4/config/fastly/hash/default.vcl" title="vcl_hash" target="_blank" />
<PageRef page="https://github.com/shopware/recipes/blob/main/shopware/fastly-meta/6.6/config/fastly/fetch/default.vcl" title="vcl_fetch" target="_blank" />

<PageRef page="https://github.com/shopware/recipes/blob/main/shopware/fastly-meta/6.4/config/fastly/hit/default.vcl" title="vcl_hit" target="_blank" />
<PageRef page="https://github.com/shopware/recipes/blob/main/shopware/fastly-meta/6.6/config/fastly/hash/default.vcl" title="vcl_hash" target="_blank" />

<PageRef page="https://github.com/shopware/recipes/blob/main/shopware/fastly-meta/6.4/config/fastly/recv/default.vcl" title="vcl_recv" target="_blank" />
<PageRef page="https://github.com/shopware/recipes/blob/main/shopware/fastly-meta/6.6/config/fastly/hit/default.vcl" title="vcl_hit" target="_blank" />

<!-- {"WATCHER_URL":"https://raw.githubusercontent.com/shopware/shopware/trunk/src/Storefront/Resources/config/packages/storefront.yaml","WATCHER_HASH":"ea090957a082e950ffa112b108e40abf"} -->
<PageRef page="https://github.com/shopware/recipes/blob/main/shopware/fastly-meta/6.6/config/fastly/recv/default.vcl" title="vcl_recv" target="_blank" />

<!-- {"WATCHER_URL":"https://raw.githubusercontent.com/shopware/shopware/trunk/src/Storefront/Resources/config/packages/storefront.yaml","WATCHER_HASH":"3ae5bc3363521c72d05f4ecbb89b3505"} -->
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ deployment:
script: |
# runs one time in deployment, then never again
./bin/console --version
store:
license-domain: 'example.com'
```
## Environment Variables
Expand All @@ -82,6 +85,9 @@ Additionally, you can configure the Shopware installation using the following en
- `INSTALL_ADMIN_USERNAME` - The username of the admin user (default: `admin`)
- `INSTALL_ADMIN_PASSWORD` - The password of the admin user (default: `shopware`)
- `SALES_CHANNEL_URL` - The URL of the Storefront sales channel (default: `http://localhost`)
- `SHOPWARE_STORE_ACCOUNT_EMAIL` - The email address of the Shopware account
- `SHOPWARE_STORE_ACCOUNT_PASSWORD` - The password of the Shopware account
- `SHOPWARE_STORE_LICENSE_DOMAIN` - The license domain of the Shopware Shop (default: license-domain value in YAML file)

## One Time Tasks

Expand All @@ -91,6 +97,27 @@ You can check with `./vendor/bin/shopware-deployment-helper one-time-task:list`
To remove a task, use `./vendor/bin/shopware-deployment-helper one-time-task:unmark <id>`. This will cause the task to be executed again during the next update.
To manually mark a task as run you can use `./vendor/bin/shopware-deployment-helper one-time-task:mark <id>`.

## Fastly Integration

The Deployment Helper can also deploy Fastly VCL Snippets for you and keep them up to date. After installing the Deployment Helper, you can install the Fastly meta package:

```bash
composer require shopware/fastly-meta
```

After that, make sure that environment variable `FASTLY_API_KEY` and `FASTLY_SERVICE_ID` are set and the Fastly VCL Snippets will be deployed with the regular deployment process of the Deployment Helper.

The deployment helper has also two commands to manage the Fastly VCL Snippets:

- `./vendor/bin/shopware-deployment-helper fastly:snippet:list` - List all VCL snippets that are currently deployed
- `./vendor/bin/shopware-deployment-helper fastly:snippet:remove <name>` - Remove a VCL snippet by name

## Automatic Store Login

The Deployment Helper can automatically log in to the Shopware Store, so you can install Apps from the Store. For this the environment variables: `SHOPWARE_STORE_ACCOUNT_EMAIL` and `SHOPWARE_STORE_ACCOUNT_PASSWORD` need to be set, and a license domain needs to be configured in the `.shopware-project.yml` file.
The license domain can be set also by env variable `SHOPWARE_STORE_LICENSE_DOMAIN`, which will overwrite the value from the `.shopware-project.yml` file.

When you open the extension manager, you will see that you are not logged in. This is normal as the Deployment Helper does log you in only for system tasks like extension installation or updates. For the extension manager, every Administration user needs to log in manually.

## Usage examples

Expand Down
22 changes: 22 additions & 0 deletions guides/hosting/performance/cart-storage.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,33 @@ Redis is better suited in high-throughput scenarios, therefore you should use Re

To use Redis, create a `config/packages/shopware.yml` file with the following content:

<Tabs>
<Tab title="Before v6.6.8.0">

```yaml
shopware:
cart:
redis_url: 'redis://host:port/dbindex?persistent=1'
```
</Tab>
<Tab title="Since v6.6.8.0">
```yaml
shopware:
redis:
connections:
persistent:
dsn: 'redis://host:port/dbindex?persistent=1'
cart:
storage:
type: 'redis'
config:
connection: 'persistent'
```
</Tab>
</Tabs>
It is recommended to use a persistent Redis connection to avoid connection issues in high-load scenarios.
## Migrating between storages
Expand Down
31 changes: 29 additions & 2 deletions guides/hosting/performance/increment.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ Shopware uses the `increment` table to store such information by default. When m

To use Redis, create a `config/packages/shopware.yml` file with the following content

<Tabs>
<Tab title="Before v6.6.8.0">

```yaml
shopware:
increment:
Expand All @@ -33,6 +36,30 @@ shopware:
config:
url: 'redis://host:port/dbindex'
```
</Tab>
<Tab title="Since v6.6.8.0">
```yaml
shopware:
redis:
connections:
persistent:
dsn: 'redis://host:port/dbindex?persistent=1'

increment:
user_activity:
type: 'redis'
config:
connection: 'persistent'

message_queue:
type: 'redis'
config:
connection: 'persistent'
```
</Tab>
</Tabs>
### Redis configuration
Expand All @@ -50,8 +77,8 @@ To disable it, create a `config/packages/shopware.yml` file with the following c
shopware:
increment:
user_activity:
type: 'array'
type: 'array'
message_queue:
type: 'array'
type: 'array'
```
Loading

0 comments on commit f4b95f5

Please sign in to comment.