[DOCUMENTATION] Synchronize 2.0-docs -> 2.0 (#17412)

Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
This commit is contained in:
Grzegorz Sadowski 2024-11-05 08:35:24 +01:00 committed by GitHub
commit 0aaca6dfc9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
234 changed files with 6816 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 686 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 480 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

View file

@ -0,0 +1,10 @@
<svg width="45" height="26" viewBox="0 0 45 28" fill="#1A9F83" xmlns="http://www.w3.org/2000/svg">
<rect width="45" height="28" fill="#1A9F83"/>
<path d="M11.9492 14.2031L14.758 19.8048L19.9424 19.8133L21.197 18.0522L11.9492 14.2031Z" fill="white"/>
<path d="M10 14.8203L13.7763 19.9894L19.9428 19.9995L21.1974 18.0657L10 14.8203Z" fill="#DADADA"/>
<path d="M14.5273 8.52097L16.3654 9.94262L18.0273 6.7627L17.4626 6.40234L14.5273 8.52097Z" fill="#DADADA"/>
<path d="M19.9422 19.9996L14.5273 8.52341L15.6857 7.6875L21.9864 16.8474L19.9422 19.9996Z" fill="white"/>
<path d="M16.9414 6.78114L20.4685 9.62217L17.9933 6L16.9414 6.78114Z" fill="white"/>
<text fill="white" font-size="16" dx="22" dy="18">+</text>
</svg>

After

Width:  |  Height:  |  Size: 715 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

100
docs/README.md Normal file
View file

@ -0,0 +1,100 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: false
pagination:
visible: true
---
# Sylius Documentation
<figure><img src=".gitbook/assets/sylius-logo_sylius-logo-light.png" alt="" width="563"><figcaption></figcaption></figure>
**Sylius** is an open-source e-commerce platform with a modular architecture, providing a robust foundation for online stores. It focuses on delivering a dynamic developer experience and allows extensive customization to meet unique business needs.&#x20;
Key features include product and customer management, versatile shopping cart systems, flexible tax categories, and promotional tools. Sylius supports seamless integration with third-party services and customizable workflows.&#x20;
Whether youre new to Symfony-based frameworks or an experienced developer, Sylius is designed to grow with you, facilitating your journey from basic to advanced e-commerce development.
{% hint style="info" %}
This documentation assumes you have a working knowledge of the Symfony Framework. If youre unfamiliar with Symfony, please start by reading the [Quick Tour](https://symfony.com/doc/current/quick\_tour) from the Symfony documentation.
{% endhint %}
***
## Why Sylius? <a href="#why-sylius" id="why-sylius"></a>
When you choose Sylius, you're investing in a flexible, open-source e-commerce platform designed for your unique needs. Here's why Sylius stands out:
* **Customizable to the Core:** With Sylius, customization is not an afterthought - it's the main event. Built with the Symfony framework, Sylius is engineered for modularity. This means you can tailor every aspect of your store, creating a truly personalized e-commerce experience for your customers.
* **Developer-Friendly:** Sylius is made for developers, by developers. Its use of PHP and Symfony, combined with a comprehensive set of API endpoints, ensures seamless integration and adaptability. This developer-centric focus allows your team to dive right into creating a powerful, feature-rich e-commerce platform.
* **Robust and Scalable:** From small businesses to massive online retailers, Sylius can handle it all. It's designed to grow with your business, ensuring that no matter how big you get, you'll never outgrow your platform.
* **Community and Support:** When you choose Sylius, you're joining a vibrant, global community of developers and e-commerce professionals. Whether you need help troubleshooting a problem, or you're looking for new ideas, the Sylius community is there. Plus, professional support is available for those who need it, ensuring you always have the help you need to succeed.
* **Emphasis on Quality:** Sylius follows a test-driven development approach, leading to a more reliable and stable platform. This dedication to quality gives you peace of mind that your e-commerce store runs smoothly and securely.
So why choose Sylius? Because it's more than just an e-commerce platform - it's the key to creating the online store you've always envisioned. It's time to turn that vision into reality with Sylius.
## Table of Contents
### Organization
* [Release Cycle](sylius-documentation/organization/release-cycle.md)
* [Backwards Compatibility Promise](sylius-documentation/organization/backwards-compatibility-promise.md)
* [Sylius Team](broken-reference)
### Getting Started with Sylius
The essential guide for the Sylius newcomers who want to know its most important features, quickly see the power of customization and run their first Sylius shop within a few hours.
* [Installation](getting-started-with-sylius/installation.md)
* [Basic Configuration](getting-started-with-sylius/basic-configuration.md)
* [Shipping & Payment](getting-started-with-sylius/shipping-and-payment.md)
* [First Product](getting-started-with-sylius/first-product.md)
* [Customizing the Shop](getting-started-with-sylius/customizing-the-shop.md)
* [Customizing Business Logic](getting-started-with-sylius/customizing-business-logic.md)
* [Using API](broken-reference)
* [Installing Plugins](getting-started-with-sylius/installing-plugins.md)
* [Deployment](getting-started-with-sylius/deployment.md)
* [Summary](getting-started-with-sylius/summary.md)
### The Book
The Developers guide to leveraging the flexibility of Sylius. Here you will find all the concepts used in the Sylius platform. The Book helps to understand how Sylius works.
* [Introduction](the-book/introduction-to-sylius.md)
* [Installation](the-book/installation/)
* [Architecture](the-book/architecture/)
* [Configuration](the-book/configuration/)
* [Customers](the-book/customers/)
* [Products](the-book/products/)
* [Carts & Orders](the-book/carts-and-orders/)
* [Frontend & Themes](the-book/frondend-and-themes.md)
* [Sylius Plugins](the-book/sylius-plugins/)
* [Support](the-book/support.md)
* [Contributing](the-book/contributing/)
* [API](the-book/api/)
### Sylius Plus
<figure><img src=".gitbook/assets/sylius-docs-banner.png" alt=""><figcaption></figcaption></figure>
[Sylius Plus](https://sylius.com/plus/?utm\_source=docs\&utm\_medium=cta\&utm\_campaign=plus), a licensed edition of Sylius, gives you all the power of Open Source and much more. It comes with enterprise-grade features and technical support from its creators. As a state-of-the-art eCommerce platform, it reduces risks and increases ROI.
\
Documentation sections referring to Sylius Plus features are:
* [Sylius Plus Installation](the-book/installation/sylius-plus-installation.md)
* [Channels](the-book/configuration/channels.md#business-units)
* [RBAC](the-book/customers/adminuser.md)
* [Customer Pools](the-book/customers/customer-pools.md)
* [Splitting Shipments](the-book/carts-and-orders/shipments.md)
* [Returns](the-book/carts-and-orders/returns.md)
* Returns related [E-Mails](the-book/architecture/e-mails.md#sylius-plus-return-requests-emails)
* [Multi-Source Inventory](the-book/products/multi-source-inventory.md)
* [Loyalty](the-book/sylius-plus/loyalty.md)

203
docs/SUMMARY.md Normal file
View file

@ -0,0 +1,203 @@
# Table of contents
* [Sylius Documentation](README.md)
* [Organization](sylius-documentation/organization/README.md)
* [Release Cycle](sylius-documentation/organization/release-cycle.md)
* [Backwards Compatibility Promise](sylius-documentation/organization/backwards-compatibility-promise.md)
* [Sylius Team](https://sylius.com/team/)
* [Sylius Roadmap](https://sylius.com/roadmap/?utm\_source=docs)
## Getting Started with Sylius
* [Index](getting-started-with-sylius/index.md)
* [Installation](getting-started-with-sylius/installation.md)
* [Basic Configuration](getting-started-with-sylius/basic-configuration.md)
* [Shipping & Payment](getting-started-with-sylius/shipping-and-payment.md)
* [First Product](getting-started-with-sylius/first-product.md)
* [Customizing the Shop](getting-started-with-sylius/customizing-the-shop.md)
* [Customizing Business Logic](getting-started-with-sylius/customizing-business-logic.md)
* [Using API](getting-started-with-sylius/using-api.md)
* [Installing Plugins](getting-started-with-sylius/installing-plugins.md)
* [Deployment](getting-started-with-sylius/deployment.md)
* [Summary](getting-started-with-sylius/summary.md)
## The Book
* [Index](the-book/index.md)
* [Introduction to Sylius](the-book/introduction-to-sylius.md)
* [Understanding Environments](the-book/understanding-environments.md)
* [Installation](the-book/installation/README.md)
* [System Requirements](the-book/installation/system-requirements.md)
* [Sylius CE Installation](the-book/installation/sylius-ce-installation/README.md)
* [Sylius CE Installation with Docker](the-book/installation/sylius-ce-installation/sylius-ce-installation-with-docker.md)
* [Sylius Plus Installation](the-book/installation/sylius-plus-installation.md)
* [Upgrading Sylius CE](the-book/installation/upgrading-sylius-ce.md)
* [Upgrading Sylius Plus](the-book/installation/upgrading-sylius-plus.md)
* [Architecture](the-book/architecture/README.md)
* [Architecture Overview](the-book/architecture/architecture-overview.md)
* [Architectural Drivers](the-book/architecture/architectural-drivers.md)
* [Resource Layer](the-book/architecture/resource-layer.md)
* [State Machine](the-book/architecture/state-machine.md)
* [Translations](the-book/architecture/translations.md)
* [E-Mails](the-book/architecture/e-mails.md)
* [Contact](the-book/architecture/contact.md)
* [Fixtures](the-book/architecture/fixtures.md)
* [Events](the-book/architecture/events.md)
* [Configuration](the-book/configuration/README.md)
* [Channels](the-book/configuration/channels.md)
* [Locales](the-book/configuration/locales.md)
* [Currencies](the-book/configuration/currencies.md)
* [Customers](the-book/customers/README.md)
* [Customer & ShopUser](the-book/customers/customer-and-shopuser.md)
* [Customer Pools](the-book/customers/customer-pools.md)
* [AdminUser](the-book/customers/adminuser.md)
* [Addresses](the-book/customers/addresses/README.md)
* [Countries](the-book/customers/addresses/countries.md)
* [Zones](the-book/customers/addresses/zones.md)
* [Addresses](the-book/customers/addresses/addresses.md)
* [Address Book](the-book/customers/addresses/address-book.md)
* [Products](the-book/products/README.md)
* [Products](the-book/products/products.md)
* [Product Reviews](the-book/products/product-reviews.md)
* [Product Associations](the-book/products/product-associations.md)
* [Attributes](the-book/products/attributes.md)
* [Pricing](the-book/products/pricing.md)
* [Catalog Promotions](the-book/products/catalog-promotions.md)
* [Taxons](the-book/products/taxons.md)
* [Inventory](the-book/products/inventory.md)
* [Multi-Source Inventory](the-book/products/multi-source-inventory.md)
* [Search](the-book/products/search.md)
* [Carts & Orders](the-book/carts-and-orders/README.md)
* [Orders](the-book/carts-and-orders/orders.md)
* [Cart flow](the-book/carts-and-orders/cart-flow.md)
* [Taxation](the-book/carts-and-orders/taxation.md)
* [Adjustments](the-book/carts-and-orders/adjustments.md)
* [Cart Promotions](the-book/carts-and-orders/cart-promotions.md)
* [Coupons](the-book/carts-and-orders/coupons.md)
* [Payments](the-book/carts-and-orders/payments.md)
* [Invoices](the-book/carts-and-orders/invoices.md)
* [Shipments](the-book/carts-and-orders/shipments.md)
* [Checkout](the-book/carts-and-orders/checkout.md)
* [Returns](the-book/carts-and-orders/returns.md)
* [Refunds](the-book/carts-and-orders/refunds.md)
* [API](the-book/api/README.md)
* [#todo](the-book/api/todo.md)
* [Frondend & Themes](the-book/frondend-and-themes.md)
* [ Sylius Plus](the-book/sylius-plus/README.md)
* [ Loyalty](the-book/sylius-plus/loyalty.md)
* [Sylius Plugins](the-book/sylius-plugins/README.md)
* [How to create a plugin for Sylius?](the-book/sylius-plugins/how-to-create-a-plugin-for-sylius.md)
* [🏗️ Plugin Development Guide](the-book/sylius-plugins/plugin-development-guide.md)
* [Official Sylius Plugins](the-book/sylius-plugins/official-sylius-plugins.md)
* [Sylius Store](the-book/sylius-plugins/sylius-store.md)
* [Support](the-book/support.md)
* [Contributing](the-book/contributing/README.md)
* [Contributing Code](the-book/contributing/contributing-code/README.md)
* [Submitting a Patch](the-book/contributing/contributing-code/submitting-a-patch.md)
* [⚠️ Security Issues](the-book/contributing/contributing-code/security-issues.md)
* [Coding Standards](the-book/contributing/contributing-code/coding-standards.md)
* [Conventions](the-book/contributing/contributing-code/conventions.md)
* [Sylius License and Trademark](the-book/contributing/contributing-code/sylius-license-and-trademark.md)
* [Contributing Documentation](the-book/contributing/contributing-documentation.md)
* [Contributing Translations](the-book/contributing/contributing-translations.md)
## The Customization Guide
* [Index](the-customization-guide/index.md)
* [Customizing Models](the-customization-guide/customizing-models.md)
* [Customizing Forms](the-customization-guide/customizing-forms.md)
* [Customizing Repositories](the-customization-guide/customizing-repositories.md)
* [Customizing Factories](the-customization-guide/customizing-factories.md)
* [Customizing Controllers](the-customization-guide/customizing-controllers.md)
* [Customizing Validation](the-customization-guide/customizing-validation.md)
* [Customizing Menus](the-customization-guide/customizing-menus.md)
* [Customizing Templates](the-customization-guide/customizing-templates.md)
* [Customizing Translations](the-customization-guide/customizing-translations.md)
* [Customizing Flashes](the-customization-guide/customizing-flashes.md)
* [Customizing State Machines](the-customization-guide/customizing-state-machines.md)
* [Customizing Grids](the-customization-guide/customizing-grids.md)
* [Customizing Fixtures](the-customization-guide/customizing-fixtures/README.md)
* [Customizing Fixture Suites](the-customization-guide/customizing-fixtures/customizing-fixture-suites.md)
* [Customizing API](the-customization-guide/customizing-api.md)
* [Tips & Tricks](the-customization-guide/tips-and-tricks.md)
## THE COOKBOOK
* [The Cookbook](https://docs.sylius.com/en/1.13/cookbook/index.html)
## The Cookbook 2.0
* [Index](the-cookbook-2.0/index.md)
* [Handling multiple Channels in CLI](the-cookbook-2.0/handling-multiple-channels-in-cli.md)
* [How to add a custom model?](the-cookbook-2.0/how-to-add-a-custom-model.md)
* [How to add a custom model accessible for respective channel administrators?](the-cookbook-2.0/how-to-add-a-custom-model-accessible-for-respective-channel-administrators.md)
* [How to add a custom translatable model?](the-cookbook-2.0/how-to-add-a-custom-translatable-model.md)
* [How to edit orders in Sylius?](the-cookbook-2.0/how-to-edit-orders-in-sylius.md)
* [How to customize Sylius Checkout?](the-cookbook-2.0/how-to-customize-sylius-checkout.md)
* [How to disable guest checkout?](the-cookbook-2.0/how-to-disable-guest-checkout.md)
* [How to add Facebook login?](the-cookbook-2.0/how-to-add-facebook-login.md)
* [How to change a redirect after the add to cart action?](the-cookbook-2.0/how-to-change-a-redirect-after-the-add-to-cart-action.md)
* [How to render a menu of taxons (categories) in a view?](the-cookbook-2.0/how-to-render-a-menu-of-taxons-categories-in-a-view.md)
* [How to embed a list of products into a view?](the-cookbook-2.0/how-to-embed-a-list-of-products-into-a-view.md)
* [How to disable localized URLs?](the-cookbook-2.0/how-to-disable-localized-urls.md)
* [How to manage content in Sylius?](the-cookbook-2.0/how-to-manage-content-in-sylius.md)
* [How to use Vue Storefront PWA with Sylius?](the-cookbook-2.0/how-to-use-vue-storefront-pwa-with-sylius.md)
* [How to configure PayPal Express Checkout?](the-cookbook-2.0/how-to-configure-paypal-express-checkout.md)
* [How to configure Stripe Credit Card payment?](the-cookbook-2.0/how-to-configure-stripe-credit-card-payment.md)
* [How to encrypt gateway config stored in the database?](the-cookbook-2.0/how-to-encrypt-gateway-config-stored-in-the-database.md)
* [How to authorize a payment before capturing?](the-cookbook-2.0/how-to-authorize-a-payment-before-capturing.md)
* [How to integrate a Payment Gateway as a Plugin?](the-cookbook-2.0/how-to-integrate-a-payment-gateway-as-a-plugin.md)
* [How to customize a Credit Memo?](the-cookbook-2.0/how-to-customize-a-credit-memo.md)
* [How to have the Credit Memos created after the Refund Payments?](the-cookbook-2.0/how-to-have-the-credit-memos-created-after-the-refund-payments.md)
* [How to customize the refund form?](the-cookbook-2.0/how-to-customize-the-refund-form.md)
* [How to add another type of refund?](the-cookbook-2.0/how-to-add-another-type-of-refund.md)
* [How to add another implementation of UnitRefundInterface?](the-cookbook-2.0/how-to-add-another-implementation-of-unitrefundinterface.md)
* [How to customize Invoices?](the-cookbook-2.0/how-to-customize-invoices.md)
* [How to have the Invoice generated after the payment is paid?](the-cookbook-2.0/how-to-have-the-invoice-generated-after-the-payment-is-paid.md)
* [How to configure mailer?](the-cookbook-2.0/how-to-configure-mailer.md)
* [How to send a custom e-mail?](the-cookbook-2.0/how-to-send-a-custom-e-mail.md)
* [How to customize email templates per channel?](the-cookbook-2.0/how-to-customize-email-templates-per-channel.md)
* [How to disable the order confirmation email?](the-cookbook-2.0/how-to-disable-the-order-confirmation-email.md)
* [How to add a custom cart promotion rule?](the-cookbook-2.0/how-to-add-a-custom-cart-promotion-rule.md)
* [How to add a custom cart promotion action?](the-cookbook-2.0/how-to-add-a-custom-cart-promotion-action.md)
* [How to add a custom catalog promotion scope?](the-cookbook-2.0/how-to-add-a-custom-catalog-promotion-scope.md)
* [How to add a custom catalog promotion action?](the-cookbook-2.0/how-to-add-a-custom-catalog-promotion-action.md)
* [How to customize catalog promotion labels?](the-cookbook-2.0/how-to-customize-catalog-promotion-labels.md)
* [How to improve the performance of the catalog promotions?](the-cookbook-2.0/how-to-improve-the-performance-of-the-catalog-promotions.md)
* [How to create a custom inventory sources filter?](the-cookbook-2.0/how-to-create-a-custom-inventory-sources-filter.md)
* [How to add a custom shipping method rule?](the-cookbook-2.0/how-to-add-a-custom-shipping-method-rule.md)
* [How to resize images?](the-cookbook-2.0/how-to-resize-images.md)
* [How to add one image to an entity?](the-cookbook-2.0/how-to-add-one-image-to-an-entity.md)
* [How to add multiple images to an entity?](the-cookbook-2.0/how-to-add-multiple-images-to-an-entity.md)
* [How to automatically store images on AWS-S3?](the-cookbook-2.0/how-to-automatically-store-images-on-aws-s3.md)
* [Introduction to Sylius Cloud by Platform.sh](the-cookbook-2.0/introduction-to-sylius-cloud-by-platform.sh.md)
* [Advanced Sylius Cloud by Platform.sh configuration](the-cookbook-2.0/advanced-sylius-cloud-by-platform.sh-configuration.md)
* [Sylius Cloud by Platform.sh management basics](the-cookbook-2.0/sylius-cloud-by-platform.sh-management-basics.md)
* [How to prepare simple CRON jobs?](the-cookbook-2.0/how-to-prepare-simple-cron-jobs.md)
* [How to use installer commands?](the-cookbook-2.0/how-to-use-installer-commands.md)
* [How to disable the default shop, admin or API of Sylius?](the-cookbook-2.0/how-to-disable-the-default-shop-admin-or-api-of-sylius.md)
* [How to disable admin version notifications?](the-cookbook-2.0/how-to-disable-admin-version-notifications.md)
* [How to customize Admin routes prefix?](the-cookbook-2.0/how-to-customize-admin-routes-prefix.md)
* [How to add Google Analytics script to shop?](the-cookbook-2.0/how-to-add-google-analytics-script-to-shop.md)
* [How to migrate from Gulp to Webpack (Sylius 1.11 or earlier)?](the-cookbook-2.0/how-to-migrate-from-gulp-to-webpack-sylius-1.11-or-earlier.md)
* [How to migrate from Gulp to Webpack (Sylius 1.12 or later)?](the-cookbook-2.0/how-to-migrate-from-gulp-to-webpack-sylius-1.12-or-later.md)
* [How to stay with Gulp after Sylius 1.12 update?](the-cookbook-2.0/how-to-stay-with-gulp-after-sylius-1.12-update.md)
* [How to configure tax rates to be based on shipping address?](the-cookbook-2.0/how-to-configure-tax-rates-to-be-based-on-shipping-address.md)
* [How to add product variants by options to the cart in Sylius API?](the-cookbook-2.0/how-to-add-product-variants-by-options-to-the-cart-in-sylius-api.md)
* [How to force already registered user to log in during checkout in Sylius API?](the-cookbook-2.0/how-to-force-already-registered-user-to-log-in-during-checkout-in-sylius-api.md)
* [How to add a new Loyalty Rule Configuration to API?](the-cookbook-2.0/how-to-add-a-new-loyalty-rule-configuration-to-api.md)
## Tests
* [Index](tests/index.md)
* [Behaviour Driven Development](tests/behaviour-driven-development/README.md)
* [How to add a new context?](tests/behaviour-driven-development/how-to-add-a-new-context.md)
* [How to add a new page object?](tests/behaviour-driven-development/how-to-add-a-new-page-object.md)
* [How to use transformers?](tests/behaviour-driven-development/how-to-use-transformers.md)
* [How to define a new suite?](tests/behaviour-driven-development/how-to-define-a-new-suite.md)
## The Performance Guide
* [Index](the-performance-guide/index.md)
* [Database indexes](the-performance-guide/database-indexes.md)
* [Query optimization](the-performance-guide/query-optimization.md)

View file

@ -0,0 +1,81 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Basic Configuration
The Configuration section is the first place you should check out in the Admin panel. There you can find a bunch of modules used to customize your shop the most basic data.
## Channels
The **Channels** section is one of the most important areas in Sylius. A channel defines core data about your store, including available locales, currencies, and billing details.
By default, you should already have one channel created during installation. You can edit your channel's configuration to suit your needs:
<figure><img src="../.gitbook/assets/channel_edit.png" alt=""><figcaption></figcaption></figure>
## Locales
Sylius supports internationalization, allowing you to add new locales for your shop easily. This enables customers to browse the site in their preferred language.
At this point, you likely only have **English (United States)** as your base locale, which was set during installation. All products, taxons, and other content must be created with at least an English name.
You can add new locales to expand language support for your customers:
<figure><img src="../.gitbook/assets/locales.png" alt=""><figcaption></figcaption></figure>
## Currencies
Each channel in Sylius operates with one **Base Currency**, but you can display prices in multiple currencies. Conversion between currencies is managed by configuring **Exchange Rates**.
During installation, **USD** was set as the default currency. You can add more currencies as needed:
<figure><img src="../.gitbook/assets/currencies.png" alt=""><figcaption></figcaption></figure>
{% hint style="info" %}
The initial data (channel, locale, currency) was created by the installation command. However, to fully configure your store, you should add the following items.
{% endhint %}
## Countries
Most eCommerce stores ship to multiple countries. In the **Countries** section, you can configure which countries are available for shipping.
To add a country:
1. Navigate to the **Countries** section.
2. Add the desired countries for your stores shipping destinations.
<figure><img src="../.gitbook/assets/country_create.png" alt=""><figcaption></figcaption></figure>
Once added, countries will be displayed in the index:
<figure><img src="../.gitbook/assets/countries.png" alt=""><figcaption></figcaption></figure>
## Zones
**Zones** are used for shipping and tax purposes, and they can consist of countries, provinces, or even other zones.
To finish your basic setup, create a zone named the **European Union** consisting of the European countries. This is essential for shipping and taxing configurations.
<figure><img src="../.gitbook/assets/zone_types.png" alt="" width="284"><figcaption></figcaption></figure>
After creating this zone, your basic shop configuration will be complete:
<figure><img src="../.gitbook/assets/zone_create.png" alt=""><figcaption></figcaption></figure>
## Learn more
* [Channels](../the-book/configuration/channels.md)
* [Currencies](../the-book/configuration/currencies.md)
* [Pricing](../the-book/products/pricing.md)
* [Locales](../the-book/configuration/locales.md)

View file

@ -0,0 +1,149 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Customizing Business Logic
Sylius offers extensive customization options, allowing you to tailor your eCommerce store to your specific needs. Lets walk through an example of how you can customize Sylius by implementing a **custom shipping calculator**.
## Custom Shipping Calculator
A **shipping calculator** in Sylius calculates the shipping cost for an order. This calculation is usually based on the products and some configuration defined by the admin. Sylius provides two default calculators:
* **FlatRateCalculator**: Charges a fixed rate per order.
* **PerUnitRateCalculator**: Charges a rate based on the number of items in the order.
Lets say you need to charge based on the number of parcels used to pack the order. You can create a custom calculator to achieve this.
### Step 1: Create the Custom Shipping Calculator
Your custom calculator must implement the `CalculatorInterface`. Below is an example of a **ParcelCalculator**, which charges based on the number of parcels.
```php
<?php
# src/ShippingCalculator/ParcelCalculator.php
declare(strict_types=1);
namespace App\ShippingCalculator;
use Sylius\Component\Shipping\Calculator\CalculatorInterface;
use Sylius\Component\Shipping\Model\ShipmentInterface;
final class ParcelCalculator implements CalculatorInterface
{
public function calculate(ShipmentInterface $subject, array $configuration): int
{
$parcelSize = $configuration['size'];
$parcelPrice = $configuration['price'];
$numberOfPackages = ceil($subject->getUnits()->count() / $parcelSize);
return (int) ($numberOfPackages * $parcelPrice);
}
public function getType(): string
{
return 'parcel';
}
}
```
In this code, we calculate the number of parcels needed by dividing the total product units by the parcel size. The total shipping cost is then the number of parcels multiplied by the price per parcel.
### Step 2: Register the Custom Calculator
To make this calculator available in the admin panel, register it as a service in your `services.yaml`:
```yaml
# config/services.yaml
services:
app.shipping_calculator.parcel:
class: App\ShippingCalculator\ParcelCalculator
tags:
- { name: sylius.shipping_calculator }
```
This will allow your custom shipping calculator to be selected when configuring shipping methods in the admin panel.
### Step 3: Configure the Shipping Method in the Admin Panel
Now that your calculator is registered, you can create a new **Shipping Method** in the admin panel using your **ParcelCalculator**. When setting up the shipping method, you will need to provide two configuration options:
* **Size**: How many units fit into one parcel.
* **Price**: The cost per parcel.
<div>
<figure><img src="../.gitbook/assets/shipping-calculator.png" alt=""><figcaption><p>Configuration in the Admin Panel</p></figcaption></figure>
<figure><img src="../.gitbook/assets/shipping-cost-1.png" alt=""><figcaption><p>Shipping cost for 1 pacel</p></figcaption></figure>
<figure><img src="../.gitbook/assets/shipping-cost-2.png" alt=""><figcaption><p>Shipping cost for 4 parcels</p></figcaption></figure>
</div>
## Testing the Custom Logic via API
Once everything is set up, you can test the logic through the API.
### Add an Item to the Cart
Use the following API call to add an item to the cart:
```bash
curl --location --request PATCH 'https://your-shop-url.com/api/v2/shop/orders/CART_TOKEN/items' --header 'Content-Type: application/merge-patch+json' --data-raw '{
"productVariant": "/api/v2/shop/product-variants/PRODUCT_VARIANT_CODE",
"quantity": 1
}'
```
This should return a response with the cart, including the `shippingTotal`:
```json
{
"taxTotal": 0,
"shippingTotal": 500, // Shipping cost in cents
"orderPromotionTotal": 0
}
```
{% hint style="info" %}
The API returns amounts in the smallest currency unit (e.g., cents for USD). So 500 represents $5.00.
{% endhint %}
### Change Item Quantity
You can modify the quantity of the item in the cart using the following API:
```bash
curl --location --request PATCH 'https://your-shop-url.com/api/v2/shop/orders/CART_TOKEN/items/ORDER_ITEM_ID' --header 'Content-Type: application/merge-patch+json' --data-raw '{
"quantity": 4
}'
```
This should return a response with the updated `shippingTotal`:
```json
{
"taxTotal": 0,
"shippingTotal": 1000, // Updated shipping cost based on the new quantity
"orderPromotionTotal": 0
}
```
Congratulations! Youve now added custom business logic to your Sylius store by creating a custom shipping calculator. With this foundation, you can continue customizing your shop to suit your business needs.

View file

@ -0,0 +1,119 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Customizing the Shop
Sylius stands out from other eCommerce platforms not only because of its vibrant community and clean codebase but also due to its exceptional developer experience. Its flexibility and ease of customization allow you to adapt the platform to meet your unique business needs.
Lets explore how you can leverage these features to make a simple yet important customization: replacing the default Sylius logo with your stores custom logo.
## Logo
The default Sylius templates are clean and elegant, but you might want to make your store unique by customizing it with your brands logo. Heres how you can replace the default Sylius logo:
<figure><img src="../.gitbook/assets/image (3).png" alt=""><figcaption></figcaption></figure>
### Step 1: Add Your Custom Logo
1. Copy your logo file to the following directory:
```bash
assets/shop/images/logo.png
```
2. Next, you need to import the logo in the `entry.js` file located at:
```bash
assets/shop/entry.js
```
3. Add the following line to import the logo:
<pre class="language-js"><code class="lang-js"><strong>import './images/logo.png';
</strong></code></pre>
4. After making this change, run the following command to rebuild the assets:
```bash
yarn build
```
### Step 2: Embed the Logo in the Template
Now, lets create the template that is responsible for displaying the logo. All templates are supposed to be managed and organized in the `/templates` directory. Your new template might look like this:
```twig
<img src="{{ asset('build/app/shop/images/logo.25de7998.png', 'app.shop') }}" alt="Logo"/>
```
Ensure the second argument in the `asset()` function is correct for the app context. For more details, check the [Managing Assets](../the-book/frondend-and-themes.md) page.
### Step 3: Override the Template with Sylius Twig Hooks
{% hint style="info" %}
Sylius Twig Hooks is a completely new concept introduced in Sylius 2.0. You can find dedicated documentation on this topic [here](https://sylius-1.gitbook.io/stack/dWolXcvu3MnA2piZOEle/twig-hooks/getting-started).
{% endhint %}
Sylius 2.0 introduces **Twig Hooks** for customization. First, use the browsers developer console to identify the element you want to change. For the logo, the relevant block is:
<figure><img src="../.gitbook/assets/image.png" alt=""><figcaption><p>DIrect view from the browser</p></figcaption></figure>
In our case, the following block is relevant:
```html
<!-- BEGIN HOOK | name: "sylius_shop.homepage.index.header.content.logo, sylius_shop.base.header.content.logo" -->
<!-- BEGIN HOOKABLE | hook: "sylius_shop.base.header.content.logo", name: "content", template: "@SyliusShop/shared/sylius_logo.html.twig", priority: 0 -->
```
In summary, a **hook** is a specific location within the template where you can attach or override custom content. A **hookable** refers to the individual element (such as a template or component) that is linked to the hook. You can assign multiple hookables to a single hook, allowing for flexible customization.
Since we want to override the logo, we need to reference our custom logo template in the appropriate hook and hookable configuration. A custom configuration for this might look like the following:
```yaml
sylius_twig_hooks:
hooks:
sylius_shop.base.header.content.logo:
content:
template: 'header/content/logo/content/logo.html.twig'
```
Place your custom logo template in the specified path. You can customize the directory structure, but following Sylius hierarchy is recommended for future consistency.
### Step 3 (Alternative Approach): Override the Template with Template Overriding
If you prefer not to use Twig Hooks, you can override the Sylius template directly, the old way.
**Identify the Template**:\
The original logo template is located at:
```bash
<vendor_path>/templates/shared/logo.html.twig
```
**Override It**:\
Create a new file with the same name in the following directory:
```bash
templates/bundles/SyliusShopBundle/shared/logo.html.twig
```
### Step 4: Final Result
After following either method, your custom logo should now be displayed on your store.
<figure><img src="../.gitbook/assets/image (1).png" alt=""><figcaption></figcaption></figure>
### Next Steps: Introducing Custom Business Logic
Congratulations! Youve successfully customized a Sylius template. Lets take things a step further by introducing your **business logic** into the system.
For more information on customizing templates or Sylius template events, check out the [**Customizing Templates**](../the-customization-guide/customizing-templates.md) chapter and the [**Managing Assets**](../the-book/frondend-and-themes.md) documentation.

View file

@ -0,0 +1,21 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Deployment
Development usually takes most of the time in project implementation, but we should not forget about whats at the end of this process—application deployment to the server. We believe that it should be as easy and understandable as possible.
Check out our deployment cookbook:
* 👉 [Introduction to Sylius Cloud by Platform.sh](../the-cookbook-2.0/introduction-to-sylius-cloud-by-platform.sh.md)

View file

@ -0,0 +1,50 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# First Product
Products Management is one of the most important sections of the Sylius Admin panel. The **Catalog** section in the menu offers a wide range of options, but for now, well focus on **product creation**.
## Simple & Configurable Products
When creating a product, you first need to choose between two types:
* **Simple Product**: A product with just one version (e.g., a standard book).
* **Configurable Product**: A product that offers options for customers to choose from (e.g., size, color, etc.).
Check out the Products chapter in the Sylius Book for more detailed information.
<figure><img src="../.gitbook/assets/product_type.png" alt=""><figcaption></figcaption></figure>
During the product creation process, you can define many important attributes:
* **Price**: How much does the product cost?
* **Shipping**: Is it a physical product that requires shipping?
* **Inventory Tracking**: Should the product be tracked within the inventory system?
* **Channels**: On which channels will the product be available for purchase?
* **Taxes**: Should any taxes be applied during checkout?
Take some time to explore these options in detail later. For now, lets focus on filling in the essential data required to create a product.
<figure><img src="../.gitbook/assets/product_create_1.png" alt=""><figcaption></figcaption></figure>
<figure><img src="../.gitbook/assets/product_create_2.png" alt=""><figcaption></figcaption></figure>
<figure><img src="../.gitbook/assets/product_create_3.png" alt=""><figcaption></figcaption></figure>
## Summary
Great, the first stage is done!&#x20;
Now that the basic setup is done, we can move on to more advanced topics, such as **customizing Sylius features** and **deploying your store** to a server to make it available to the world.

View file

@ -0,0 +1,55 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: false
pagination:
visible: true
---
# Index
{% content-ref url="installation.md" %}
[installation.md](installation.md)
{% endcontent-ref %}
{% content-ref url="basic-configuration.md" %}
[basic-configuration.md](basic-configuration.md)
{% endcontent-ref %}
{% content-ref url="shipping-and-payment.md" %}
[shipping-and-payment.md](shipping-and-payment.md)
{% endcontent-ref %}
{% content-ref url="first-product.md" %}
[first-product.md](first-product.md)
{% endcontent-ref %}
{% content-ref url="customizing-the-shop.md" %}
[customizing-the-shop.md](customizing-the-shop.md)
{% endcontent-ref %}
{% content-ref url="customizing-business-logic.md" %}
[customizing-business-logic.md](customizing-business-logic.md)
{% endcontent-ref %}
{% content-ref url="using-api.md" %}
[using-api.md](using-api.md)
{% endcontent-ref %}
{% content-ref url="installing-plugins.md" %}
[installing-plugins.md](installing-plugins.md)
{% endcontent-ref %}
{% content-ref url="deployment.md" %}
[deployment.md](deployment.md)
{% endcontent-ref %}
{% content-ref url="summary.md" %}
[summary.md](summary.md)
{% endcontent-ref %}

View file

@ -0,0 +1,25 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Installation
Check the chosen pages of The Book:
{% content-ref url="../the-book/installation/system-requirements.md" %}
[system-requirements.md](../the-book/installation/system-requirements.md)
{% endcontent-ref %}
{% content-ref url="../the-book/installation/sylius-ce-installation/" %}
[sylius-ce-installation](../the-book/installation/sylius-ce-installation/)
{% endcontent-ref %}

View file

@ -0,0 +1,74 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Installing Plugins
Sylius is highly flexible and can easily be customized to fit your business needs. However, you dont always have to build custom solutions from scratch! Sylius supports the creation of **plugins**, which are the best way to extend its functionality and share your custom features with the community.
You can take advantage of plugins developed by the **Sylius Core Team** or the **Sylius Community**. While the official Sylius website lists approved plugins, many more are available within the wider Sylius ecosystem.
***
#### Example: Installing SyliusCmsPlugin
To showcase how easy and powerful Sylius plugins can be, lets install the popular **SyliusCmsPlugin** developed by BitBag. This plugin adds CMS features to your Sylius store.
**Installation Steps**
The installation process follows the typical steps used for most Sylius plugins:
1. **Install the Plugin Using Composer**
Run the following command to add the plugin to your project:
```bash
composer require bitbag/cms-plugin
```
2. **Configure the Plugin**
After installation, you'll need to configure the plugin. This usually involves importing the routing for the plugin in your `config/routes.yaml` file.
3. **Update the Database**
Run database migrations to apply any necessary changes:
```bash
php bin/console doctrine:migrations:migrate
```
4. **Additional Steps**
Some plugins may require additional steps. For example, the **SyliusCmsPlugin** requires the installation of CKEditor. Follow the plugins documentation for these steps.
***
#### Using the Plugin
Once installed and configured, you can immediately start using the plugins features in your shop:
<figure><img src="../.gitbook/assets/plugin-installed.png" alt="" width="249"><figcaption></figcaption></figure>
***
#### Why Use Plugins?
Plugins are one of the fastest and easiest ways to customize your Sylius store. Before creating a custom solution, always check the existing plugins available in the Sylius ecosystem—you might find that the functionality you need has already been developed!
By using plugins, you avoid reinventing the wheel and speed up the development process, allowing you to focus on other critical aspects of your shop.
***
#### Learn more
* [The Book: Plugins](../the-book/sylius-plugins/)
* [Plugins Development Guide](../the-book/sylius-plugins/plugin-development-guide.md)
* :sparkles: [Sylius Store: The Official Plugins List](https://store.sylius.com/)

View file

@ -0,0 +1,44 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Shipping & Payment
With the basic configuration completed, we can now move forward and set up the necessary options for customers to buy your products. During the checkout process, customers need to choose how they want their orders to be shipped and paid for.
## Shipping method
Sylius allows you to configure different **shipping methods** based on factors such as the shipping address (which is where the **Zone** concept becomes important) or the product's affiliation with a specific **Shipping Category**.
Lets create a shipping method named **“InPost”** that charges $5.00 for the entire order.
<figure><img src="../.gitbook/assets/shipping_method.png" alt=""><figcaption></figcaption></figure>
## Payment method
Customers also need to choose how they wish to pay for their orders. At least one **payment method** is required for checkout.
Before creating a payment method, ensure you have set up a **payment gateway** if necessary. Sylius supports an **Offline** payment method by default, but you can add more payment gateways via plugins.
Heres how to create a payment method:
1. Go to the **Payment Methods** section.
2. Select the payment method gateway for which you will create the payment method (if applicable) and configure it:
<figure><img src="../.gitbook/assets/payment_method.png" alt=""><figcaption></figcaption></figure>
{% hint style="info" %}
You can find additional payment gateway integrations by exploring [Sylius plugins](https://sylius.com/plugins).
{% endhint %}
Great! The only thing left is creating some products, and we can go shopping!\

View file

@ -0,0 +1,40 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Summary
We hope youve enjoyed your first steps with Sylius! Now that youve gained some foundational knowledge, the possibilities are endless for how you can use Sylius, customize it, and add new features with both your code and contributions from the community.
#### A Few Tips Before You Go:
* **Want to dive deeper into Sylius features?**\
Check out [The Book](../the-book/index.md), where you'll find comprehensive information on everything Sylius has to offer.
* **Interested in making more customizations?**\
Explore [The Customization Guide](../the-customization-guide/index.md) for insights on how to tailor Sylius to your unique needs.
* **Have cool features to share with the community?**\
Head over to the [Sylius Plugins](../the-book/sylius-plugins/) chapter to learn how to contribute your work.
***
#### Join the Sylius Community
The most important tip: Sylius thrives because of its community!
* [**Join us on Slack** ](https://sylius.com/slack)to connect with other developers, get help, and share ideas.
* [**Follow our GitHub repository**](https://github.com/Sylius/Sylius) **⭐️** to stay updated with the latest Sylius releases.
* **Contribute** by opening issues, submitting pull requests, or joining discussions. Together, we can keep making Sylius better and empower commerce with cutting-edge technology!
***
Were excited to have you on board—good luck on your Sylius journey!

View file

@ -0,0 +1,334 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Using API
Since Sylius 1.8, we have offered a new API based on ApiPlatform. Below are examples of how to use the API for basic shop operations. **Public API documentation is available** [**here**](https://master-ce.demo.sylius.com/api/v2/docs)**.**
## Register a customer
To register a new customer, send a single `POST` request:
```bash
curl -X 'POST' \
'https://master-ce.demo.sylius.com/api/v2/shop/customers' \
-H 'accept: */*' \
-H 'Content-Type: application/ld+json' \
-d '{
"firstName": "shop",
"lastName": "user",
"email": "shop.user@example.com",
"password": "pa$$word",
"subscribedToNewsletter": true
}'
```
If the response status is **204**, the customer was registered successfully.
<figure><img src="../.gitbook/assets/api_platform_shop_customer_post.png" alt=""><figcaption></figcaption></figure>
### Login to the shop
After registering a customer, you can log in to obtain an authentication token, which is required to access more shop endpoints.
```bash
curl -X 'POST' \
'https://master-ce.demo.sylius.com/api/v2/shop/customers/token' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"email": "shop.user@example.com",
"password": "pa$$word"
}'
```
If successful, the response will have a **200** status code and include the token and customer IRI:
```json
{
"token": "string",
"customer": "iri"
}
```
{% hint style="warning" %}
If your shop requires email authentication, no token will be returned.
{% endhint %}
Use the token to authenticate subsequent API requests:
```bash
curl -X 'METHOD' \
'api-url' \
-H 'accept: application/ld+json' \
-H 'Authorization: Bearer token'
```
## Basic Operations: Products, Carts, and Orders
Once the customer is authorized, you can start interacting with products, carts, and orders via the API. Below are the typical operations:
### Adding product to cart
**Create a Cart:**
You can create a cart for a logged-in customer by sending a `POST` request:
```bash
curl -X 'POST' \
'https://master-ce.demo.sylius.com/api/v2/shop/orders' \
-H 'accept: application/ld+json' \
-H 'Content-Type: application/ld+json' \
-H 'Authorization: Bearer token' \
-d '{
# "localeCode": "string" (optional)
}'
```
{% hint style="info" %}
```
You can have your cart in a different locale if needed. If no `localeCode` is provided, the channel's default will be added automatically.
```
{% endhint %}
Response status **201** will include cart details and the cart's `tokenValue`, which is needed for subsequent operations.
<figure><img src="../.gitbook/assets/api_platform_shop_orders_post.png" alt=""><figcaption></figcaption></figure>
**Add a Product to the Cart:**
First, retrieve a product variant by sending a `GET` request:
```bash
curl -X 'GET' \
'https://master-ce.demo.sylius.com/api/v2/shop/product-variants?page=1&itemsPerPage=30' \
-H 'accept: application/ld+json' \
-H 'Authorization: Bearer token'
```
```javascript
// ...
{
"@id": "/api/v2/shop/product-variants/Everyday_white_basic_T_Shirt-variant-0",
"@type": "ProductVariant",
"id": 123889,
"code": "Everyday_white_basic_T_Shirt-variant-0",
"product": "/api/v2/shop/products/Everyday_white_basic_T_Shirt",
"optionValues": [
"/api/v2/shop/product-option-values/t_shirt_size_s"
],
"translations": {
"en_US": {
"@id": "/api/v2/shop/product-variant-translations/123889",
"@type": "ProductVariantTranslation",
"id": 123889,
"name": "S",
"locale": "en_US"
}
},
"price": 6420,
"originalPrice": 6420,
"inStock": true
}
// ...
```
Use the `@id` of the desired variant, and add it to the cart:
```bash
curl -X 'PATCH' \
'https://master-ce.demo.sylius.com/api/v2/shop/orders/rl1KwtiSLA/items' \
-H 'accept: application/ld+json' \
-H 'Authorization: Bearer token' \
-H 'Content-Type: application/merge-patch+json' \
-d '{
"productVariant": "/api/v2/shop/product-variants/Everyday_white_basic_T_Shirt-variant-0",
"quantity": 1
}'
```
<figure><img src="../.gitbook/assets/api_platform_shop_orders_items_patch.png" alt=""><figcaption></figcaption></figure>
The response status **200** confirms the product has been added to the cart.
```bash
{
# Rest of orders body
"items": [
{
"@id": "/api/v2/shop/order-items/59782",
"@type": "OrderItem",
"variant": "/api/v2/shop/product-variants/Everyday_white_basic_T_Shirt-variant-0",
"productName": "Everyday white basic T-Shirt",
"id": 59782,
"quantity": 1,
"unitPrice": 6420,
"total": 6869,
"subtotal": 6420
}
],
# Rest of orders body
}
```
### Changing the Product Quantity in the Cart
To change the quantity of a product already added to the cart, use the following `PATCH` request:
```bash
curl -X 'PATCH' \
'https://master-ce.demo.sylius.com/api/v2/shop/orders/OPzFiAWefi/items/59782' \
-H 'accept: application/ld+json' \
-H 'Authorization: Bearer token' \
-H 'Content-Type: application/merge-patch+json' \
-d '{
"quantity": 3
}'
```
<figure><img src="../.gitbook/assets/api_platform_shop_orders_change_quantity.png" alt=""><figcaption></figcaption></figure>
The response status **200** confirms the quantity change.
<figure><img src="../.gitbook/assets/api_platform_shop_orders_change_quantity_response.png" alt=""><figcaption></figcaption></figure>
### Completing the Order
Once the cart is filled, follow these steps to complete the order:
#### **1. Add Customer Address**
Add the customer's billing and shipping address by sending a `PATCH` request:
```bash
curl -X 'PATCH' \
'https://master-ce.demo.sylius.com/api/v2/shop/orders/rl1KwtiSLA/address' \
-H 'accept: application/ld+json' \
-H 'Authorization: Bearer token' \
-H 'Content-Type: application/merge-patch+json' \
-d '{
"email": "shop.user@example.com",
"billingAddress": {
"city": "California",
"street": "Coral str",
"postcode": "90210",
"countryCode": "US",
"firstName": "David",
"lastName": "Copperfield"
}
}'
```
<figure><img src="../.gitbook/assets/api_platform_shop_orders_addressing.png" alt=""><figcaption></figcaption></figure>
{% hint style="info" %}
If no `shippingAddress` is provided, the `billingAddress` will be used for both.
{% endhint %}
<figure><img src="../.gitbook/assets/api_platform_shop_orders_addressing_response.png" alt=""><figcaption></figcaption></figure>
#### **2. Select Shipping and Payment Methods**
First, get the available shipping and payment methods:
```bash
curl -X 'GET' \
'https://master-ce.demo.sylius.com/api/v2/shop/orders/rl1KwtiSLA' \
-H 'accept: application/ld+json' \
-H 'Authorization: Bearer token'
```
Use the methods' `@id` in the next steps.
```bash
"payments": [
{
"@id": "/api/v2/shop/payments/20446",
"@type": "Payment",
"id": 20446,
"method": "/api/v2/shop/payment-methods/cash_on_delivery"
}
],
"shipments": [
{
"@id": "/api/v2/shop/shipments/17768",
"@type": "Shipment",
"id": 17768,
"method": "/api/v2/shop/shipping-methods/ups"
}
],
```
**For Shipping:**
```bash
curl -X 'PATCH' \
'https://master-ce.demo.sylius.com/api/v2/shop/orders/rl1KwtiSLA/shipments/17768' \
-H 'accept: application/ld+json' \
-H 'Authorization: Bearer token' \
-H 'Content-Type: application/merge-patch+json' \
-d '{
"shippingMethod": "/api/v2/shop/shipping-methods/ups"
}'
```
<figure><img src="../.gitbook/assets/api_platform_shop_orders_choose_shipping.png" alt=""><figcaption></figcaption></figure>
**For Payment:**
```bash
curl -X 'PATCH' \
'https://master-ce.demo.sylius.com/api/v2/shop/orders/{cartToken}/payments/{paymentId}' \
-H 'accept: application/ld+json' \
-H 'Authorization: Bearer token' \
-H 'Content-Type: application/merge-patch+json' \
-d '{
"paymentMethod": "/api/v2/shop/payment-methods/cash_on_delivery"
}'
```
#### **3. Complete the Order**
Finally, complete the order by sending the following request:
```bash
curl -X 'PATCH' \
'https://master-ce.demo.sylius.com/api/v2/shop/orders/rl1KwtiSLA/complete' \
-H 'accept: application/ld+json' \
-H 'Authorization: Bearer token' \
-H 'Content-Type: application/merge-patch+json' \
-d '{
"notes": "your note"
}'
```
<figure><img src="../.gitbook/assets/api_platform_shop_orders_completed.png" alt=""><figcaption></figcaption></figure>
The response status **200** confirms the order completion, with the `checkoutState` changed to **completed**.
```bash
{
# Orders body
"currencyCode": "USD",
"localeCode": "en_US",
"checkoutState": "completed",
"paymentState": "awaiting_payment",
"shippingState": "ready",
# Orders body
}
```
#### Final Output
The full checkout process has now been completed using Sylius API. With this API, you can create a fully functional shop frontend based on Sylius' backend logic.

View file

@ -0,0 +1,31 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Organization
We aim to shape the future of eCommerce, leveraging the strength of open source and the power of community-driven development. Our team ensures that Sylius as a framework stays up-to-date, innovative, and tailored to the ever-changing needs of modern eCommerce, making it a leading choice for those seeking a customizable and powerful solution.
This chapter describes the rules and processes we use to organize our work.
{% content-ref url="backwards-compatibility-promise.md" %}
[backwards-compatibility-promise.md](backwards-compatibility-promise.md)
{% endcontent-ref %}
{% content-ref url="broken-reference" %}
[Broken link](broken-reference)
{% endcontent-ref %}
{% content-ref url="broken-reference" %}
[Broken link](broken-reference)
{% endcontent-ref %}

View file

@ -0,0 +1,79 @@
# Backwards Compatibility Promise
Sylius follows a versioning strategy called [Semantic Versioning](https://semver.org/). It means that only major releases include BC breaks, whereas minor releases include new features without breaking backwards compatibility.
Since Sylius is based on Symfony, our BC promise extends [Symfonys Backward Compatibility Promise](https://symfony.com/doc/current/contributing/code/bc.html) with a few new rules and exceptions stated in this document. We also follow [Symfonys Experimental Features](https://symfony.com/doc/current/contributing/code/experimental.html) process to be able to innovate safely.
### Minor and patch releases
Patch releases (such as 1.0.x, 1.1.x, etc.) do not require any additional work apart from cleaning the Symfony cache.
Minor releases (such as 1.1.0, 1.2.0, etc.) require to run database migrations.
### Code covered
This BC promise applies to all of Sylius PHP code except for:
* code tagged with `@internal` or `@experimental` tags
* event listeners
* model and repository interfaces
* PHPUnit tests (located at `tests/`, `src/**/Tests/`)
* PHPSpec tests (located at `src/**/spec/`)
* Behat tests (located at `src/Sylius/Behat/`)
* final controllers (their service name is still covered with BC promise)
### Additional rules
#### Models & model interfaces
To fulfill the constant Sylius need to evolve, model interfaces are excluded from this BC promise. Methods may be added to the interface, but backward compatibility is promised as long as your custom model extends the one from Sylius, which is true for most cases.
#### Repositories & repository interfaces
Following the reasoning same as above and due to technological constraints, repository interfaces are also excluded from this BC promise.
#### Event listeners
They are excluded from this BC promise, but they should be as simple as possible and always call another service. Behaviour theyre providing (the end result) is still included in BC promise.
#### Final controllers
It is allowed to change their dependencies, but the behaviour theyre providing is still included in BC promise. The service name and class name will not change.
#### Routing
The currently present routes cannot have their name changed, but optional parameters might be added to them. All the new routes will start with `sylius_` prefix in order to avoid conflicts.
#### Services
Services names cannot change, but new services might be added with `sylius.` or `Sylius\\` prefix.
#### Templates
Neither template events, block or templates themselves cannot be deleted or renamed.
### Deprecations
Before we remove or replace code covered by this backwards compatibility promise, it is first deprecated in the next minor release before being removed in the next major release.
A code is marked as deprecated by adding a `@deprecated` PHPDoc to relevant classes, methods, properties:
```
/**
* @deprecated Deprecated since version 1.X. Use XXX instead.
*/
```
The deprecation message should indicate the version in which the class/method was deprecated and how the feature was replaced (whenever possible).
A PHP deprecation must also be triggered to help people with the migration, for instance:
```
trigger_deprecation(
'sylius/some-package', // package name
'1.x', // package version
'A is deprecated and will be removed in Sylius 2.0. Use B instead.', // message
);
```
You should not use the `@trigger_error()` function.\

View file

@ -0,0 +1,6 @@
---
hidden: true
---
# Release Cycle

View file

@ -0,0 +1,2 @@
# Behaviour Driven Development

View file

@ -0,0 +1,2 @@
# How to add a new context?

View file

@ -0,0 +1,2 @@
# How to add a new page object?

View file

@ -0,0 +1,2 @@
# How to define a new suite?

View file

@ -0,0 +1,2 @@
# How to use transformers?

2
docs/tests/index.md Normal file
View file

@ -0,0 +1,2 @@
# Index

View file

@ -0,0 +1,6 @@
---
hidden: true
---
# API

View file

@ -0,0 +1,2 @@
# #todo

View file

@ -0,0 +1,2 @@
# Architecture

View file

@ -0,0 +1,90 @@
# Architectural Drivers
Architectural Drivers are the key factors that influence all the decisions we make during application development. Historically, a lot of them were taken unconsciously, but, happily, resulted in good decisions that we can undoubtedly justify today. All of them have a significant influence on the Sylius as an application - they can and should be used to guide us during the development, to make the best decision for the product.
### Technical constraints
#### Programming language
**PHP**
Due to the decision to base Sylius on the **Symfony** framework (see below), **PHP** was the only possible option as a programming language. Nevertheless, a good decision! This language has been dynamically developing for the last few years and still powers up most of the websites and applications on the World Wide Web.
Currently supported PHP versions can be seen in [this chapter.](../installation/system-requirements.md)
#### Main frameworks and libraries
**Fullstack Symfony**
Sylius is based on Symfony, a leading PHP framework for creating web applications. Using Symfony allows developers to work better and faster by providing them with the certainty of developing an application that is fully compatible with the business rules, structured, maintainable, and upgradable. It also allows developers to save time by providing generic reusable modules.
[Learn more about Symfony](https://symfony.com/what-is-symfony).
**Doctrine**
Sylius, by default, uses the Doctrine ORM to manage all entities. Doctrine is a family of PHP libraries focused on providing a data persistence layer. The most important are the object-relational mapper (ORM) and the database abstraction layer (DBAL). One of Doctrines key features is the possibility to write database queries in Doctrine Query Language (DQL) - an object-oriented dialect of SQL.
For a deeper understanding of how Doctrine works, please refer to the [excellent documentation on their official website](https://www.doctrine-project.org/projects/doctrine-orm/en/3.1/index.html).
**Twig**
Twig is a modern template engine for PHP that is fast, secure, and flexible. Twig is being used by Symfony.
To read more about Twig, [go here](https://twig.symfony.com/).
**API Platform**
API Platform is a modern solution for developing high-quality APIs. API Platform works by default with Symfony and depends on its components.
**Third-Party Libraries**
Sylius uses a lot of libraries for various tasks:
* [Payum](https://github.com/Payum/Payum) for payments
* [KnpMenu](https://symfony.com/doc/current/bundles/KnpMenuBundle/index.html) - for shop and admin menus
* [Flysystem](https://github.com/thephpleague/flysystem) - for filesystem abstraction (store images locally, Amazon S3 or external server)
* [Imagine](https://github.com/liip/LiipImagineBundle) - for image processing, generating thumbnails, and cropping
* [Pagerfanta](https://github.com/whiteoctober/Pagerfanta) - for pagination
### Functional requirements
All of the functionality provided by default with Sylius is described as user stories using Behat scenarios. Take a look [here](https://github.com/Sylius/Sylius/tree/2.0/features) to browse them.
### Quality attributes
Sylius has focused a lot on software quality since its very beginning. We use test-driven methodologies like [TDD and BDD](broken-reference) to ensure the reliability of the provided functionalities. Moreover, as Sylius is not the end-project (it is rarely used in a _vanilla_ version), but serves as the base for the actual applications, its crucial to take care about its ability to fulfill such a role.
#### Extendability
Sylius offers a lot of standard e-commerce features, that could and should be used as a base to introduce more advanced and business-specific functionalities.
**Question to be asked:** is it possible to easily add new, more advanced functionality to the module/class/service I implement? **Examples:**
* promotions [actions](https://github.com/Sylius/Sylius/blob/2.0/src/Sylius/Bundle/CoreBundle/Resources/config/services/promotion.xml) and [rules](https://github.com/Sylius/Sylius/blob/2.0/src/Sylius/Bundle/PromotionBundle/Resources/config/services.xml) registered with tags
* state machine [callbacks](https://github.com/Sylius/Sylius/blob/2.0/src/Sylius/Bundle/CoreBundle/Resources/config/app/state\_machine/sylius\_order.yml)
* resource [events](https://github.com/Sylius/SyliusResourceBundle/blob/1.12/src/Bundle/Controller/ResourceController.php#L175)
#### Customizability
Seemingly similar to the previous one, but essentially different. Focuses on making it possible to override the standard functionality with a different one, while still keeping the whole process working. The most important (but not the only) step to reach it is using interfaces with small, focused, and granular services. Customizability should be kept on all levels - from the single service to the whole module/component.
**Question to be asked:** is it possible to replace this functionality and not break the whole process? **Examples:**
* service for [calculating the variant prices](https://github.com/Sylius/Sylius/blob/2.0/src/Sylius/Component/Core/Calculator/ProductVariantPriceCalculator.php) that can be overridden to provide more advanced pricing strategies
* [resource configuration](https://github.com/Sylius/SyliusResourceBundle/blob/1.12/docs/reference.md), which gives possibility to configure any service as a resource-specific controller/factory/repository etc.
#### Testability
As mentioned before, Sylius embraces test-driven methodologies from its very beginning. Therefore, every class (with some exceptions) should be described with unit tests, every functionality should be designed through Behat acceptance scenarios. Highly tested code is crucial to ensure another, also important driver, which is the **reliability** of the software.
**Question to be asked:** is my module/class easy to be tested, to protect it from potential regression?
As history has shown, if something is difficult to test, there is a huge chance its not designed or written properly.
### Sources and inspirations
This chapter was created and inspired by the following sources:
* [Architectural Drivers in Modern Software Architecture](https://medium.com/@janerikfra/architectural-drivers-in-modern-software-architecture-cb7a42527bf2) by Erik Franzen
* [Modular Monolith: Architectural Drivers](http://www.kamilgrzybek.com/design/modular-monolith-architectural-drivers/) by Kamil Grzybek
* 🇵🇱 [Droga Nowoczesnego Architekta](https://droganowoczesnegoarchitekta.pl/) - a polish online course for software architects and engineers\

View file

@ -0,0 +1,59 @@
# Architecture Overview
Before we dive separately into every Sylius concept, you need to have an overview of how our main application is structured.
### Architectural drivers
All architectural decisions need to be backed by a valid reason. The fundamental signposts we use to take such choices, are explained in [Architectural Drivers](architectural-drivers.md) section.
Specific decisions we make during the development are often explained using Architectural Decision Records. Theyre stored in the [main Sylius repository](https://github.com/Sylius/Sylius/tree/1.11/adr) for better visibility.
### Architecture
On the below image you can see the symbolic representation of Sylius architecture.
<figure><img src="../../.gitbook/assets/architecture_overview.png" alt="" width="375"><figcaption></figcaption></figure>
Keep on reading this chapter to learn more about each of its parts: Shop, Admin, API, Core, Components and Bundles.
### Division into Components, Bundles, Platform
You already know that Sylius is built from components and Symfony bundles, which are integration layers with the framework. All bundles share the same conventions for naming things and the way of data persistence.
#### Components
Every single component of Sylius can be used standalone. Taking the `Taxation` component as an example, its only responsibility is to calculate taxes, it does not matter whether these will be taxes for products or anything else, it is fully decoupled. In order to let the Taxation component operate on your objects you need to have them implementing the `TaxableInterface`. Since then they can have taxes calculated. Such approach is true for every component of Sylius. Besides components that are strictly connected to the e-commerce needs, we have plenty of components that are more general. For instance Attribute, Mailer, Locale etc.
All the components are packages available via [Packagist](https://packagist.org/).
#### Bundles
These are the Symfony Bundles - therefore if you are a Symfony Developer, and you would like to use the Taxation component in your system, but you do not want to spend time on configuring forms or services in the container. You can include the `TaxationBundle` in your application with minimal or even no configuration to have access to all the services, models, configure tax rates, tax categories and use that for any taxes you will need.
#### Platform
This is a fullstack Symfony Application, based on Symfony Standard. Sylius Platform gives you the classic, quite feature rich webshop. Before you start using Sylius you will need to decide whether you will need a full platform with all the features we provide, or maybe you will use decoupled bundles and components to build something very custom, maybe smaller, with different features. But of course the platform itself is highly flexible and can be easily customized to meet all business requirements you may have.
### Division into Core, Admin, Shop, Api
#### Core
The Core is another component that integrates all the other components. This is the place where for example the `ProductVariant` finally learns that it has a `TaxCategory`. The Core component is where the `ProductVariant` implements the `TaxableInterface` and other interfaces that are useful for its operation. Sylius has here a fully integrated concept of everything that is needed to run a webshop. To get to know more about concepts applied in Sylius - keep on reading [The Book](../index.md).
#### Admin
In every system with the security layer the functionalities of system administration need to be restricted to only some users with a certain role - Administrator. This is the responsibility of our `AdminBundle` although if you do not need it, you can turn it off. Views have been built using [Bootstrap](https://getbootstrap.com/).
#### Shop
Our `ShopBundle` is basically a standard B2C interface for everything that happens in the system. It is made mainly of yaml configurations and templates. Also here views have been built using [Bootstrap](https://getbootstrap.com/).
#### API
When we created our API based on API Platform framework we have done everything to offer API as easy as possible to use by developer. The most important features of our API:
* All operations are grouped by _shop_ and _admin_ context (two prefixes);
* Developers can enable or disable entire API by changing single parameter (check [this](../api/) chapter);
* We create all endpoints implementing the REST principles and we are using http verbs (POST, GET, PUT, PATCH, DELETE);
* Returned responses contain minimal information (developer should extend serialization if need more data);
* Entire business logic is separated from API - if it necessary we dispatch command instead mixing API logic with business logic.

View file

@ -0,0 +1,48 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Contact
The functionality of contacting the shop support/admin is in Sylius very basic. Each **Channel** of your shop may have a `contactEmail` configured on it. This will be the email address to support.
### Contact form
The contact form can be found on the `/contact` route.
{% hint style="info" %}
When the `contactEmail` is not configured on the channel, the customer will see the following flash message:
\
<img src="../../.gitbook/assets/contact_request_error.png" alt="" data-size="original">
{% endhint %}
The form itself has only two fields `email` (which will be filled automatically for the logged-in users) and `message`.
### ContactEmailManager
The **ContactEmailManager** service is responsible for the sending of a contact request email. It can be found under the `sylius.email_manager.contact` service id.
### ContactController
The controller responsible for the request action handling is the **ContactController**. It has the `sylius.controller.shop.contact` service id.
### Configuration
The routing for contact can be found in the `Sylius/Bundle/ShopBundle/Resources/config/routing/contact.yml` file. By overriding that routing you will be able to customize **redirect url, error flash, success flash, form, and its template**.
You can also change the template of the email that is being sent by simply overriding it in your project in the `templates/bundles/SyliusShopBundle/Email/contactRequest.html.twig` file.
### Learn more
* [Emails - Documentation](e-mails.md)

View file

@ -0,0 +1,214 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# E-Mails
Sylius is sending various e-mails and this chapter is a reference about all of them. Continue reading to learn what e-mails are sent, when, and how to customize the templates. To understand how e-mail sending works internally, please refer to [SyliusMailerBundle documentation](https://github.com/Sylius/SyliusMailerBundle/blob/master/docs/index.md). To learn more about mailer services configuration, read the dedicated [cookbook](../../the-cookbook-2.0/how-to-customize-email-templates-per-channel.md).
### User Confirmation
Every time a customer registers via the registration form, a user registration e-mail is sent to them.
**Code**: `user_registration`
**The default template**: `@SyliusShop/Email/userRegistration.html.twig`
You also have the following parameters available:
* `user`: Instance of the user model
* `channel`: Currently used channel
* `localeCode`: Currently used locale code
### Email Verification
When a customer registers via the registration form, besides the User Confirmation an Email Verification is sent.
**Code**: `verification_token`
**The default template**: `@SyliusShop/Email/verification.html.twig`
You also have the following parameters available:
* `user`: Instance of the user model
* `channel`: Currently used channel
* `localeCode`: Currently used locale code
### Password Reset
This e-mail is used when the user requests to reset their password in the login form.
**Code**: `reset_password_token`
**The default template**: `@SyliusShop/Email/passwordReset.html.twig`
You also have the following parameters available:
* `user`: Instance of the user model
* `channel`: Currently used channel
* `localeCode`: Currently used locale code
### Order Confirmation
This e-mail is sent when an order is placed.
**Code**: `order_confirmation`
**The default template**: `@SyliusShop/Email/orderConfirmation.html.twig`
You also have the following parameters available:
* `order`: Instance of the order, with all its data
* `channel`: Channel in which an order was placed
* `localeCode`: Locale code in which an order was placed
### Shipment Confirmation
This e-mail is sent when the orders shipping process has started.
**Code**: `shipment_confirmation`
**The default template**: `@SyliusAdmin/Email/shipmentConfirmation.html.twig`
You have the following parameters available:
* `shipment`: Shipment instance
* `order`: Instance of the order, with all its data
* `channel`: Channel in which an order was placed
* `localeCode`: Locale code in which an order was placed
### Contact Request
This e-mail is sent when a customer validates the contact form.
**Code**: `contact_request`
**The default template**: `@SyliusShop/Email/contactRequest.html.twig`
You have the following parameters available:
* `data`: An array of submitted data from a form
* `channel`: Channel in which an order was placed
* `localeCode`: Locale code in which an order was placed
{% embed url="https://sylius.com/plus/?utm_campaign=plus&utm_medium=cta&utm_source=docs" fullWidth="true" %}
### Sylius Plus: Return Requests Emails
{% hint style="info" %}
What are Return Requests? Check [here](../carts-and-orders/returns.md)!
{% endhint %}
#### Return Request Confirmation
This email is sent after a return request has been created by a customer.
**Code**: `sylius_plus_return_request_confirmation`
**The default template**: `@SyliusPlusPlugin/Returns/Infrastructure` `/Resources/views/Emails/returnRequestConfirmation.html.twig`
Parameters:
* `order` - for which the return request has been created
#### Return Request Acceptation
This email is sent when the administrator accepts a return request.
**Code**: `sylius_plus_return_request_accepted`
**The default template**: `@SyliusPlusPlugin/Returns/Infrastructure` `/Resources/views/Emails/returnRequestAcceptedNotification.html.twig`
Parameters:
* `returnRequest` which has been accepted
* `order` of the accepted return request
#### Return Request Rejection
This email is sent when the administrator rejects a return request.
**Code**: `sylius_plus_return_request_rejected`
**The default template**: `@SyliusPlusPlugin/Returns/Infrastructure` `/Resources/views/Emails/returnRequestRejectedNotification.html.twig`
Parameters:
* `returnRequest` which has been rejected
* `order` of the rejected return request
#### Return Request Resolution Change
This email is sent when the administrator changes the return requests resolution proposed by a customer.
**Code**: `sylius_plus_return_request_resolution_changed`
**The default template**: `@SyliusPlusPlugin/Returns/Infrastructure` `/Resources/views/Emails/returnRequestResolutionChangedNotification.html.twig`
Parameters:
* `returnRequest` whose resolution has been changed
* `order` of the modified return request
#### Return Request: Repaired Items Sent
This email is sent when the administrator marks that a return requests repaired items have been sent back to the Customer.
**Code**: `sylius_plus_return_request_repaired_items_sent`
**The default template**: `@SyliusPlusPlugin/Returns/Infrastructure` `/Resources/views/Emails/returnRequestRepairedItemsSentNotification.html.twig`
Parameters:
* `returnRequest` of which the items were sent
* `order` of the return request
<div data-full-width="true">
<figure><img src="../../.gitbook/assets/banner.png" alt=""><figcaption></figcaption></figure>
</div>
### How to send an Email programmatically?
For sending emails **Sylius** is using a dedicated service - **Sender**. Additionally, we have **EmailManagers** for Order Confirmation ([OrderEmailManager](https://github.com/Sylius/Sylius/blob/2.0/src/Sylius/Bundle/ShopBundle/EmailManager/OrderEmailManager.php)) and Shipment Confirmation \
([ShipmentEmailManager](https://github.com/Sylius/Sylius/blob/2.0/src/Sylius/Bundle/AdminBundle/EmailManager/ShipmentEmailManager.php)).
{% hint style="info" %}
While using **Sender** you have the available emails of Sylius available under constants in:
* [Core - Emails](https://github.com/Sylius/Sylius/blob/2.0/src/Sylius/Bundle/CoreBundle/Mailer/Emails.php)
* [User - Emails](https://github.com/Sylius/Sylius/blob/2.0/src/Sylius/Bundle/UserBundle/Mailer/Emails.php)
{% endhint %}
Example using **Sender**:
```php
/** @var SenderInterface $sender */
$sender = $this->container->get('sylius.email_sender');
$sender->send(\Sylius\Bundle\UserBundle\Mailer\Emails::EMAIL_VERIFICATION_TOKEN, ['sylius@example.com'], ['user' => $user, 'channel' => $channel, 'localeCode' => $localeCode]);
```
Example using **EmailManager**:
```php
/** @var OrderEmailManagerInterface $sender */
$orderEmailManager = $this->container->get('sylius.email_manager.order');
$orderEmailManager->sendConfirmationEmail($order);
```
### Learn more
* [Mailer - Documentation](https://github.com/Sylius/SyliusMailerBundle/blob/master/docs/index.md)

View file

@ -0,0 +1,80 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Events
{% hint style="info" %}
You can learn more about events in general in [the Symfony documentation](https://symfony.com/doc/current/event\_dispatcher.html).
{% endhint %}
### What is the naming convention of Sylius events?
The events that are designed for the entities have a general naming convention: `sylius.entity_name.event_name`.
The examples of such events are: `sylius.product.pre_update`, `sylius.shop_user.post_create`, `sylius.taxon.pre_create`.
#### Events reference
All Sylius bundles are using [SyliusResourceBundle](https://github.com/Sylius/SyliusResourceBundle/blob/master/docs/index.md), which has some built-in events.
| Event | Description |
| ------------------------------------- | -------------------- |
| sylius.\<resource>.pre\_create | Before persist |
| sylius.\<resource>.post\_create | After flush |
| sylius.\<resource>.pre\_update | Before flush |
| sylius.\<resource>.post\_update | After flush |
| sylius.\<resource>.pre\_delete | Before remove |
| sylius.\<resource>.post\_delete | After flush |
| sylius.\<resource>.initialize\_create | Before creating view |
| sylius.\<resource>.initialize\_update | Before creating view |
#### CRUD events rules
As you should already know, every resource controller is represented by the `sylius.controller.<resource_name>` service. Several useful events are dispatched during the execution of every default action of this controller. When creating a new resource via the `createAction` method, 2 events occur.
First, before the `persist()` is called on the resource, the `sylius.<resource_name>.pre_create` event is dispatched.
After the data storage is updated, `sylius.<resource_name>.post_create` is triggered.
The same set of events is available for the `update` and `delete` operations. All the dispatches are using the `GenericEvent` class and return the resource object by the `getSubject` method.
#### Checkout events rules
To dispatch checkout steps the event names are overloaded. See `_sylius.event` in `src/Sylius/Bundle/ShopBundle/Resources/config/routing/checkout.yml`
| Event | Description |
| ----------------------------------------- | ----------------------------- |
| sylius.order.initialize\_address | Before creating address view |
| sylius.order.initialize\_select\_shipping | Before creating shipping view |
| sylius.order.initialize\_payment | Before creating payment view |
| sylius.order.initialize\_complete | Before creating complete view |
### What events are already used in Sylius?
Even though Sylius has events as entry points to each resource only some of these points are already used in our use cases.
The events already used in Sylius are described in the Book alongside the concepts they concern.
{% hint style="info" %}
What is more, you can easily check all the Sylius events in your application by using this command:\
`php bin/console debug:event-dispatcher | grep sylius`
{% endhint %}
### Customizations
{% hint style="info" %}
**Customizing Logic via Events vs. State Machines**
The logic in which Sylius operates can be customized in two ways. The first of them is using the state machines: which is useful when you need to modify business logic for instance modify the flow of the checkout, and the second is listening to the kernel events related to the entities, which helps modify the HTTP responses visible directly to the user, like displaying notifications, sending emails.
{% endhint %}

View file

@ -0,0 +1,56 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Fixtures
Fixtures are used mainly for testing, but also for having your shop in a certain state, and having defined data - they ensure that there is a fixed environment in which your application is working.
Note
The way Fixtures are designed in Sylius is well described in the [FixturesBundle documentation](https://github.com/Sylius/SyliusFixturesBundle/blob/master/docs/index.md).
### What are the available fixtures in Sylius?
To check what fixtures are defined in Sylius run:
```bash
php bin/console sylius:fixtures:list
```
### How to load Sylius fixtures?
The recommended way to load the predefined set of Sylius fixtures is here:
```bash
php bin/console sylius:fixtures:load
```
### What data is loaded by fixtures in Sylius?
All files that serve for loading fixtures of Sylius are placed in the `Sylius/Bundle/CoreBundle/Fixture/*` directory.
And the specified data for fixtures is stored in the [Sylius/Bundle/CoreBundle/Resources/config/app/fixtures.yml](https://github.com/Sylius/Sylius/blob/2.0/src/Sylius/Bundle/CoreBundle/Resources/config/app/fixtures.yml) file.
### Available configuration options
#### locale
| Configuration key | Function |
| --------------------- | --------------------------------------------------------------------------------------------------- |
| load\_default\_locale | Determine if default shop locale (defined as _%locale%_) parameter will be loaded. True by default. |
| locales | Array of locale codes, which will be loaded. Empty by default. |
### Learn more
* [FixturesBundle documentation](https://github.com/Sylius/SyliusFixturesBundle/blob/master/docs/index.md)

View file

@ -0,0 +1,176 @@
# Resource Layer
We created an abstraction on top of Doctrine, to have a consistent and flexible way to manage all the resources. By “resource” we understand every model in the application. The simplest examples of Sylius resources are “product”, “order”, “tax\_category”, “promotion”, “user”, “shipping\_method” and so on…
There are two types of resources in **Sylius**:
* registered by default - their names begin with `sylius.*` for example: `sylius.product`
* custom resources, from your application which have a separate convention. We place them under `sylius_resource:` `resource_name:` in the `config.yml`. For these, we recommend using the naming convention of `app.*` for instance `app.my_entity`.
Sylius resource management system lives in the **SyliusResourceBundle** and can be used in any Symfony project.
### Services
For every resource you have four essential services available:
* Factory
* Manager
* Repository
* Controller
Let us take the “product” resource as an example. By default, it is represented by an object of a class that implements the `Sylius\Component\Core\Model\ProductInterface`.
### Factory
The factory service gives you the ability to create new default objects. It can be accessed via the `sylius.factory.product.id` (for the Product resource of course).
```php
<?php
public function myAction()
{
$factory = $this->container->get('sylius.factory.product');
/** @var ProductInterface $product **/
$product = $factory->createNew();
}
```
{% hint style="info" %}
Creating resources via this factory method makes the code more testable, and allows you to change the model class easily.
{% endhint %}
### Manager
The manager service is just an alias to appropriate Doctrines [ObjectManager](https://www.doctrine-project.org/projects/doctrine-persistence/en/latest/reference/index.html#object-manager) and can be accessed via the `sylius.manager.product.id`. API is the same and you are probably already familiar with it:
```php
<?php
public function myAction()
{
$manager = $this->container->get('sylius.manager.product');
// Assuming that the $product1 exists in the database we can perform such operations:
$manager->remove($product1);
// If we have created the $product2 using a factory, we can persist it in the database.
$manager->persist($product2);
// Before performing a flush, the changes we have made, are not saved. There is only the $product1 in the database.
$manager->flush(); // Saves changes in the database.
//After these operations we have only $product2 in the database. The $product1 has been removed.
}
```
### Repository
A repository is defined as a service for every resource and shares the API with the standard Doctrine `ObjectRepository`. It contains two additional methods for creating a new object instance and a paginator provider.
The repository service is available via the `sylius.repository.product.id` and can be used like all the repositories you have seen before.
```php
<?php
public function myAction()
{
$repository = $this->container->get('sylius.repository.product');
$product = $repository->find(4); // Get product with id 4, returns null if not found.
$product = $repository->findOneBy(['slug' => 'my-super-product']); // Get one product by defined criteria.
$products = $repository->findAll(); // Load all the products!
$products = $repository->findBy(['special' => true]); // Find products matching some custom criteria.
}
```
{% hint style="info" %}
An important feature of the repositories are the`add($resource)`and the`remove($resource)`methods, which take a resource as an argument and perform the adding/removing action with a flush inside.
{% endhint %}
These actions can be used when the performance of operations is negligible. If you want to perform operations on large sets of data we recommend using the manager instead.
Every Sylius repository supports paginating resources. To create a [Pagerfanta instance](https://github.com/whiteoctober/Pagerfanta) use the `createPaginator` method:
```php
<?php
public function myAction(Request $request)
{
$repository = $this->container->get('sylius.repository.product');
$products = $repository->createPaginator();
$products->setMaxPerPage(3);
$products->setCurrentPage($request->query->get('page', 1));
// Now you can return products to template and iterate over it to get products from current page.
}
```
Paginator can be created for specific criteria and with desired sorting:
```php
<?php
public function myAction(Request $request)
{
$repository = $this->container->get('sylius.repository.product');
$products = $repository->createPaginator(['foo' => true], ['createdAt' => 'desc']);
$products->setMaxPerPage(3);
$products->setCurrentPage($request->query->get('page', 1));
}
```
### Controller
This service is the most important for every resource and provides a format-agnostic CRUD controller with the following actions:
* `[GET] showAction()` for getting a single resource
* `[GET] indexAction()` for retrieving a collection of resources
* `[GET/POST] createAction()` for creating a new resource
* `[GET/PUT] updateAction()` for updating an existing resource
* `[DELETE] deleteAction()` for removing an existing resource
As you see, these actions match the common operations in any REST API and yes, they are format agnostic. This means all Sylius controllers can serve HTML, JSON, or XML, depending on your request.
Additionally, all these actions are very flexible and allow you to use different templates, forms, and repository methods per route. The bundle is very powerful and allows you to register your own resources as well. Here are some examples to give you some idea of what is possible!
Displaying a resource with a custom template and repository methods:
```yaml
# config/routes.yaml
app_product_show:
path: /products/{slug}
methods: [GET]
defaults:
_controller: sylius.controller.product:showAction
_sylius:
template: AppStoreBundle:Product:show.html.twig # Use a custom template.
repository:
method: findForStore # Use a custom repository method.
arguments: [$slug] # Pass the slug from the url to the repository.
```
Creating a product using a custom form and a redirection method:
```yaml
# config/routes.yaml
app_product_create:
path: /my-stores/{store}/products/new
methods: [GET, POST]
defaults:
_controller: sylius.controller.product:createAction
_sylius:
form: AppStoreBundle/Form/Type/CustomFormType # Use this form type!
template: AppStoreBundle:Product:create.html.twig # Use a custom template.
factory:
method: createForStore # Use a custom factory method to create a product.
arguments: [$store] # Pass the store name from the url.
redirect:
route: app_product_index # Redirect the user to their products.
parameters: [$store]
```
All other methods have the same level of flexibility and are documented in the [SyliusResourceBundle](https://github.com/Sylius/SyliusResourceBundle/blob/master/docs/index.md).

View file

@ -0,0 +1,209 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# State Machine
In Sylius, the default approach to managing frequent changes in the system is through the **Symfony Workflow,** which offers a highly flexible and well-organized solution. However, Sylius also provides the option to use the **Winzou State Machine** if preferred.&#x20;
Both options allow you to define a set of states stored on an entity and manage transitions between them. Additionally, each state machine can be configured with callbacks—events triggered during specific transitions—making it easy to customize how your system responds to changes.
### States
States of a state machine are defined as constants on the model of an entity that the state machine is controlling.
How to configure states? Lets see the example from the **Checkout** state machine.
{% tabs %}
{% tab title="Symfony Workflow" %}
```yaml
# CoreBundle/Resources/config/app/workflow/sylius_order_checkout.yaml
framework:
workflows:
!php/const Sylius\Component\Core\OrderCheckoutTransitions::GRAPH:
type: state_machine
marking_store:
type: method
property: checkoutState
supports:
- Sylius\Component\Core\Model\OrderInterface
initial_marking: !php/const Sylius\Component\Core\OrderCheckoutStates::STATE_CART
places:
- !php/const Sylius\Component\Core\OrderCheckoutStates::STATE_CART
- !php/const Sylius\Component\Core\OrderCheckoutStates::STATE_ADDRESSED
- !php/const Sylius\Component\Core\OrderCheckoutStates::STATE_SHIPPING_SELECTED
- !php/const Sylius\Component\Core\OrderCheckoutStates::STATE_SHIPPING_SKIPPED
- !php/const Sylius\Component\Core\OrderCheckoutStates::STATE_PAYMENT_SELECTED
- !php/const Sylius\Component\Core\OrderCheckoutStates::STATE_PAYMENT_SKIPPED
- !php/const Sylius\Component\Core\OrderCheckoutStates::STATE_COMPLETED
```
{% endtab %}
{% tab title="Winzou State Machine" %}
```yaml
# CoreBundle/Resources/config/app/state_machine/sylius_order_checkout.yml
winzou_state_machine:
sylius_order_checkout:
class: "%sylius.model.order.class%"
property_path: checkoutState
graph: sylius_order_checkout
state_machine_class: "%sylius.state_machine.class%"
states:
cart: ~
addressed: ~
shipping_selected: ~
shipping_skipped: ~
payment_skipped: ~
payment_selected: ~
completed: ~
```
{% endtab %}
{% endtabs %}
### Transitions
On the graph it would be the connection between two states, defining that you can move from one state to another subsequently.
How to configure transitions? Lets see the example of our **Checkout** state machine. Having states configured we can have a transition between the `cart` state to the `addressed` state.
{% tabs %}
{% tab title="Symfony Workflow" %}
```yaml
# CoreBundle/Resources/config/app/workflow/sylius_order_checkout.yaml
framework:
workflows:
!php/const Sylius\Component\Core\OrderCheckoutTransitions::GRAPH:
transitions:
!php/const Sylius\Component\Core\OrderCheckoutTransitions::TRANSITION_ADDRESS:
from:
- !php/const Sylius\Component\Core\OrderCheckoutStates::STATE_CART
- !php/const Sylius\Component\Core\OrderCheckoutStates::STATE_ADDRESSED
- !php/const Sylius\Component\Core\OrderCheckoutStates::STATE_SHIPPING_SELECTED
- !php/const Sylius\Component\Core\OrderCheckoutStates::STATE_SHIPPING_SKIPPED
- !php/const Sylius\Component\Core\OrderCheckoutStates::STATE_PAYMENT_SELECTED
- !php/const Sylius\Component\Core\OrderCheckoutStates::STATE_PAYMENT_SKIPPED
to: !php/const Sylius\Component\Core\OrderCheckoutStates::STATE_ADDRESSED
```
{% endtab %}
{% tab title="Winzou State Machine" %}
```yaml
# CoreBundle/Resources/config/app/state_machine/sylius_order_checkout.yml
winzou_state_machine:
sylius_order_checkout:
transitions:
address:
from: [cart, addressed, shipping_selected, shipping_skipped, payment_selected, payment_skipped] # here you specify which state is the initial
to: addressed
```
{% endtab %}
{% endtabs %}
### Listeners / Callbacks
{% tabs %}
{% tab title="Symfony Workflow" %}
**Listeners** can be used to execute actions in reaction to a given transition in Symfony Workflow.
**How do you configure Listeners attached to events in Symfony Workflow?**&#x20;
You need to create a Listener that will be waiting for the chosen transition and will invoke the desired behaviors.\
\
Below you can see the `ProcessCartListner` configured for the `order_checkout` state machine's transitions.
```php
/** src/Sylius/Bundle/CoreBundle/EventListener/Workflow/OrderCheckout/ProcessCartListener.php **/
<?php
declare(strict_types=1);
namespace Sylius\Bundle\CoreBundle\EventListener\Workflow\OrderCheckout;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Order\Processor\OrderProcessorInterface;
use Symfony\Component\Workflow\Event\CompletedEvent;
use Webmozart\Assert\Assert;
final class ProcessCartListener
{
public function __construct(private OrderProcessorInterface $orderProcessor)
{
}
public function __invoke(CompletedEvent $event): void
{
/** @var OrderInterface $order */
$order = $event->getSubject();
Assert::isInstanceOf($order, OrderInterface::class);
$this->orderProcessor->process($order);
}
}
[...]
```
```xml
<!-- src/Sylius/Bundle/CoreBundle/Resources/config/services/listeners/workflow/order_checkout.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<defaults public="false" />
<service id="Sylius\Bundle\CoreBundle\EventListener\Workflow\OrderCheckout\ProcessCartListener">
<argument type="service" id="sylius.order_processing.order_processor" />
<tag name="kernel.event_listener" event="workflow.sylius_order_checkout.completed.address" priority="-200"/>
<tag name="kernel.event_listener" event="workflow.sylius_order_checkout.completed.select_shipping" priority="-200"/>
<tag name="kernel.event_listener" event="workflow.sylius_order_checkout.completed.skip_shipping" priority="-200"/>
<tag name="kernel.event_listener" event="workflow.sylius_order_checkout.completed.select_payment" priority="-200"/>
<tag name="kernel.event_listener" event="workflow.sylius_order_checkout.completed.skip_payment" priority="-200"/>
</service>
[...]
```
{% endtab %}
{% tab title="Winzou State Machine" %}
**Callbacks** in Winzou State Machine are used to execute some code before or after applying transitions. Winzou StateMachineBundle adds the ability to use Symfony services in the callbacks.
**How do you configure callbacks in Winzou State Machine?**&#x20;
Having a configured transition, you can attach a callback to it before or after. A callback is simply a method of a service you want to be executed.
Below you can see how the `sylius_process_cart` callback is configured on the `sylius_order_checkout` state machine.
```yaml
# CoreBundle/Resources/config/app/state_machine/sylius_order_checkout.yml
winzou_state_machine:
sylius_order_checkout:
callbacks:
# callbacks may be called before or after specified transitions, in the checkout state machine we've got callbacks only after transitions
after:
sylius_process_cart:
on: ["select_shipping", "address", "select_payment", "skip_shipping", "skip_payment"]
do: ["@sylius.order_processing.order_processor", "process"]
args: ["object"]
priority: -200
```
{% endtab %}
{% endtabs %}
### Configuration
In order to use a state machine, you have to define a graph beforehand. A graph is a definition of states, transitions, and optionally callbacks - all attached to an object from your domain. Multiple graphs may be attached to the same object.
In **Sylius** the best example of a state machine is the one from checkout. It has seven states available: `cart`, `addressed`, `shipping_selected`, `shipping_skipped`, `payment_skipped`, `payment_selected` and `completed` - which can be achieved by applying some transitions to the entity. For example, when selecting a shipping method during the shipping step of checkout we should apply the `select_shipping` transition, and after that the state would become `shipping_selected`.
### Learn more
* [Winzou StateMachine Bundle](https://github.com/winzou/StateMachineBundle)
* [Customization Guide: State machines](../../the-customization-guide/customizing-state-machines.md)

View file

@ -0,0 +1,136 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Translations
Sylius uses the approach of personal translations - where each entity is bound with a translation entity, that has its table (instead of keeping all translations in one table for the whole system). This results in the `ProductTranslation` class and `sylius_product_translation` table for the `Product` entity.
The logic of handling translations in Sylius is in the **ResourceBundle**
The fields of an entity that are meant to be translatable are saved on the translation entity, only their getters and setters are also on the original model.
Lets see an example:
Assuming that we would like to have a translatable model of a `Supplier`, we need a Supplier class and a SupplierTranslation class.
```php
<?php
namespace App\Entity;
use Sylius\Component\Resource\Model\AbstractTranslation;
class SupplierTranslation extends AbstractTranslation
{
/**
* @var string
*/
protected $name;
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @param string $name
*/
public function setName($name)
{
$this->name = $name;
}
}
```
The actual entity has access to its translation by using the `TranslatableTrait` which provides the `getTranslation()` method.
{% hint style="warning" %}
Remember that the **Translations collection** of the entity (from the TranslatableTrait) has to be initialized in the constructor!
{% endhint %}
```php
<?php
namespace App\Entity;
use Sylius\Component\Resource\Model\TranslatableInterface;
use Sylius\Component\Resource\Model\TranslatableTrait;
class Supplier implements TranslatableInterface
{
use TranslatableTrait {
__construct as private initializeTranslationsCollection;
}
public function __construct()
{
$this->initializeTranslationsCollection();
}
/**
* @return string
*/
public function getName()
{
return $this->getTranslation()->getName();
}
/**
* @param string $name
*/
public function setName($name)
{
$this->getTranslation()->setName($name);
}
}
```
### Fallback Translations
The `getTranslation()` method gets a translation for the current locale, while we are in the shop, but we can also manually impose the locale - `getTranslation('pl_PL')` will return a Polish translation **if there is a translation in this locale**.
But when the translation for the chosen locale is unavailable, instead the translation for the **fallback locale** (the one that was either set in `config/services.yaml` or using the `setFallbackLocale()` method from the TranslatableTrait on the entity) is used.
### How to add a new translation programmatically?
You can programmatically add a translation to any of the translatable resources in Sylius. Lets see how to do it in the example of a ProductTranslation.
```php
// Find a product to add a translation to it
/** @var ProductInterface $product */
$product = $this->container->get('sylius.repository.product')->findOneBy(['code' => 'radiohead-mug-code']);
// Create a new translation of the product, give it a translated name, and slug in the chosen locale
/** @var ProductTranslation $translation */
$translation = new ProductTranslation();
$translation->setLocale('pl_PL');
$translation->setName('Kubek Radiohead');
$translation->setSlug('kubek-radiohead');
// Add the translation to your product
$product->addTranslation($translation);
// Remember to save the product after adding the translation
$this->container->get('sylius.manager.product')->flush();
```
### Learn more
* [Locales - concept documentation](../configuration/locales.md)\

View file

@ -0,0 +1,2 @@
# Carts & Orders

View file

@ -0,0 +1,106 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Adjustments
**Adjustments** are closely tied to orders in Sylius. They influence the total amount of an order and can be applied at different levels:
* **Order Level**
* **OrderItem Level**
* **OrderItemUnit Level**
### Types of Adjustments
Adjustments can be divided into three main groups:
**Promotion Adjustments**
Applied when promotions or discounts are used
* Example: `Order Promotion Adjustments`, `OrderItem Promotion Adjustments`
**Shipping Adjustments**
Applied to the cost of shipping
* Example: `Shipping Adjustments`, `Shipping Promotion Adjustments`
**Tax Adjustments**
Applied to calculate taxes on orders
* Example: `Tax Adjustments`
#### Positive vs Negative Adjustments
| Positive Adjustments | Negative Adjustments |
| :---------------------------------------------------------------------------: | :----------------------------------------------------------------------------: |
| These are charges that increase the total amount (e.g., shipping fees, taxes) | These are discounts that reduce the total amount (e.g., promotional discounts) |
### Creating an Adjustment Programmatically
Adjustments need to be linked to an order to make sense. Heres how you can create one:
1. **Get the Adjustment Factory**
First, youll need to get the adjustment factory and create a new adjustment instance.
```php
/** @var AdjustmentInterface $adjustment */
$adjustment = $this->container->get('sylius.factory.adjustment')->createNew();
```
2. **Set the Adjustment Type and Amount**
* Set the **type** of the adjustment (available types are found in `AdjustmentInterface`).
* Provide the **amount** (in the base currency).
* Optionally, set whether the adjustment is **neutral** (neutral adjustments dont affect the total like taxes already included in the price).
```php
$adjustment->setType(AdjustmentInterface::ORDER_PROMOTION_ADJUSTMENT);
$adjustment->setAmount(200); // Amount in base currency
$adjustment->setNeutral(false); // Affects the total
$adjustment->setLabel('Test Promotion Adjustment');
```
3. **Add the Adjustment to an Order**
After setting up the adjustment, add it to the relevant order:
```php
$order->addAdjustment($adjustment);
```
4. **Save the Changes**
To apply the changes, update the order in the database:
```php
$this->container->get('sylius.manager.order')->flush();
```
#### Adding Adjustments to Order Items or Item Units
If you want to add adjustments at the **OrderItem** level, make sure the adjustment is attached to the **OrderItem**. If its for an **OrderItemUnit**, apply it at the **OrderItemUnit** level.
{% hint style="info" %}
Adjustments on different levels affect only that specific part of the order.
{% endhint %}
#### Locking an Adjustment
You can lock an adjustment to prevent it from being removed during recalculations. This is useful for scenarios like expired promotions that still need to be applied to the order.
```php
$adjustment->lock();
```
For example, if a promotion is no longer applicable but you still want it to be applied (e.g., an expired coupon), locking the adjustment ensures it remains active.

View file

@ -0,0 +1,66 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Cart flow
Picture this: A user visits your Sylius shop and exclaims, “Someones been using my cart! Its full of items I didnt add!” Lets avoid this surprise by exploring how Sylius handles cart functionality.
In Sylius, the cart represents an **order in progress** that hasnt been placed yet.
{% hint style="info" %}
Each visitor in Sylius has a cart. The cart can be cleared in three ways, by:\
\- placing an order\
\- removing items manually\
\- using a cart-clearing command
{% endhint %}
The cart flow varies depending on whether the user is logged in and whats already in the cart.
#### First scenario:
```gherkin
Given there is a not logged in user
And this user adds a blue T-Shirt to the cart
And there is a customer identified by email "sylius@example.com"
And the "sylius@example.com" customer has a previously created cart with a red Cap in it
When the not logged in user logs in using "sylius@example.com" email
Then the cart created by a not logged in user should be dropped
And the cart previously created by the user identified by "sylius@example.com" should be set as the current one
And the "sylius@example.com" customer's cart should have a red Cap in it
```
#### Second scenario:
```gherkin
Given there is a not logged in user
And this user adds a blue T-Shirt to the cart
And there is a customer identified by email "sylius@example.com" with an empty cart
When the not logged in user logs in using "sylius@example.com" email
Then the cart created by a not logged in user should not be dropped
And the "sylius@example.com" customer's cart should have a blue T-Shirt in it
```
#### Third scenario:
```gherkin
Given there is a customer identified by email "sylius@example.com" with an empty cart
And this user adds a blue T-Shirt to the cart
When the user logs out
And views the cart
Then the cart should be empty
```
{% hint style="info" %}
The cart mentioned in the third scenario will be available once the customer logs in again.
{% endhint %}

View file

@ -0,0 +1,145 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Cart Promotions
The Cart Promotions system in Sylius is highly flexible, combining **promotion rules** and **actions** to create tailored discount programs.
## Promotion Basics
Each cart promotion has:
* A **unique code** and **name**.
* A **usage limit**: the total number of times it can be used.
* A **validity period**: the time frame during which it is active.
* An **exclusivity option**: exclusive promotions prevent other promotions from being applied.
* A **priority**: used to control the order of application, especially for exclusive promotions.
{% hint style="info" %}
Promotion priorities are assigned as numbers. Higher numbers indicate higher priority, so a promotion with a priority `3` will be applied before one with a priority `1`\
\
**Example of Priority Use**: Suppose you have two promotions—one for 10% off the entire order and another for a $5 discount. In this case, you might want to apply the 10% discount first to maximize its impact.
{% endhint %}
## Creating a Promotion Programmatically
To create a promotion, use the promotion factory:
```php
/** @var PromotionInterface $promotion */
$promotion = $this->container->get('sylius.factory.promotion')->createNew();
$promotion->setCode('simple_promotion_1');
$promotion->setName('Simple Promotion');
```
However, a basic promotion needs **Rules** and **Actions** to be functional.
### Promotion Rules
Promotion rules define the conditions that must be met for a promotion to apply. Each rule has a specific **RuleChecker** that checks order details, such as:
* Whether a specific taxon is in the order.
* If the total price of items in a specific taxon meets a threshold.
* Whether the order total reaches a specified amount.
* and more...
**Default Promotion Rule Types in Sylius**
<table data-header-hidden><thead><tr><th width="196"></th><th></th></tr></thead><tbody><tr><td><strong>Cart Quantity</strong></td><td>Checks if the cart has a certain number of items</td></tr><tr><td><strong>Item Total</strong></td><td>Checks if the carts item total meets a specified amount</td></tr><tr><td><strong>Has at least one from taxons</strong></td><td>Ensures the cart includes items from certain taxons</td></tr><tr><td><strong>Total price of items from taxon</strong></td><td>Ensures items from a specific taxon meet a total price threshold</td></tr><tr><td><strong>Nth Order</strong></td><td>Checks if the customer is placing their nth order</td></tr><tr><td><strong>Shipping Country</strong></td><td>Verifies the shipping country matches a specific requirement</td></tr><tr><td><strong>Customer Group</strong></td><td>Ensures the customer belongs to a certain group</td></tr><tr><td><strong>Contains Product</strong></td><td>Checks if a specified product is in the order</td></tr></tbody></table>
**Creating a Promotion Rule Programmatically**
Use the `PromotionRuleFactory` to create and configure rules.
**Example**: To set a rule that requires at least 5 items in the cart:
```php
/** @var PromotionRuleFactoryInterface $ruleFactory */
$ruleFactory = $this->container->get('sylius.factory.promotion_rule');
$quantityRule = $ruleFactory->createCartQuantity('5');
$promotion->addRule($quantityRule);
```
{% hint style="info" %}
Rules define eligibility conditions only. To apply discounts, **actions** are required.
{% endhint %}
### Promotion Actions
Promotion actions define what happens when promotion rules are met. Actions include various types of discounts:
* **Fixed Order Discount**: e.g., $5 off the order total.
* **Percentage Order Discount**: e.g., 10% off the entire order.
* **Fixed Unit Discount**: e.g., $1 off each unit.
* **Percentage Unit Discount**: e.g., 10% off each unit.
* **Shipping Percentage Discount**: e.g., 10% off shipping costs.
{% hint style="info" %}
Actions affect all items in the order by default. To apply discounts to specific items only, use **filters**.
{% endhint %}
**Creating a Promotion Action Programmatically**
Use the `PromotionActionFactory` to create actions. For example, to set a fixed discount of $10:
```php
/** @var PromotionActionFactoryInterface $actionFactory */
$actionFactory = $this->container->get('sylius.factory.promotion_action');
$action = $actionFactory->createFixedDiscount(10);
$promotion->addAction($action);
```
After configuring rules and actions, save the promotion to the repository:
```php
$this->container->get('sylius.repository.promotion')->add($promotion);
```
## Applying Cart Promotions
The **PromotionProcessor** manages the application of cart promotions:
1. Reverts any existing promotions on the order.
2. Checks the eligibility of all available promotions for the order.
3. Applies eligible promotions.
### **Applying a Promotion Manually**
To apply a 10% discount programmatically:
```php
/** @var PromotionInterface $promotion */
$promotion = $this->container->get('sylius.factory.promotion')->createNew();
$promotion->setCode('discount_10%');
$promotion->setName('10% discount');
/** @var PromotionActionFactoryInterface $actionFactory */
$actionFactory = $this->container->get('sylius.factory.promotion_action');
$action = $actionFactory->createPercentageDiscount(10);
$promotion->addAction($action);
$this->container->get('sylius.repository.promotion')->add($promotion);
// Apply the promotion to an order
$this->container->get('sylius.promotion_applicator')->apply($order, $promotion);
```
## Promotion Filters
**Filters** allow actions to target specific groups of products. For example, use a [TaxonFilter](https://github.com/Sylius/Sylius/blob/2.0/src/Sylius/Component/Core/Promotion/Filter/TaxonFilter.php) to apply a promotion only to items within a specific taxon.
{% hint style="info" %}
Check [these scenarios](https://github.com/Sylius/Sylius/blob/2.0/features/promotion/receiving\_discount/receiving\_fixed\_discount\_on\_products\_from\_specific\_taxon.feature) on promotion filters to have a better understanding of them.
{% endhint %}

View file

@ -0,0 +1,6 @@
---
hidden: true
---
# Checkout

View file

@ -0,0 +1,119 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Coupons
Coupons are tightly integrated with Sylius Cart Promotions, allowing promotions to be activated by unique codes. Heres how to create, apply, and generate coupons for promotions.
### Coupon Parameters
Each coupon has the following attributes:
* **Code**: The unique identifier for the coupon.
* **Expiration Date**: The date when the coupon expires.
* **Usage Limit**: The maximum number of times it can be used.
* **Usage Count**: Tracks how many times the coupon has been used.
## Creating a Coupon-Based Promotion
To create a coupon-based promotion, follow these steps:
1. **Create a Promotion**
Begin by creating a new promotion and setting it as **coupon-based**. Only coupon-based promotions can hold multiple coupons.
```php
/** @var PromotionInterface $promotion */
$promotion = $this->container->get('sylius.factory.promotion')->createNew();
$promotion->setCode('free_shipping');
$promotion->setName('Free Shipping');
// Set the promotion's channel
$promotion->addChannel($this->container->get('sylius.repository.channel')->findOneBy(['code' => 'US_Web_Store']));
$promotion->setCouponBased(true);
```
2. **Create a Coupon and Link It to the Promotion**
Next, create a coupon and associate it with your promotion:
```php
/** @var CouponInterface $coupon */
$coupon = $this->container->get('sylius.factory.promotion_coupon')->createNew();
$coupon->setCode('FREESHIPPING');
$promotion->addCoupon($coupon);
```
3. **Add a Promotion Action**
Define what action the promotion should take when applied. For a free shipping promotion, create a **100% shipping discount** action:
```php
/** @var PromotionActionFactoryInterface $actionFactory */
$actionFactory = $this->container->get('sylius.factory.promotion_action');
// Use a float for percentage discounts (1 = 100%, 0.1 = 10%)
$action = $actionFactory->createShippingPercentageDiscount(1);
$promotion->addAction($action);
// Save the promotion to the repository
$this->container->get('sylius.repository.promotion')->add($promotion);
```
### Applying a Coupon to an Order
To apply a promotion coupon we've just created to an order:
1. Ensure the order has shipments (as the above coupon applies a promotion on shipping).
2. Set the promotion coupon on the order (this simulates a customer applying the coupon code at checkout).
3. Process the order with the **OrderProcessor** to apply the promotion.
```php
$order->setPromotionCoupon($coupon);
$this->container->get('sylius.order_processing.order_processor')->process($order);
```
## Generating Multiple Coupons
For larger promotions, manually creating codes is tedious. Sylius offers the **CouponGenerator** service to automatically generate coupon codes in bulk.
1. **Retrieve the Promotion**
First, find the promotion to which you want to add coupons.
```php
$promotion = $this->container->get('sylius.repository.promotion')->findOneBy(['code' => 'simple_promotion']);
```
2. **Configure the Coupon Generator**
Use `PromotionCouponGeneratorInstruction` to specify the number of coupons, code length, expiration date, and usage limit.
```php
/** @var CouponGeneratorInterface $generator */
$generator = $this->container->get('sylius.promotion_coupon_generator');
/** @var PromotionCouponGeneratorInstructionInterface $instruction */
$instruction = new PromotionCouponGeneratorInstruction();
$instruction->setAmount(10); // Generate 10 coupons
$instruction->setPrefix('NEW_YEAR_'); // Optional prefix
$instruction->setSuffix('_SALE'); // Optional suffix
$generator->generate($promotion, $instruction);
```
This example generates 10 coupons with the prefix `NEW_YEAR_` and suffix `_SALE` for the `simple_promotion` promotion.

View file

@ -0,0 +1,6 @@
---
hidden: true
---
# Invoices

View file

@ -0,0 +1,235 @@
---
layout:
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Orders
The **Order** model in Sylius is a key component where many eCommerce concepts converge. An order can represent either an active shopping cart or a placed order.
An **Order** consists of a collection of **OrderItem** instances, each representing a product variant with a chosen quantity from your store.
Each order is:
* **Assigned to the channel** where it was created;
* **Associated with the language** the customer used while placing the order;
* **Created with the base currency** of the current channel by default.
## Creating an Order Programmatically
To create an order programmatically, youll need a factory:
```php
/** @var FactoryInterface $orderFactory */
$orderFactory = $this->container->get('sylius.factory.order');
/** @var OrderInterface $order */
$order = $orderFactory->createNew();
```
Next, youll need to assign a channel to the order. You can retrieve the channel from the context or the repository:
```php
/** @var ChannelInterface $channel */
$channel = $this->container->get('sylius.context.channel')->getChannel();
$order->setChannel($channel);
```
Then, set the locale and currency code:
```php
/** @var string $localeCode */
$localeCode = $this->container->get('sylius.context.locale')->getLocaleCode();
$order->setLocaleCode($localeCode);
$currencyCode = $this->container->get('sylius.context.currency')->getCurrencyCode();
$order->setCurrencyCode($currencyCode);
```
Additionally, the order should have a **Customer** assigned:
```php
/** @var CustomerInterface $customer */
$customer = $this->container->get('sylius.repository.customer')->findOneBy(['email' => 'shop@example.com']);
$order->setCustomer($customer);
```
### Adding Items to an Order
To add **OrderItems** to an order, first retrieve a **ProductVariant** from the repository:
```php
/** @var ProductVariantInterface $variant */
$variant = $this->container->get('sylius.repository.product_variant')->findOneBy([]);
```
Then, create a new **OrderItem**:
```php
/** @var OrderItemInterface $orderItem */
$orderItem = $this->container->get('sylius.factory.order_item')->createNew();
$orderItem->setVariant($variant);
```
Modify the quantity of the item using the **OrderItemQuantityModifier**:
```php
$this->container->get('sylius.order_item_quantity_modifier')->modify($orderItem, 3);
```
Add the item to the order:
```php
$order->addItem($orderItem);
```
Next, process the order using the **CompositeOrderProcessor** to recalculate everything:
```php
$this->container->get('sylius.order_processing.order_processor')->process($order);
```
{% hint style="warning" %}
By default, all **OrderProcessors** only work on orders in the **cart** state. If you need to process orders in different states, you will need to modify the `canBeProcessed` method of the **Order**.
{% endhint %}
This **CompositeOrderProcessor** is one of the most powerful concepts. It handles the whole order calculation logic and allows for really granular operations over the order. It is called multiple times in the checkout process, and internally it works like this:
<figure><img src="../../.gitbook/assets/sylius_order_processor.png" alt=""><figcaption></figcaption></figure>
Finally, save the order using the repository:
```php
/** @var OrderRepositoryInterface $orderRepository */
$orderRepository = $this->container->get('sylius.repository.order');
$orderRepository->add($order);
```
## Order State Machine
An order in Sylius has a state machine with the following states:
* `cart` before checkout is completed, this is the initial state
* `new` when checkout is completed, the cart becomes a new order
* `fulfilled` when both payment and shipping are completed
* `cancelled` when the order is canceled
<figure><img src="../../.gitbook/assets/sylius_order.png" alt=""><figcaption></figcaption></figure>
{% hint style="info" %}
The state machine of order is an obvious extension of the [state machine of checkout](checkout.md).
{% endhint %}
## Shipments of an Order
Each **Order** in Sylius can hold a collection of **Shipments**, with each shipment having its own shipping method and state machine. This allows you to split an order into multiple shipments, each with its shipping process (e.g., sending physical items via a courier and digital products via email).
To learn more about shipments, check the [Shipments Documentation](shipments.md).
### Order's Shipment State Machine
<figure><img src="../../.gitbook/assets/sylius_order_shipping.webp" alt=""><figcaption></figcaption></figure>
### Adding a Shipment to an Order
To add a shipment to an order, first create a shipment and assign a shipping method:
```php
/** @var ShipmentInterface $shipment */
$shipment = $this->container->get('sylius.factory.shipment')->createNew();
$shipment->setMethod($this->container->get('sylius.repository.shipping_method')->findOneBy(['code' => 'UPS']));
$order->addShipment($shipment);
```
Next, process the order using the **OrderProcessor** and save the changes:
```php
$this->container->get('sylius.order_processing.order_processor')->process($order);
$this->container->get('sylius.manager.order')->flush();
```
### Shipping Costs
Shipping costs are stored as **Adjustments**. When a shipment is added to the cart, the order processor assigns a shipping adjustment to the order that holds the cost.
### Shipping a Shipment Using State Machine Transition
To manually trigger shipping transitions, you can apply the following transitions:
```php
$stateMachineFactory = $this->container->get('sm.factory');
$stateMachine = $stateMachineFactory->get($order, OrderShippingTransitions::GRAPH);
$stateMachine->apply(OrderShippingTransitions::TRANSITION_REQUEST_SHIPPING);
$stateMachine->apply(OrderShippingTransitions::TRANSITION_SHIP);
$this->container->get('sylius.manager.order')->flush();
```
After these transitions, the `shippingState` of the order will be `shipped`.
## Payments of an Order
An **Order** in Sylius holds a collection of **Payments**, each with its payment method and state. This allows an order to be paid for using multiple methods, each tracked independently.
### Order's Payment State Machine
<figure><img src="../../.gitbook/assets/sylius_order_payment.png" alt=""><figcaption></figcaption></figure>
### Adding a Payment to an Order
To add a payment to an order, create a payment and assign a payment method:
```php
/** @var PaymentInterface $payment */
$payment = $this->container->get('sylius.factory.payment')->createNew();
$payment->setMethod($this->container->get('sylius.repository.payment_method')->findOneBy(['code' => 'offline']));
$payment->setCurrencyCode($currencyCode);
$order->addPayment($payment);
```
### Completing a Payment Using State Machine Transition
To complete the payment process, apply the necessary transitions:
```php
$stateMachineFactory = $this->container->get('sm.factory');
$stateMachine = $stateMachineFactory->get($order, OrderPaymentTransitions::GRAPH);
$stateMachine->apply(OrderPaymentTransitions::TRANSITION_REQUEST_PAYMENT);
$stateMachine->apply(OrderPaymentTransitions::TRANSITION_PAY);
$this->container->get('sylius.manager.order')->flush();
```
If this is the only payment assigned to the order, the `paymentState` of the order will now be `paid`.
## <mark style="color:blue;">\[Plugin] Creating an Order via Admin Panel</mark>
To create orders from the Admin panel, you can use the [Sylius/AdminOrderCreationPlugin](https://github.com/Sylius/AdminOrderCreationPlugin). This plugin allows administrators to:
* Create orders for customers.
* Choose products, set custom prices, and select payment and shipping methods.
* Reorder previously placed orders.
## <mark style="color:blue;">\[Plugin] Customer Order Operations: Reorder & Cancellation</mark>
Using Sylius plugins, your customers can:
* **Cancel unpaid orders** in the "My Account" section with the [Customer Order Cancellation Plugin](https://github.com/Sylius/CustomerOrderCancellationPlugin).
* **Reorder previously placed orders** with the [Customer Reorder Plugin](https://github.com/Sylius/CustomerReorderPlugin).

View file

@ -0,0 +1,6 @@
---
hidden: true
---
# Payments

View file

@ -0,0 +1,6 @@
---
hidden: true
---
# Refunds

Some files were not shown because too many files have changed in this diff Show more