# Preparing for certificate ## Coding standards - **Software Development Principles:** General software development principles, like clean code and SOLID, constitute a reader-focused development style that produces software that’s easy to write, read, and maintain by different rules. - **PHP Coding Standards:** A collection of rules (for example PSR-2) presented by the PHP Framework Interop Group of established PHP projects with the goal to talk about commonalities between the projects and to make it easier to combine frameworks and libraries. - **Spryker Coding Standards:** This is the Spryker interpretation and implementation of coding styles, conventions, and design patterns. - **Project Standards:** Project coding standards supplement the Spryker coding standards based on the project's need. For example, making some rules more strict than the Spryker default. ## Dealing with Data - **Data Transfer Objects (DTO):** We use Data Transfer Objects, or DTOs, to pass data across the layers and services. - **Entities:** We use entities to persist or request the data transported by DTOs. ### Sample of DTO: ```xml // src/Pyz/Shared/MyModule/Transfer/my_module.transfer.xml <?xml version="1.0"?> <transfers xmlns="spryker:transfer-01" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="spryker:transfer-01 http://static.spryker.com/transfer-01.xsd"> <transfer name="Antelope"> <property name="idAntelope" type="int" /> <property name="name" type="string" /> </transfer> </transfers> ``` the generated PHP Class using the command `docker/sdk console transfer:generate`: `src/Generated/Shared/Transfer/CustomerTransfer.php` we can use the DTO like this: ```php $customerTransfer = new CustomerTransfer(); $customerTransfer->setCompany('Spryker'); $quoteTransfer = new QuoteTransfer(); $quoteTransfer->setCustomer($customerTransfer); echo $quoteTransfer->getCustomer()->getCompany(); // "Spryker" ``` ### Entities: ```xml Src/Pyz/Zed/MyModule/Persistence/Propel/Schema/pyz_customer.schema.xml <?xml version="1.0"?> <database xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="zed" xsi:noNamespaceSchemaLocation="http://static.spryker.com/schema-01.xsd" namespace="Orm\Zed\Antelope\Persistence" package="src.Orm.Zed.Antelope.Persistence"> <table name="pyz_antelope" idMethod="native" allowPkInsert="true" phpName="PyzAntelope"> <column name="id_antelope" required="true" type="INTEGER" primaryKey="true" autoIncrement="true"/> <column name="name" required="true" type="VARCHAR" size="255"/> <unique name="pyz_antelope-name"> <unique-column name="name"/> </unique> <id-method-parameter value="pyz_antelope_pk_seq"/> </table> </database> ``` run `docker/sdk console propel:install` **Note:** This command triggers several other commands, performing the following actions: * Run config convert * Create database * Postgres compatibility * Copy schemas * Run Diff * Build models * Migrate tasks ```php $customer = new SpyCustomer(); $customer->setFirstName('John'); $customer->setLastName('Doe'); $customer->setEmail('john.doe@spryker.com'); $customer->save(); ``` **Note:** - Created by spryker Tables created by Spryker have the spy_ prefix, e.g. spy_customer. When extending an existing Spryker table, keep this naming convention. - Created by you When creating your own table not from a Spryker module, use the pyz_ prefix, e.g. pyz_customer. As a customer, you should only be adding to the pyz part of the project. ## SOLID ### "S" for Single responsibility principle In Spryker, as an example, we make use of splitting business models by action, e.g. FooCreator, FooUpdater, FooRemover, where each class is responsible for a single action. ### "O" for Open-closed principle is a computer programming design principle that states "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification"; that is, such an entity can allow its behavior to be extended without modifying its source code. ### "L" for The Liskov substitution principle (LSP) is a concept in object-oriented programming that states that, in a computer program, if S is a subtype of T, then objects of type T may be replaced with objects of type S ### "I" for The interface segregation principle (ISP) is a concept in computer programming that states that no client should be forced to depend on methods it does not use. ISP splits interfaces that are very large into smaller and more specific ones so that clients will only have to know about the methods that are of interest to them. ### "D" for The dependency inversion principle (DIP) ## Design Paterns ### Facade: used to describe a front-facing interface that hides the complexity of the underlying system. ### Factory: used to create objects, They are simply the place where you instantiate objects. ### Dependency Injection: The dependency injection pattern is a software design pattern that is used to manage dependencies between objects. ## Spryker Application Layers ![](https://i.imgur.com/iNegFGg.png) - Yves (Storefront) - frontend application layer - Zed (Back Office, Backend Gateway API, etc) - backend application layer with all the business logic - Glue - provides an infrastructure for API to connect with multiple touchpoints - Client - an intermediate layer between a front-end and back-end, which provides data access infrastructure to handle all interactions involving data storage and a search engine - Shared - contains code which can be shared among the application layers - Service - represents Spryker's multi-purpose library to be used in all applications ## Some useful commands: `cache:class-resolver:build` There are several types of special resolvable classes that are loaded dynamically at runtime, but cached to speed things up. This command refreshes the cache. `cache:empty-all` Used when you change twig templates, or for emptying caching for the routing in back office, as the routing there is auto-generated, and then cached. `transfer:generate` Used to generate DTOs. `propel:install` Used for executing a collection of commands for generating entities, table structures, etc. `code:sniff:style` `code:sniff:architecture` Used to look for violations of rules defined by Spryker and, potentially, further refined on the project level. ![](https://i.imgur.com/amFyhvY.png) ![](https://i.imgur.com/tEMPHOS.png) - Zed Persistance Layer In the Zed Persistence Layer, you worked towards holding possible criteria for data requests, initializing queries, getting queries from the layers factory, filtering by name, and persisting a record into the database. - Zed Business Layer In the Zed Business Layer, you built logic to pass additional data back from Zed to Yves, separate reading from writing, instantiate the Reader and Writer, and expose the module functionality through a Facade. - Zed Communication Layer Here, you enabled adding records, added a template file in the Presentation layer, and exposed an endpoint from the BackendGateway to Yves. - Client Layer In the Client Layer, you worked towards calling the BackendGateway, injected the ZedRequestClient into the module and injected it in your Stub, and created the actual Client. - Yves Layer When preparing the Yves Layer, you added a template to display a record's data, injected the Client into a module, enabled loading the twig file, and connected the RouteProviderPlugin to the RouterDependencyProvider. ## Example Creating DTO and Entity ```xml // src/Pyz/Shared/Training/Transfer/antelope.transfer.xml <?xml version="1.0"?> <transfers xmlns="spryker:transfer-01" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="spryker:transfer-01 http://static.spryker.com/transfer-01.xsd"> <transfer name="Antelope"> <property name="idAntelope" type="int" /> <property name="name" type="string" /> </transfer> </transfers> ``` ```xml // src/Pyz/Zed/Training/Persistence/Propel/Schema/pyz_antelope.schema.xml <?xml version="1.0"?> <database xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="zed" xsi:noNamespaceSchemaLocation="http://static.spryker.com/schema-01.xsd" namespace="Orm\Zed\Antelope\Persistence" package="src.Orm.Zed.Antelope.Persistence"> <table name="pyz_antelope" idMethod="native" allowPkInsert="true" phpName="PyzAntelope"> <column name="id_antelope" required="true" type="INTEGER" primaryKey="true" autoIncrement="true"/> <column name="name" required="true" type="VARCHAR" size="255"/> <unique name="pyz_antelope-name"> <unique-column name="name"/> </unique> <id-method-parameter value="pyz_antelope_pk_seq"/> </table> </database> ``` ## My summary: Yves <= Client <= Zed Zed: Persistance, Backend, BackendGateway EntityManager, Repository, Business (Reader and Writer), Controller, ControllerGatway Client: Stub (to connect between Yves and Zed through ControllerGatway) Yves: Controller, Router ## Project customization ### Config files - in config files - in config class for each module (optional) example: ```php <?php namespace Pyz\Yves\TrainingPage; use Spryker\Yves\Kernel\AbstractBundleConfig; class TrainingPageConfig extends AbstractBundleConfig { public const COLOR_CONFIG_KEY = 'AntelopeColor'; public function getColor() { return $this->get(self::COLOR_CONFIG_KEY); } } ``` ```php <?php namespace Pyz\Yves\TrainingPage; use Pyz\Client\Training\TrainingClientInterface; use Spryker\Yves\Kernel\AbstractFactory; /** * @method TrainingPageConfig getConfig() */ class TrainingPageFactory extends AbstractFactory { public function getColor() { return $this->getConfig()->getColor(); } } ``` **The config class in the module is optional. If the file exists, it can be found and read in the Factory through a helper function getConfig()** ### Plugins Plugins are declared in the DependencyProvider ### Extending exsiting core modules - Replacement Class (copying code from the core) - Inheritance (extending class in core) - Composition (you implement the same interface and inject the parent in the constructor) # ATOMIC Design 5 atomic design components: atom, molecule, organism, template, and page. Spryker atomic design components follow the FIRST principle of atomic design, which means they are: * Focused * Independent * Reusable * Small * Testable ### ATOM The smallest component of atomic design is called an atom. It’s a basic and fundamental unit used for other components. Atoms usually have a very generic purpose. Examples: button, checkbox, or search input field. ### Molecule Several atoms can grow into larger units—called molecules, which have a specific purpose. Molecules are fundamental units of a compound. They form relatively simple UI components. Examples: logo field, filter in a catalog, menu, or search box with an input field, together with a label, and a button. ### Organism An organism is a combination of atoms, molecules, and even other organisms. They are already complex enough to exist alone and be used directly on a page. Examples: a typical organism is usually 1:1 to a shop section, like a header, footer, or a sidebar. ### Template A template in Atomic Design is basically a generic layout skeleton which determines the structure of atoms, molecules, and organisms. In other words, a template is a data container. When we take a template with all the components included and fill it in with content, we get a page. ### Page According to Frost, a page is the fifth component of the atomic design. However, at Spryker, we don’t have pages by themselves by default. Instead, we have views—specific-purpose containers for components. They act like templates to define the layout in which components are organized. But generally they are here to extend templates. Views are called by controllers. Which brings up the question: why don’t we call them pages? Because at Spryker we need views for page-modules and widgets to support better modularity, project customisation, and decouple backend from frontend. And this is where modular frontend applies. You will learn about it in the next pages. - **Page Modules**: determine the general organization of any page, like product detail or checkout. Page-modules usually contain a minimum of information, and we use them to implement basic functionality. Some page-modules are logically grouped by Spryker to ease implementation of more complex pages, like the Login or Checkout page. - **Widgets**: A Widget is a Spryker extra component that can be used to inject information from an external data source that might be otherwise unavailable. For example, with widget-placeholders you can define where price, product image or rating will be displayed on a page, and what is their behavior. ## To Build assets: ```bash docker/sdk console frontend:yves:build ``` ## To add new theme add it here : `config/Yves/frontend-build-config.json` ## Summary: ### Spryker Atomic Frontend: Spryker Atomic Frontend is based on the Atomic design concept and Modular Frontend. ### Atomic Design Components: Atomic design explains the usage of web components: atoms, molecules, organisms, templates and views (the Spryker interpretation of pages) for better UI functionality and project customization. ### Vendor folder and default theme: In the vendor/spryker-shop/shop-ui, you can locate a default theme of the Spryker shop with all the components: models from which you can create new elements, styles with all the CSS code for styling, and Twig templates. ### Project Customisation At the project level, a very similar collection can be found in the src/Pyz/Yves/ShopUi—this namespace is for all your project customizations. Here, you can also create a folder with Twig files or new theme styles for your shop, such as in the multi-store use case. The folder structure here will be similar to the Spryker core. To customise colors or fonts, you will have to adjust the code in the respective SCSS style file. ### Multi-theme: With Spryker, you can have multiple themes used for any project purpose. OOTB Spryker offers a default theme which includes colors, typography and many more. In your project, you can determine which of your themes should be applied to a particular store. ### ShopUI Module: The Spryker ShopUi module provides the fundamental implementation of UI for every basic module. Everything that affects the whole UI is located in the ShopUi module ### Helpers: In the src/Pyz/Yves/ShopUi/Twig directory you can find Twig helper functions. ### Widgets: Out-of-the-box, Spryker offers a collection of different widgets. Along with these, you can implement your own widgets to make a shopping experience even more complete. You should activate new widgets with the help of the ShopApplicationDependencyProvider. # Middleware Spryker Middleware is a constructor that lets you set up a linear data processing flow, also referred to as a pipeline, to import and export data from some system to a shop or from the shop to some system. The pipeline contains five standard stages: **reader**, **validator**, **mapper**, **translator**, and **writer** Each stage can be abstracted as having the following: - Input. The item is received from the previous stage; an exception might be a reader that receives nothing. - Output. The item is provided for the next stage; an exception might be a writer that persists data and sends back nothing. - Configuration. The configuration of the stage—for example, validation rules for the validator. - Logging. It is set by any stage to leave some artifacts of processing data. # Checkout * Entry step (cart creation) * Customer step * Address step * Shipment step * Payment step * Summary step * Place order step * Success step