/magento2-developer-exam-notes

A collection of notes to cover the topics included in the various Magento 2 developer certification exams. This repository is intended to be a free resource for the Magento community built by it's members.

Magento 2 Developer Certification Exam Notes

A collection of notes for the Magento 2 certified developer exams.

Magento 2.4 GitHub last commit (master)


paypal



📝 Table of Contents


🧐 Tips & Useful Information

The exam includes questions relating to Magento Admin - more than you would expect. It is worth knowing some of the more common features and areas:

  • Marketing & SEO
  • Category management
  • Scopes (Global, Website, Store, and Store View)

The questions are typically structured in two parts. They first gives a bit of background information, usually in the form of "you have been asked to do...", then ask you the question they want answering. Make sure to read the questions carefully as the background information often includes key words that might trip you up and trick you into answering the wrong question.

Quite a few answers are very similar, make sure you are confident in the exact file paths of files.

It may be beneficial to set up a throwaway Magento environment to test some of the things that you revise - such as managing the database using the Declarative Schema; something introduced within Magento 2.3. There were quite a few questions which involved knowledge regarding Data and Schema patches and being aware when to use them.


⛏️ Exam Structure

Associate Developer

Magento Version 2.4.x
Magento Theme Luma
Number of Questions 60
Time Limit 90 Minutes
Passing Grade 68%

✍️ Exam Content

1.0. Magento Architecture & Customisation Techniques

Certification Exam Content
Associate Developer 33%
Professional Developer 18%

1.1. Describe the Magento Module-Based Architecture

What are the significant steps to add a new module?

You need to create the following files:

  • registration.php
  • module.xml
registration.php

This file is included by the Composer autoloader and is added to the static list of components in Magento\Framework\Component\ComponentRegistrar. Example:

<?php
use \Magento\Framework\Component\ComponentRegistrar;

ComponentRegistrar::register(
    ComponentRegistrar::MODULE,        // type
    'YourCompany_YourModule',          // componentName
    __DIR__                            // path
);

Once Magento has found this file, it will then look to find etc/module.xml.

module.xml

A component declares itself (that is, defines its name and existence) in the module.xml file located in the module's etc/ directory. This file specifies the loading sequence for the module and it's setup version (if not using Declarative Schema).

The sequence tells Magento which order to load modules in. This is done in Magento\Framework\Module\ModuleList\Loader.php and only occurs when the module is installed. This sequence is useful for events, plugins, preferences, and layouts.

  • NB: If your module modifies the layout of another and your module is loaded first, the other module will overwrite your modifications.

Example:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="YourCompany_YourModule" setup_version="1.0.0">
        <sequence>
            <module name="TheirCompany_TheirModule" />
            <module name="AnotherCompany_AnotherModule" />
        </sequence>
    </module>
</config>

What are the different Composer package types?

Name Package Type Description
Metapackage metapackage Technically, a Composer package type, not a Magento component type. A metapackage consists of only a composer.json file that specifies a list of components and their dependencies. For example, both Magento Open Source and Magento Commerce are metapackages.
Module magento2-module Code that modifies Magento application behavior. You can upload a single module to the Magento Marketplace or your module can be dependent on some parent package.
Theme magento2-theme Code that modifies the look and feel of the storefront or Magento Admin.
Language Package magento2-language Translations for the storefront or Admin.

When would you place a module in the app/code folder versus another location?

Custom built modules and modules you build to extend other functionality are placed in the app/code/ directory. Other modules, including extensions and the Magento 2 core modules, are placed in the vendor/ directory as they are installed via Composer.


How do different modules interact with each other?

The way modules in Magento 2 interact with each other is by means of dependency injection, Service Contracts or Data Service Contracts. An important aspect of interaction is the scope in which the component is located. In other words, a Magento area. Some benefits of using service contracts is that these contracts ensure a well-defined, durable API that other modules and third-party extensions can implement. Also, these contracts make it easy to configure services as web APIs.


What side effects can come from this interaction?

If modules use Dependency injection, they can load in the wrong order or try to redefine the already redefined functionality of the module. To solve this problem, you should use sequence in module.xml.

If the modules use other modules’ logic and the module, whose logic is used, is disabled, dependencies will not be used and an error will occur when executing the code.


1.2. Describe the Magento Directory Structure

How do you locate different files in Magento?

All of the core Magento files are located in the vendor/magento/ directory with some supporting JavaScript and CSS files being stored in lib/.

Third-party files can be found in their respective vendor/vendor-name/module-name/ directories.

For your customisations:

  • For modules, use app/code.
  • For storefront themes, use app/design/frontend.
  • For Admin themes, use app/design/adminhtml.
  • For language packages, use app/i18n.
/Api: Service Contracts

The /Api directory stores the contracts or interfaces that are exposed to the API. An example of this would be Magento\Catalog\Api\CategoryListInterface.

/Api/Data: Data Service Contracts

This folder contains interfaces that represent data. Examples of this would be a product interface, a category interface, or a customer interface. The concrete implementations of these interfaces usually do little more than provide getters and setters for data.

See Magento\Catalog\Api\Data\ProductInterface for an example.

/Block: View Models

Blocks can be considered as template assistants. Very little functionality or business logic should be done in templates - that is the responsibility of the Block.

/Console: Console Commands

When running bin/magento on the command line, a list of available commands to run is output. The code for commands should be placed inside the /Console directory.

/Controller: Web Request Handlers

This directory stores controller classes for web requests.

/Cron: Cron Job Classes

Definitions for cron jobs are stored here.

/etc: Configuration Files

Any files directly within this directory are applied globally. You can restrict the area these files belong to by placing it in the relevant sub-directory - etc/frontend/, etc/adminhtml/ etc.

  • NB: Some files MUST be placed within a particular area whilst others MUST be global.
/Helper: Aggregated Functionality

Small, reusable snippets of code should be stored in a helper class.

/i18n: Localisation Files

This directory contains the translation CSV files for the module. These CSV files contain two columns, from and to.

/Model: Data Handling & Data Structures

A self-explanatory directory.

/Model/ResourceModel: Database Interactions

The classes stored in this directory dictate how data is stored and retrieved from the database. Any direct database interaction should be done within these files.

See vendor/magento/module-catalog/Model/ResourceModel/Product.php for an example.

/Observer: Event Listeners

When Magento fires an event, certain observers are called - decoupling the system. Magento Commerce integrates with RabbitMQ which allows even more control and reliability to this process. Event data should be able to be stored and then run in a queue at a later time.

Observers MUST implement the Magento\Framework\Event\ObserverInterface. The PHP class should follow the stand of using TitleCase while the event name should be snake_case.

Observers should not contain any business logic. This logic should instead be placed in another class and injected into your observer.

/Plugin

This directory stores your module's plugins. These are covered in more detail in a later section.

/Setup: Database Modification

Stores the following files:

  • InstallSchema.php
    • Sets up table and column schema when the module is installed.
  • UpgradeSchema.php
    • Modifies table and column schema when the module version is upgraded.
  • Recurring.php
    • Runs after every install or upgrade.
  • InstallData.php
    • Sets up data when the module is installed. An example would be adding a custom CMS block.
  • UpgradeData.php
    • Modifies data after the module is installed and when the module version is upgraded.
  • RecurringData.php
    • Applies to data after every install or upgrade.
/Test: Module Tests

This directory stores your module's tests. Tests can be run via the command line using bin/magento dev:tests:run.

/Ui: Data Generation Files
/view/[area]/templates: Block Templates

The counterpart to a Block is a template to render the HTML for the block. Whilst the block (in /Block) represents the business logic, the template represents how the results of the business logic are shown to the user.

/view/[area]/web: Web Assets

Web assets such as images, CSS, JavaScript, LESS, and SCSS are stored in this directory.

view/[area]/web/template: JavaScript Templates

HTML templates that can be requested asynchronously via JavaScript are stored in this directory. These files often contain KnockoutJS declarative bindings.

/view/adminhtml/ui_component: Adminhtml UI Components

This directory contains the XML configuration for UI components. They are used to represent distinct UI elements, such as grids and forms, and are designed to provide flexible user interface rendering. Most Magento Admin grids (such as the Catalog Product grid and the Customer grid) are composed with UI components. The checkout on the frontend is also a UI component.


What are the naming conventions, and how are namespaces established?

The naming of classes and namespaces in Magento 2 conforms to the PSR-4 standard. Each class is located in a separate file and is declared in the namespace corresponding to a pattern of the type: {Vendor}\{Module}\{Path_1}\…\{Path_N}, where each {Path_N} corresponds to a specific folder containing the class file. The class names themselves correspond to the StudlyCaps notation.


How can you identify the files responsible for some functionality?

When searching for certain class files, remember that each class is in a separate file and the class namespace fully corresponds to the directory structure in which the file of this class is located. The configuration file of the di.xml module (etc/di.xml), which contains a list of the various module classes, can help you. To search for block files, you can use layout files from the module’s view/{area}/{layout} directory. You can also use the Template Path Hints tool to search for blocks and their associated template files.

Enable the Template Path Hints in the admin panel by navigating to Stores -> Configuration -> Advanced -> Developer -> Debug.

Controller files are located at the following folders of the module: Controllers/{Controller_Name}/{Action_name}.


1.3. Utilise Configuration and Configuration Variables Scope

Which configuration files are important in the development cycle?

acl.xml

Defines permissions for accessing protected resources.

config.xml

Loads configuration values into Stores > Configuration in the Magento Admin. This file can also encrypt configuration entries.

crontab.xml

Defines cron job scheduling.

di.xml

This file configures dependency injection for your module. It defines plugins, preferences, concrete classes for interfaces, virtual types, and constructor argument modifications.

email_templates.xml
events.xml

This file registers observers.

indexer.xml

This file configures Magento indexers.

module.xml

This file is required by Magento.

mview.xml

Triggers a type of event when data is modified in a database column - most often used for indexing.

view.xml

This file is similar to config.xml but is used to specify the default values for design configuration.

webapi.xml

Configures API access and routes.

widget.xml

Configures widgets to be used in products, CMS blocks, and CMS pages.

[area]/routes.xml

This file tells Magento that this area accepts web requests. The route node configures the first part of the layout handle (route ID) and the front name (first segment in the URL after the domain name).

adminhtml/menu.xml

Configuration for the menu in Magento Admin.

adminhtml/system.xml

Configures tabs, sections, groups, and fields found in Store > Configuration in Magento Admin.


How do you identify the configuration scope for a given variable?

Scope values come from the store, store_group, and store_website tables.

  • The store table specifies store view names and codes
  • The store_website table specifies website names and codes
  • You can also find the code values using the Magento Admin.

How to read the table:

  • Path in Magento Admin column

Values before the comma are paths in the Admin navigation. Values after the comma are options in the right pane.

  • Variable name column is the name of the corresponding environment variable.

You have the option of specifying system values for these configuration parameters as environment variables if you wish.

  • The entire variable name is always ALL CAPS
  • Start a variable name with CONFIG__ (note two underscore characters)
  • You can find the <STORE_VIEW_CODE> or <WEBSITE_CODE> portion of a variable name in either the Magento Admin or the Magento database, as indicated in the following sections.

Find a website or store view scope in the Magento Admin The following table summarizes how to find website or store view value in the Admin.

Description Path in Magento Admin Variable name
Create, edit, delete store views Stores > All Stores CONFIG__STORES__<STORE_VIEW_CODE>__<SYSTEM__VARIABLE__NAME>
Create, edit, delete websites Stores > All Stores CONFIG__WEBSITES__<WEBSITE_CODE>__<SYSTEM__VARIABLE__NAME>

How do native Magento scopes (for example, price or inventory) affect development and decision-making processes?


How can you fetch a system configuration value programmatically?

You can use the functions contained within the Magento\Framework\App\Config\ScopeConfigInterface class, passing the configuration path as the minimum required parameter e.g. web/secure/base_url.


How can you override system configuration values for a given store using XML configuration?

Magento may load our custom system config and merge into the exist nodes. In our custom system config, we should try:

Vendor/ModuleName/etc/adminhtml/system.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
    <system>
        <section id="payment">
            <group id="checkmo">
                <field id="order_status" translate="label" type="select" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1">
                    <label>Custom New Order Status</label> <!-- Custom label -->
                </field>  
            </group>
        </section>
    </system>
</config>

Remember to add overridden module - Magento_OfflinePayments

Vendor/ModuleName/etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Vendor_YourModule" setup_version="1.0.0">
        <sequence>
            <module name="Magento_OfflinePayments"/>
        </sequence>
    </module>
</config>

1.4. Demonstrate How To Use Dependency Injection

How are objects realized in code?

Since dependency injection happens automatically through the constructor, Magento must handle class creation - either at the time of injection or via a factory.

Class Creation During Injection

First the object manager locates the proper class type. If an interface is requested, hopefully an entry in di.xml will provide a concrete class for the interface (if not, an exception will be thrown).

Then the parameters for the constructor are loaded and recursively parsed meaning that the dependencies for the initially requested class are loaded as well as the dependencies of those dependencies as well.

The deploy mode (bin/magento deploy:mode:show) determines which class loader is used:

  • vendor/magento/framework/ObjectManager/Factory/Dynamic/Developer.php
  • vendor/magento/framework/ObjectManager/Factory/Dynamic/Production.php
Class Creation Via Factories

Why is it important to have a centralized object creation process?

Having a centralised process to create objects makes testing much easier. It also provides a simple interface to substitute objects as well as modify existing ones.


How can you override a native class, inject your class into another object, and use other techniques available in di.xml (for example, virtualTypes)?

Overriding Native Classes

preference nodes are used to substitute entire classes through di.xml. They can also be used to specify concrete classes for interfaces:

<preference for="Magento\GoogleTagManager\Block\ListJson"
            type="YourCompany\YourModule\Path\To\Your\Class"
/>
Injecting Your Class into Other Objects

Specify a <type> entry with your class as an <argument> in di.xml:

<type name="Path\To\Your\Class\To\Inject\Into">
    <arguments>
        <argument xsi:type="object">
            Path\To\Your\Injected\Class
        </argument>
    </arguments>
</type>
Virtual Types

A virtual type allows you to create an instance of an existing class that has custom constructor arguments. This is useful in cases where you need a “new” class only because the constructor arguments need to be changed. This is used frequently in Magento to reduce redundant PHP classes.


How would you obtain a class instance from different places in the code?

There are 2 ways to create new instance of objects in Magento 2. One is constructor injection. Second one is using a factory. Using Object manager directly in code should be avoided as much as possible.


1.5. Demonstrate Ability To Use Plugins

How are plugins used in core code? How can they be used for customizations?

A plugin is a class that modifies the behavior of public class functions by intercepting a function call and running code before, after, or around that call. This allows you to customise or extend the behavior of original, public methods for any class or interface.

Before Plugin

Before plugins are used when you want to modify the function input. To modify the input of a function:

public function beforeFunctionName(
    Class\Containing\The\Function $subject,
    $normalFunctionInput1,
    $normalFunctionInput2,
) {
    // ...
    
    return [$normalFunctionInput1, $normalFunctionInput2];
}

The return value determines the array of arguments being passed into the next plugin or targeted function.

After Plugin

After plugins are used when you want to modify the function output. To modify the output of a function:

public function afterFunctionName(
    Class\Containing\The\Function $subject,
    $result
) {
    // ...
    
    return $result;
}

The return value determines the output of the function being passed into the next plugin or targeted function.

Around Plugin

Around plugins give you full control over the function, it's inputs, and it's output. To use an around plugin to replace a function:

public function aroundFunctionName(
    Class\Containing\The\Function $subject,
    callable $proceed
) {
    // ...
    
    $result = $proceed();
    
    // ...
    
    return $result;
    
}
Declaring Plugins

To declare a plugin, add a <type/> to your module's di.xml:

<type name="Class\Containing\The\Function\To\Plug\Into">
    <plugin name="PluginName"
            type="Class\Containing\Your\Plugin"
            disabled="false"
            sortOrder="10"
    />
</type>
Plugin Limitations

Plugins have the following limitations:

  • Only work with public functions
  • Do not work with final classes or functions
  • Do not work with static functions

How do multiple plugins interact?

The sortOrder from the plugins declared in di.xml determines the plugin’s prioritisation when more than one plugin is observing the same method.

The Magento\Framework\Interception\PluginListInterface which is implemented by Magento\Framework\Interception\PluginList\PluginList is responsible to define when to call the before, around, or after methods respecting this prioritisation.

If two or more plugins have the same sortOrder value or do not specify it, the component load order declared in the <sequence> node from module.xml and the area will define the merge sequence. The component load order can be checked in app/etc/config.php.

Magento executes plugins using these rules during each plugin execution in two main flows:

  1. Before the execution of the observed method, starting from lowest to highest sortOrder.

    • Magento executes the current plugin’s before method.
    • Then the current plugin’s around method is called.
      • The first part of the plugin’s around method is executed.
      • The around method executes the callable.
        • If there is another plugin in the chain, all subsequent plugins are wrapped in an independent sequence loop and the execution starts another flow.
        • If the current plugin is the last in the chain, the observed method is executed.
      • The second part of the around method is executed.
    • Magento moves on to the next plugin.
  2. Following the execution flow, starting from lowest to highest sortOrder in the current sequence plugins loop.

    • The current plugin’s after method is executed.
    • Magento moves on to the next plugin.

As a result of these rules, the execution flow of an observed method is affected not only by the prioritisation of the plugins, but also by their implemented methods.

Examples of how this prioritisation is realised can be found in the [Magento 2 dev docs regarding plugins and interceptors])https://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html#examples.


How can the plugin execution order be controlled?

The sortOrder attribute defines the order in which to execute plugins, starting from the lowest and working through to the highest.


What are the limitations of using plugins for customization?

Plugins can not be used on the following:

  • Final methods
  • Final classes
  • Non-public methods
  • Class methods (such as static methods)
  • __construct
  • Virtual types
  • Objects that are instantiated before Magento\Framework\Interception is bootstrapped

In which cases should plugins be avoided?

Plugins are useful to modify the input, output, or execution of an existing method. Plugins are also best to be avoided in situations where an event observer will work. Events work well when the flow of data does not have to be modified.

  1. Interception

4.1. Around-plugins SHOULD only be used when behavior of an original method is supposed to be substituted in certain scenarios.

4.2. Plugins SHOULD NOT be used within own module .

4.3. Plugins SHOULD NOT be added to data objects.

4.4. Plugins MUST be stateless.

...

  1. Events

14.1. All values (including objects) passed to an event MUST NOT be modified in the event observer. Instead, plugins SHOULD BE used for modifying the input or output of a function.

Avoid using around method plugins when they are not required because they increase stack traces and affect performance. The only use case for around method plugins is when the execution of all further plugins and original methods need termination. Use after method plugins if you require arguments for replacing or altering function results.


1.6. Configure Event Observers & Scheduled Jobs

Observers listen for events that are triggered in Magento. Scheduled jobs perform an action at a specified interval.

Observers MUST implement the Magento\Framework\Event\ObserverInterface.


How are observers registered?

Create an <event/> node in your etc/[area]/events.xml file:

<event name="event_for_your_observer_to_listen_for">
    <observer name="observerName"
              instance="Your\Observer\Class"
    />
</event>

How are they scoped for frontend or backend?

Place the events.xml file in the etc/frontend/ and etc/adminhtml/ directories respectively.


How are automatic events created, and how should they be used?

Events should be used when you do not want to change the data. They can be triggered by injecting an instance of Magento\Framework\Event\ManagerInterface into the constructor and calling: $this->eventManager->dispatch('event_name', [params]);.


How are scheduled jobs configured?

To configure a scheduled job you need to assign it a name, specify the function it should execute, the class that function belongs to, and set the schedule using the regular cron schedule notatation. Scheduled jobs are specified in the etc/crontab.xml file:

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
        xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
    <group id="default">
        <job name="cron_job_name"
             instance="Path\To\Your\Class"
             method="execute">
            <schedule>*/5 * * * *</schedule>
        </job>
    </group>
</config>

1.7. Utilise the CLI

Which commands are available?

A full list of commands can be found by running bin/magento. All of the commands listed below can be run from within the magento/ directory via the command line, prefixed with bin/magento.

Usage:
  command [options] [arguments]

Options:
  -h, --help            Display this help message
  -q, --quiet           Do not output any message
  -V, --version         Display this application version
      --ansi            Force ANSI output
      --no-ansi         Disable ANSI output
  -n, --no-interaction  Do not ask any interactive question
  -v|vv|vvv, --verbose  Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Available commands:
  help                                     Displays help for a command
  list                                     Lists commands
 admin
  admin:user:create                        Creates an administrator
  admin:user:unlock                        Unlock Admin Account
 app
  app:config:dump                          Create dump of application
  app:config:import                        Import data from shared configuration files to appropriate data storage
  app:config:status                        Checks if config propagation requires update
 cache
  cache:clean                              Cleans cache type(s)
  cache:disable                            Disables cache type(s)
  cache:enable                             Enables cache type(s)
  cache:flush                              Flushes cache storage used by cache type(s)
  cache:status                             Checks cache status
 catalog
  catalog:images:resize                    Creates resized product images
  catalog:product:attributes:cleanup       Removes unused product attributes.
 config
  config:sensitive:set                     Set sensitive configuration values
  config:set                               Change system configuration
  config:show                              Shows configuration value for given path. If path is not specified, all saved values will be shown
 cron
  cron:install                             Generates and installs crontab for current user
  cron:remove                              Removes tasks from crontab
  cron:run                                 Runs jobs by schedule
 customer
  customer:hash:upgrade                    Upgrade customer's hash according to the latest algorithm
 deploy
  deploy:mode:set                          Set application mode.
  deploy:mode:show                         Displays current application mode.
 dev
  dev:di:info                              Provides information on Dependency Injection configuration for the Command.
  dev:profiler:disable                     Disable the profiler.
  dev:profiler:enable                      Enable the profiler.
  dev:query-log:disable                    Disable DB query logging
  dev:query-log:enable                     Enable DB query logging
  dev:source-theme:deploy                  Collects and publishes source files for theme.
  dev:template-hints:disable               Disable frontend template hints. A cache flush might be required.
  dev:template-hints:enable                Enable frontend template hints. A cache flush might be required.
  dev:tests:run                            Runs tests
  dev:urn-catalog:generate                 Generates the catalog of URNs to *.xsd mappings for the IDE to highlight xml.
  dev:xml:convert                          Converts XML file using XSL style sheets
 encryption
  encryption:payment-data:update           Re-encrypts encrypted credit card data with latest encryption cipher.
 i18n
  i18n:collect-phrases                     Discovers phrases in the codebase
  i18n:pack                                Saves language package
  i18n:uninstall                           Uninstalls language packages
 indexer
  indexer:info                             Shows allowed Indexers
  indexer:reindex                          Reindexes Data
  indexer:reset                            Resets indexer status to invalid
  indexer:set-dimensions-mode              Set Indexer Dimensions Mode
  indexer:set-mode                         Sets index mode type
  indexer:show-dimensions-mode             Shows Indexer Dimension Mode
  indexer:show-mode                        Shows Index Mode
  indexer:status                           Shows status of Indexer
 info
  info:adminuri                            Displays the Magento Admin URI
  info:backups:list                        Prints list of available backup files
  info:currency:list                       Displays the list of available currencies
  info:dependencies:show-framework         Shows number of dependencies on Magento framework
  info:dependencies:show-modules           Shows number of dependencies between modules
  info:dependencies:show-modules-circular  Shows number of circular dependencies between modules
  info:language:list                       Displays the list of available language locales
  info:timezone:list                       Displays the list of available timezones
 maintenance
  maintenance:allow-ips                    Sets maintenance mode exempt IPs
  maintenance:disable                      Disables maintenance mode
  maintenance:enable                       Enables maintenance mode
  maintenance:status                       Displays maintenance mode status
 module
  module:disable                           Disables specified modules
  module:enable                            Enables specified modules
  module:status                            Displays status of modules
  module:uninstall                         Uninstalls modules installed by composer
 queue
  queue:consumers:list                     List of MessageQueue consumers
  queue:consumers:start                    Start MessageQueue consumer
 sampledata
  sampledata:deploy                        Deploy sample data modules for composer-based Magento installations
  sampledata:remove                        Remove all sample data packages from composer.json
  sampledata:reset                         Reset all sample data modules for re-installation
 setup
  setup:backup                             Takes backup of Magento Application code base, media and database
  setup:config:set                         Creates or modifies the deployment configuration
  setup:cron:run                           Runs cron job scheduled for setup application
  setup:db-data:upgrade                    Installs and upgrades data in the DB
  setup:db-declaration:generate-patch      Generate patch and put it in specific folder.
  setup:db-declaration:generate-whitelist  Generate whitelist of tables and columns that are allowed to be edited by declaration installer
  setup:db-schema:upgrade                  Installs and upgrades the DB schema
  setup:db:status                          Checks if DB schema or data requires upgrade
  setup:di:compile                         Generates DI configuration and all missing classes that can be auto-generated
  setup:install                            Installs the Magento application
  setup:performance:generate-fixtures      Generates fixtures
  setup:rollback                           Rolls back Magento Application codebase, media and database
  setup:static-content:deploy              Deploys static view files
  setup:store-config:set                   Installs the store configuration. Deprecated since 2.2.0. Use config:set instead
  setup:uninstall                          Uninstalls the Magento application
  setup:upgrade                            Upgrades the Magento application, DB data, and schema
 store
  store:list                               Displays the list of stores
  store:website:list                       Displays the list of websites
 theme
  theme:uninstall                          Uninstalls theme

How are commands used in the development cycle?

Commands provide a secure method of perfoming tasks that may otherwise be insecure or more time consuming to perform through the Magento Admin. Some of the more commonly used commands during development are listd below:

cache:disable

Disables specific caches. You might use this to disable the layout, block_html, and full_page caches during the development of some frontend templates so Magento always generates the pages you are working on rather than older versions that it has cached. Example:

bin/magento cache:disable layout block_html full_page
cache:flush

Destroys the Magento caches, deleting the cache keys. This can be used to destroy any of the Magento caches in combination. Example:

# destroy all caches
bin/magento cache:flush

# destroy configuration cache
bin/magento cache:flush config
cache:status

Lists the caches and whether they are enabled or disabled. You might use this prior to using the cache:disable or cache:enable commands.

deploy:mode:set

Sets your deploy mode. During development you will likely want to set this to developer whilst on your live server you will want to set this to production. Example:

# developer mode
bin/magento deploy:mode:set developer

# production mode
bin/magento deploy:mode:set production

# default mode
bin/magento deploy:mode:set default
dev:query-log:enable

Enables database query logging.

indexer:reindex

Runs the Magento indexers.

module:disable

Disables a specified module. Example:

bin/magento module:disable Module_Name
module:enable

Enables a specified module. Example:

bin/magento module:enable Module_Name
module:status

List all modules and whether they are enabled or disabled.

setup:db:status

Checks whether the Magento database needs to be upgraded.

setup:upgrade

Synchronises module versions in the database with those defined in the codebase.

1.8 Describe how extensions are installed and configured

How would you install and verify an extension by a customer’s request?

We recommend working in a development branch when adding an extension to your implementation. If you do not have a branch, see the Get started creating branches topic. When installing an extension, the extension name (_) is automatically inserted in the app/etc/config.php file. There is no need to edit the file directly.

To install an extension:

  • On your local workstation, change to the Cloud project root directory.

  • Create or checkout a development branch. See branching.

  • Using the Composer name and version, add the extension to the require section of the composer.json file.

composer require <extension-name>:<version> --no-update

For example:

composer require pixlee/magento2:1.0.1 --no-update

  • Update the project dependencies.

composer update

  • Add, commit, and push code changes.
git add -A
git commit -m "Install <extension-name>"
git push origin <branch-name>

When installing an extension, you must include the composer.lock file when you push code changes to the remote environment. The composer install command reads the composer.lock file to enable the defined dependencies in the remote environment.

After the build and deploy finishes, use a SSH to log in to the remote environment and verify the extension installed.

bin/magento module:status <extension-name>

An extension name uses the format: _.

Sample response:

Module is enabled


2.0 Request Flow Processing

Certification Exam Content
Associate Developer 7%
Professional Developer 12%

2.1. Magento 2 Modes & Application Initialisation

Understand the pros and cons of using developer mode or production mode.

Production

This mode should be used on your live production server. Production mode leads to an increase in performance by providing all necessary static files at the time of deployment rather than requiring Magento to dynamically locate and create static files during run time.

In this mode Magento:

  • Logs exceptions and does not show exceptions on the frontend
  • Serves static view files from the cache only
  • Prevents automatic code compilation meaning that new or updated files are not written to the file system
  • Prevents you from enabling or disabled cache types via Magento Admin
Developer

As it's name suggests, this mode is intended to be used during development only. When in this mode, Magento:

  • Disables static view file caching instead writing them to pub/static every time they are called
  • Provides verbose logging in var/report
  • Enables automatic code compilation
  • Displays uncaught exceptions to the frontend
  • Enables enhanced debugging
  • Shows custom x-magento-* HTTP request and response headers
  • Performs slower

When do you use default mode?

As its name implies, default mode is how Magento operates if no other mode is specified. It enables you to deploy the Magento application on a single server without changing any settings. However, default mode is not as optimized for production.

To deploy the Magento application on more than one server or to optimize it for production, change to one of the other modes.

In default mode:

  • Errors are logged to the file reports at server, and never shown to a user
  • Static view files are cached
  • Not optimized for a production environment, primarily because of the adverse performance impact of static files being dynamically generated rather than materialized. In other words, creating static files and caching them has a greater performance impact than generating them using the static files creation tool.

How do you enable/disable maintenance mode?

Maintenance mode can be enabled and disabled via the command line:

# enable maintenance mode
bin/magento maintenance:enable

# disable maintenance mode
bin/magento maintenance:disable

Identify the steps for application initialisation.


How would you design a customization that should act on every request and capture output data regardless of the controller?


2.2. Demonstrate Ability To Use Frontend Controllers

Describe front controller responsibilities.


In which situations will the front controller be involved in execution, and how can it be used in the scope of customizations?


2.3. URL Processing

URL rewrites provide a user-friendly URL to the customer in place of a cumbersome Magento URL. These values are stored in the url_rewrite table.


How is the user-friendly URL of a product or category defined?

The product/category url_key attribute defines their URL. For each category a product belongs to, Magento will generate a URL based on the category tree before appending the product's url_key.


How can you change a URL?

You can change a URL by creating a URL rewrite. The following actions also cause a URL to change:

  • Updating a category's url_key attribute
  • Updating a product's url_key attribute
  • Modifying the categories a product belongs to

How do you determine which page corresponds to a given user-friendly URL?

In the url_rewrite table you will find a row where the request_path value is the user-friendly URL. The corresponding target_path value is the internal Magento page. The Magento_UrlRewrite module contains a router that checks to see whether the given URL can be matched to a request_path in the url_rewrite table, redirecting to the target_path if a match is found.


How do you identify which module/controller corresponds to a given URL?

https://your-store.com/catalog/product/view/id/42


What would you do to create a given URL?

Set the Category and Product url_key attributes. You can also create URL rewrites through the Magento Admin path Marketing > SEO & Search > URL Rewrites


Describe how action controllers and results function.


How do controllers interact with each other?


How are different response types generated?


3.0. Customising The Magento UI

Certification Exam Content
Associate Developer 15%
Professional Developer 10%

3.1. Customise The Magento UI Using Themes

When would you create a new theme?

You would create a new theme when making design changes to the Magento frontend or admin. This typically involves copying and modifying layout files, templates, and styles to achieve your desired design.


How do you define theme hierarchy for a project?

The theme.xml file can be used to specify the theme's parent using the <parent /> node:

<theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="urn:magento:framework:Config/etc/theme.xsd">
    <title>Your Theme Name</title>
	<parent>Vendor/Theme</parent>
</theme>

Omitting the <parent /> node dictates that the theme is the base, or default, theme.


3.2. Blocks & Templates

How do you assign a template to a block?

To assign a template to a block:

<block class="Namespace\Of\Your\Class"
       name="blockName"
       template="Module_Name::path/to/your/template.phtml"
/>

NB: The path/to/your/template.phtml starts from the templates/ directory.


How do you assign a different template to a native block?

To assign a template to an existing block, pass an argument to the block:

<referenceBlock name="blockName">
    <action method="setTemplate">
        <argument name="template" xsi:type="string">
            Module_Name::path/to/your/template.phtml
        <argument>
    </action>
</referenceBlock>

3.3. Identify the uses of different types of blocks

When would you use non-template block types?

Block Type Path Use
Text vendor/magento/framework/View/Element/Text.php Printing a string
ListText vendor/magento/framework/View/Element/Text/ListTest.php Output each of the child blocks

3.4. Magento Layout XML

How do you use layout XML directives in your customizations?

Layout XML is what links templates to blocks and there are a number of directives available for use.

<block />

Defines a block. A block is a unit of page output that renders some distinctive content (anything visually tangible for the end-user), such as a piece of information or a user interface element. Blocks are a foundational building unit for layouts in Magento. They are the link between a PHP block class (which contains logic) and a template (which renders content). Blocks can have children and grandchildren (and so on).

Attribute Description Values Required
class Name of a class that implements rendering of a particular block. An object of this class is responsible for actual rendering of block output. Class name No
name Name that can be used to address the block to which this attribute is assigned. The name must be unique per generated page. If not specified, an automatic name will be assigned in the format ANONYMOUS_n. 0-9, A-Z, a-z, underscore (_), period (.), dash (-). Should start with a letter. Case-sensitive. No
before Used to position the block before an element under the same parent. The element name or alias name is specified in the value. Use dash (-) to position the block before all other elements of its level of nesting. Element name or dash (-). No
after Used to position the block after an element under the same parent. The element name or alias name is specified in the value. Use dash (-) to position the block after all other elements of its level of nesting. Element name or dash (-). No
template A template that represents the functionality of the block to which this attribute is assigned. Template file name No
as An alias name that serves as identifier in the scope of the parent element. Same as name No
cachable Defines whether a block element is cacheable. This can be used for development purposes and to make needed elements of the page dynamic. true or false No
@TODO: <block /> example
<container />

A structure without content that holds other layout elements such as blocks and containers. A container renders child elements during view output generation. It can be empty or it can contain an arbitrary set of <container> and <block> elements. If the <container> is empty, and there is no child <block> available, it will not be displayed in the frontend source code.

Attribute Description Values Required
name Name that can be used to address the block to which this attribute is assigned. The name must be unique per generated page. If not specified, an automatic name will be assigned in the format ANONYMOUS_n. 0-9, A-Z, a-z, underscore (_), period (.), dash (-). Should start with a letter. Case-sensitive. No
label An arbitrary name to display in the web browser. Any No
before Used to position the block before an element under the same parent. The element name or alias name is specified in the value. Use dash (-) to position the block before all other elements of its level of nesting. Element name or dash (-). No
after Used to position the block after an element under the same parent. The element name or alias name is specified in the value. Use dash (-) to position the block after all other elements of its level of nesting. Element name or dash (-). No
as An alias name that serves as identifier in the scope of the parent element. Same as name No
output Defines whether to output the root element. If specified, the element will be added to output list. If not specified, the parent element is responsible for rendering its children. Any value except the obsolete toHtml. Recommended value is 1. No
htmlTag Output parameter. If specified, the output is wrapped into specified HTML tag. Any valid HTML5 tag No
htmlID Output parameter. If specified, the value is added to the wrapper element. If there is no wrapper element, this attribute has no effect. Any valid HTML5 id value No
htmlClass Output parameter. If specified, the value is added to the wrapper element. If there is no wrapper element, this attribute has no effect. Any valid HTML5 class value No
@TODO: <container /> example
<referenceBlock /> and <referenceContainer />

Updates in <referenceBlock> and <referenceContainer> are applied to the corresponding <block> or <container>. For example, if you make a reference by <referenceBlock name="right">, you are targeting the block <block name="right">.

Attribute Description Values Required
remove Allows you to remove or cancel the removal of the element. When a container is removed, its child elements are removed as well. true or false No
display Allows you to disable rendering of specific block or container with all its children (both set directly and by reference). The block’s/container’s and its children’ respective PHP objects are still generated and available for manipulation. true or false No

The remove attribute is optional and its default value is false This implementation allows you to remove a block or container in your layout by setting the remove attribute value to true, or to cancel the removal of a block or container by setting the value to false.

<referenceBlock name="blockName" remove="true" />

The display attribute is optional and its default value is true. You are always able to overwrite this value in your layout. In situation when the remove value is true, the display attribute is ignored.

<referenceContainer name="containerName" display="false" />
<arguments />

<arguments> is a required container for <argument>. It does not have its own attributes.

<arguments>
    ...
</arguments>
<argument />

Information can be passed from layout XML files to blocks using the <argument /> node. These directives must always be enclosed within <arguments /> directives. Argument values set in a layout file are added to the block's data array and can be accessed in templates using the getData('argumentName') and hasData('argumentName') functions. The latter returns a boolean defining whether there’s any value set.

Attribute Description Values Required
name Argument name. Must be unique. Yes
xsi:type Argument type. string / boolean / object / number / null / array / options / url / helper Yes
translate true or false No
<arguments>
    <!-- String -->
    <argument name="stringArgName" xsi:type="string">
        Some String
    </argument>
    
    <!-- Boolean -->
    <argument name="booleanArgName" xsi:type="boolean">
        true
    </argument>
    
    <!-- Object -->
    <argument name="objectArgName" xsi:type="object">
        <!-- Must implement `Magento\Framework\View\Element\Block\ArgumentInterface` -->
        Namespace\To\Your\Class
    </argument>
    
    <!-- Number -->
    <argument name="numberArgName" xsi:type="number">
        42
    </argument>
    
    <!-- Null -->
    <argument name="nullArgName" xsi:type="null" />
    
    <!-- Array -->
    <argument name="arrayArgName" xsi:type="array">
        <item name="arrayKeyOne" xsi:type="string">First Item</item>
        <item name="arrayKeyTwo" xsi:type="object">Namespace\Of\Your\Class</item>
        ...
    </argument>
    
    <!-- Options -->
    <argument name="optionsArgName" xsi:type="options">
        <!-- Must implement `Magento\Framework\Data\OptionSourceInterface` -->
        Namespace\Of\Your\Class
    </argument>
    
    <!-- URL -->
    <argument name="urlArgName"
              xsi:type="url"
              path="your/url/path"
    />
    
    <!-- Helper -->
    <argument name="helperArgName" 
              xsi:type="string"
              helper="Namespace\To\Your\Helper\Class::helperFunction">
        <param name="paramName">paramValue</param>
    </argument>
<arguments>

NB: The helper can only use public functions.

<move />

Sets the declared block or container element as a child of another element in the specified order.

Attribute Description Values Required
element Name of the element to move. Element name Yes
destination Name of the target parent element. Element name Yes
as Alias name for the element in the new location. 0-9, A-Z, a-z, underscore (_), period (.), dash (-). Case-sensitive. No
after or before Specifies the element’s position relative to siblings. Use dash (-) to position the block before or after all other siblings of its level of nesting. If the attribute is omitted, the element is placed after all siblings. Element name No
<move element="elementName"
      destination="parentElementName"
      as="newAlias"
      after="siblingElementName"
      before="anotherSiblingElementName"
/>

NB:

  • <move> is skipped if the element to be moved is not defined.
  • If the as attribute is not defined, the current value of the element alias is used. If that is not possible, the value of the name attribute is used instead.
  • During layout generation, the <move> instruction is processed before the removal (set using the remove attribute). This means if any elements are moved to the element scheduled for removal, they will be removed as well.
<remove />

<remove> is used only to remove the static resources linked in a page <head> section. For removing blocks or containers, use the remove attribute for <referenceBlock> and <referenceContainer>.

<!-- Remove local resources -->
<remove src="css/styles-m.css" />
<remove src="my-js.js"/>
<remove src="Magento_Catalog::js/compare.js" />

<!-- Remove external resources -->
<remove src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css"/>
<remove src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"/>
<remove src="http://fonts.googleapis.com/css?family=Montserrat" />
<update />

Includes a certain layout file.

<update handle="{handleNameToInclude}" />

How do you register a new layout file?

If the new page has a 3-columns-double-footer layout, create a custom page-layout XML file: app/design/frontend/<VendorName>/<ThemeName>/Magento_Theme/page_layout/3-columns-double-footer.xml.

<?xml version="1.0"?>
<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_layout.xsd">
    <update handle="3columns"/>
    <referenceContainer name="page.wrapper">
        <container name="footer-bottom" as="footer-bottom" after="footer" label="Footer Bottom" htmlTag="footer" htmlClass="page-footer-bottom">
            <container name="footer-bottom-content" as="footer-bottom-content" htmlTag="div" htmlClass="footer content">
                <block class="Magento\Framework\View\Element\Template" name="report.bugs.bottom" template="Magento_Theme::html/bugreport.phtml"/>
            </container>
        </container>
    </referenceContainer>
</layout>

Add the newly created page layout to the layouts.xml file of the theme directory: app/design/frontend/<VendorName>/<ThemeName>/Magento_Theme/layouts.xml.

<?xml version="1.0" encoding="UTF-8"?>
<page_layouts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/PageLayout/etc/layouts.xsd">
    <layout id="3-columns-double-footer">
        <label translate="true">3 Columns Double Footer</label>
    </layout>
</page_layouts>

Clean the cache by going to System > Cache Management > Flush Magento Cache or bin/magento cache:clean


How do you pass variables from layout to block?

Information can be passed from layout XML files to blocks using the <argument /> node. These directives must always be enclosed within <arguments /> directives. Argument values set in a layout file are added to the block's data array and can be accessed in templates using the getData('argumentName') and hasData('argumentName') functions. The latter returns a boolean defining whether there’s any value set.

Attribute Description Values Required
name Argument name. Must be unique. Yes
xsi:type Argument type. string / boolean / object / number / null / array / options / url / helper Yes
translate true or false No
<arguments>
    <!-- String -->
    <argument name="stringArgName" xsi:type="string">
        Some String
    </argument>
    
    <!-- Boolean -->
    <argument name="booleanArgName" xsi:type="boolean">
        true
    </argument>
    
    <!-- Object -->
    <argument name="objectArgName" xsi:type="object">
        <!-- Must implement `Magento\Framework\View\Element\Block\ArgumentInterface` -->
        Namespace\To\Your\Class
    </argument>
    
    <!-- Number -->
    <argument name="numberArgName" xsi:type="number">
        42
    </argument>
    
    <!-- Null -->
    <argument name="nullArgName" xsi:type="null" />
    
    <!-- Array -->
    <argument name="arrayArgName" xsi:type="array">
        <item name="arrayKeyOne" xsi:type="string">First Item</item>
        <item name="arrayKeyTwo" xsi:type="object">Namespace\Of\Your\Class</item>
        ...
    </argument>
    
    <!-- Options -->
    <argument name="optionsArgName" xsi:type="options">
        <!-- Must implement `Magento\Framework\Data\OptionSourceInterface` -->
        Namespace\Of\Your\Class
    </argument>
    
    <!-- URL -->
    <argument name="urlArgName"
              xsi:type="url"
              path="your/url/path"
    />
    
    <!-- Helper -->
    <argument name="helperArgName" 
              xsi:type="string"
              helper="Namespace\To\Your\Helper\Class::helperFunction">
        <param name="paramName">paramValue</param>
    </argument>
<arguments>

NB: The helper can only use public functions.


3.5. Create and add code and markup to a given page

How do you add new content to existing pages using layout XML?


4.0. Working With Databases In Magento

Certification Exam Content
Associate Developer 18%
Professional Developer 7%

4.1. Models, Resource Models, And Collections

What are the responsibilities of each of the ORM object types?

The Magento ORM elements are:

  • Models: Define entities, their data, and their behaviour.
  • Resource Models: Data mappers for storage structures.
  • Collections: Stores sets of Models and related functionality including filtering, sorting, and pagination.
  • Resources: Maintain database connections through adapters.

How do they relate to one another?

  • Models are like a black box which provides a layer of abstraction on top of the resource models. The fetching, extraction, and manipulation of data occur through models. As a rule of thumb, every entity we create (i.e. every table we create in our database) should have its own model class. Every model extends the Magento\Framework\Model\AbstractModelclass, which inherits the \Magento\Framework\DataObjectclass, hence, we can call the setData() and getData() functions on our model, to get or set the data of a model respectively.
  • All of the actual database operations are executed by the resource model. Every model must have a resource model, since all of the methods of a resource model expects a model as its first parameter. All resource models must extend the Magento\Framework\Model\ResourceModel\Db\AbstractDbclass.
  • Collections are used when we want to fetch multiple rows from our table. Meaning collections are a group of models.

4.2 how entity load and save occurs

How do you use the native Magento save/load process in the development process?

  • Load: First calls beforeLoad() which can be used for plugin. Creates connection to database and loads a select query using parameters to fetch the row and set the data. Then calls afterLoad() method for plugins and object is returned.

  • Save: If object is deleted then it deletes it. If object is not modified then it is committed and method is returned. Checks for validation before save then beforeSave() is called. If object can be saved then it is saved and afterSave is called and event is dispatched.

You can use native Magento load/save to do basic get/set and customize it with plugins.


4.3 Describe how to filter, sort, and specify the selected values for collections and repositories.

Collections
  • Filter: $collection->addFieldToFilter()
  • Sort: $collection->addOrder()
  • Select Column: $collection->addFieldToSelect()
  • Pagination: $collection->setPageSize() and $collection->setCurPage()
Repositories

Repositories give service requestors the ability to perform create, read, update, and delete (CRUD) operations on entities or a list of entities. A repository is an example of a service contract, and its implementation is part of the domain layer.

A repository should be stateless after instantiation. This means that every method call should not rely on previous calls nor should it affect later method calls. Any field contained in the repository class must also be stateless.

If your repository needs to provide functionality that requires state, such as for caching, use the registry pattern. A good example that uses this pattern is the CustomerRepository class.

  • Search Criteria A Search Criteria is an implementation of the SearchCriteriaInterface class that allows you to build custom requests with different conditions.

Repositories use this class to retrieve entities based on a matching criteria.

  • Filter The Filter class is the smallest part of a Search Criteria. It allows you to add a custom field, value, and condition type to the criteria.

Example of how to define a Filter:

$filter
    ->setField("url")
    ->setValue("%magento.com")
    ->setConditionType("like");

This filter will find all urls with the suffix of “magento.com”.

  • Filter Group

The FilterGroup class acts like a collection of Filters that apply one or more criteria to a search.

The boolean OR statement joins Filters inside a single Filter Group. The boolean AND statement joins Filter Groups inside a Search Criteria.

For example:

$filter1
    ->setField("url")
    ->setValue("%magento.com")
    ->setConditionType("like");

$filter2
    ->setField("store_id")
    ->setValue("1")
    ->setConditionType("eq");

$filterGroup1->setFilters([$filter1, $filter2]);

$filter3
    ->setField("url_type")
    ->setValue(1)
    ->setConditionType("eq");

$filterGroup2->setFilters([$filter3]);

$searchCriteria->setFilterGroups([$filterGroup1, $filterGroup2]);

The code above creates a Search Criteria with the Filters put together in the following way: (url like %magento.com OR store_id eq 1) AND (url_type eq 1)

  • Sorting

To apply sorting to the Search Criteria, use the SortOrder class.

Field and direction make up the two parameters that define a Sort Order object. The field is the name of the field to sort. The direction is the method of sorting whose value can be ASC or DESC.

The example below defines a Sort Order object that will sort the customer email in ascending order:

$sortOrder
    ->setField("email")
    ->setDirection("ASC");

$searchCriteria->setSortOrders([$sortOrder]);
  • Pagination The setPageSize function paginates the Search Criteria by limiting the amount of entities it retrieves:
$searchCriteria->setPageSize(20); //retrieve 20 or less entities

The setCurrentPage function sets the current page:

$searchCriteria
    ->setPageSize(20)
    ->setCurrentPage(2); //show the 21st to 40th entity

https://devdocs.magento.com/guides/v2.2/extension-dev-guide/searching-with-repositories.html


How do you select a subset of records from the database?

For getList method, a SearchCriteria object with set parameters has to be passed in the method.

  • Search Criteria: A SearchCriteria object contains smaller objects such as filters and filter groups.
    • Filter: Filter class is the smallest object of SearchCriteria object and allows you to filter searches with set fields, values and conditions.
    • Filter Group: Like a filter but allows you to apply multiple filters to a search. OR statements join filters in a single filter group. AND statements join filter groups inside the search criteria object.
    • Sort Order: Sorts the results returned from search criteria and takes in field parameter (e.g. email) and direction parameter (e.g. ASC).

4.4. Declarative Schema

Declarative schema in Magento 2.3 allows developers to declare the final desired state of the database and has the system adjust to it automatically, without performing redundant operations. Developers are no longer forced to write scripts for each new version. Additionally, this approach allows data be deleted when a module is uninstalled - something that previously had to be done separately.

Terminology

Data Patch

  • A class that contains data modification instructions. It can have dependencies on other data or schema patches.
  • Some data patches can be reverted as a module or patch is uninstalled or deleted. Revertable operations are Data Query Language (DQL) and Data Manipulation Language (DML) operations: INSERT, UPDATE.

Schema Patch

  • A class that contains custom schema modification instructions. Schema patches are used along with declarative schema, but these patches allow complex operations such as:
    • Adding triggers, stored procedures, or functions
    • Performing data migration with inside DDL operations
    • Renaming tables, columns, and other entities
    • Adding partitions and options to a table

How do you add a column using declarative schema?

You can create/modify the etc/db_schema.xml file, specifying a <table /> node for the table you are editing and adding a <column /> node inside to create the new column.

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="table_name">
        <column xsi:type="varchar"
                name="title"
                padding="10"
                comment="Page Title"
        />
    </table>
</schema>

You can also create a schema patch file in the YourCompany\YourModule\Setup\Patch\Schema namespace:

<?php
namespace YourCompany\YourModule\Setup\Patch\Schema;

use Magento\Framework\DB\Ddl\Table;
use Magento\Framework\Setup\Patch\SchemaPatchInterface;
use Magento\Framework\Setup\SchemaSetupInterface;

class YourSchemaPatch implements SchemaPatchInterface
{
    /** @var SchemaSetupInterface */
    private $moduleSchemaSetup;

    /**
     * YourSchemaPatch Constructor.
     *
     * @param SchemaSetupInterface $moduleSchemaSetup
     */
    public function __construct(SchemaSetupInterface $moduleSchemaSetup)
    {
        $this->moduleSchemaSetup = $moduleSchemaSetup;
    }

    /**
     * {@inheritdoc}
     */
    public function apply()
    {
        $this->schemaSetup->startSetup();
        $table = $this->schemaSetup->getTable('your_table_name');
        $connection = $this->schemaSetup->getConnection();
        
        if ($connection->isTableExists($table)) {
            // declare new columns to add
            $newColumns = [
                'shiny_new_column' => [
                    'type' => Table::TYPE_TEXT,
                    'nullable' => true,
                    'comment' => 'Shiny New Column',
                ],
                'another_shiny_column' => [
                    'type' => Table::TYPE_TEXT,
                    'nullable' => true,
                    'comment' => 'OMG More Shinies! :O',
                ],
            ];

            foreach ($newColumns as $newColumn => $columnDescription) {
                $connection->addColumn($table, $newColumn, $columnDescription);
            }
        }

        $this->schemaSetup->endSetup();
    }

    /**
     * {@inheritDoc}
     */
    public static function getDependencies()
    {
        // return [dependencies]
    }
    
    /**
     * {@inheritDoc}
     */
    public function getAliases()
    {
        // return [aliases]
    }
}

NB: When adding new columns to a table, you also need to generate the db_schema_whitelist.json file.


How do you modify a table added by another module?

To modify a table added by another module, create Your_Company/Your_Module/etc/db_schema.xml and specify the table name in the <table /> node:

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="table_create_by_other_module">
        ...
    </table>
</schema>

How do you delete a column?

To remove a column from a table created by your module you can simply remove the corresponding <column /> node in Your_Company/Your_Module/etc/db_schema.xml. To drop a column declared in another module, you must redeclare it and set the disabled attribute to true:

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="table_create_by_other_module">
        ...
        <column xsi:type="int"
                name="new_id"
                padding="10"
                unsigned="true"
                nullable="false"
                comment="New ID"
                disabled="true"
        />
        ...
    </table>
</schema>

How do you add an index or foreign key using declarative schema?

Index

To add an index, declare an <index /> node in Your_Company/Your_Module/etc/db_schema.xml:

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="table_create_by_other_module">
        ...
        <index referenceId="INDEX_NAME" indexType="btree">
            <column name="column_name" />
        </index>
        ...
    </table>
</schema>
Foreign Key

To add a foreign key, declare a <constraint /> node with an xsi:type of foreign in Your_Company/Your_Module/etc/db_schema.xml:

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="table_create_by_other_module">
        ...
        <constraint xsi:type="foreign"
                    referenceId="YOUR_REFERENCE_ID"
                    
                    <!-- The current table -->
                    table="table_name"
                    
                    <!-- The column in the current table that refers to a column in another table -->
                    column="column_name"
                    
                    <!-- The table being referenced -->
                    referenceTable=""
                    
                    <!-- The column being referenced -->
                    referenceColumn=""
                    
                    <!-- Foreign key trigger (CASCADE/SET/NULL/NO ACTION) -->
                    onDelete="CASCADE"
        />
        ...
    </table>
</schema>

How do you manipulate data using data patches?


What is the purpose of schema patches?

Schema patches are used to make custom database schema modifications:

  • Renaming tables
  • Adding/removing columns
  • Setting primary & foreign keys

5.0. Developing With Adminhtml

Certification Exam Content
Associate Developer 11%
Professional Developer 10%

5.1 Create a controller for an admin router

How would you create an admin controller?

Admin routes go in /etc/adminhtml/routes.xml and admin router node uses id=”admin” instead of id=”standard”. All admin routes have /admin/ as the first segment of the URL. The controller folder directory is [Package]\[Module]\Controller\Adminhtml\[Controller Segment]\[Action Segment] which is similar to its front end counterpart but with no /Adminhtml/ segment. The controller also must inherit from Magento\Backend\App\Action along with a $context variable if using __contruct() method.

How do you ensure the right level of security for a new controller?

_isAllowed() is a required method for admin controllers and typically uses ACL rules to return true for access. The view/adminhtml/layout directory uses routeId_controller_action.xml to connect layout to route.

5.2 Define basic terms and elements of system configuration, including scopes, website, store, store view

How would you add a new system configuration option?

The system configuration goes in etc/adminhtml/system.xml and has element nodes like group, tab, section, and fields. To set default values of system.xml, use the etc/config.xml file. List of scopes ranges:

  • Global scope: System-wide settings and resources
  • Website scope: Settings and resources that are limited to the current website. Each website has a default store.
  • Store scope: Settings and resources that are limited to the current store. Each store has a default root category (main menu) and default store view.
  • Store view scope: Settings and resources that are limited to the current store view. The parameters showInDefault = “1”, showInWebsite = “1” and showInStore = “1” indicate which scope it is available.

What is the difference in this process for different option types (secret, file)?

5.3 Define / identify basic terms and elements of ACL

How would you add a new ACL resource to a new entity?

Your controller in the admin application must implement an _isAllowed() method or const ADMIN_RESOURCE which determines if a user can access the URL endpoint.

How do you manage the existing ACL hierarchy?

Editing etc/acl.xml. sorOrder define the position where the option is displayed in the menu.

<acl>
	<resources>
	    <resource id="Magento_Backend::admin">
		<resource id="Magenest_HelloWorld::helloworld" title="Hello World" sortOrder="51">
		    <resource id="Magenest_HelloWorld::post" title="Manage Post" sortOrder="10"/>
		    <resource id="Magenest_HelloWorld::helloworld_configuration" title="Configuration" sortOrder="99" />
		</resource>
		<resource id="Magento_Backend::stores">
		    <resource id="Magento_Backend::stores_settings">
			<resource id="Magento_Config::config">
			    <resource id="Magenest_HelloWorld::helloworld_config" title="Hello World"/>
			</resource>
		    </resource>
		</resource>
	    </resource>
	</resources>
</acl>

5.4 Set up a menu item

How do you add a new menu item to a given tab?

Adminhtml menu items are configured in etc/adminhtml/menu.xml. To add a new menu item, edit this file:

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd">
   <menu>
       <add id="Your_Module::brief_module_description"
           title="Your Menu Tab Title"
           translate="title"
           module="Your_Module"
           sortOrder="10"
           
           <!-- No parent means the tab appears in the side bar -->
           parent="Magento_Catalog::inventory"
           
           <!-- No action means the item acts as a header -->
           action="path/to/your/controller"
           
           <!-- ID of the ACL entry that validates permissions -->
           resource="ACL_Entry_ID"
           />
   </menu>
</config>

How do you add a new tab to the Admin menu?

Do not specify a parent attribute in the <add /> node.

5.5 Create appropriate permissions for users

How are menu items related to ACL permissions?

Menu items are not shown to users with insufficient permissions to access them.

How do you add a new user with given set of permissions?

Navigate to System > Permissions > All Users in Magento admin, add a new user, and set their role under User Information > User Role.

This can also be done programmatically:

use Magento\User\Model\UserFactory;

// ...

protected $userFactory;

public function __construct(UserFactory $userFactory)
{
    $this->_userFactory = $userFactory;
}

public function execute()
{
    $user = $this->userFactory->create();
    $user->setData(
        [
            'username'          => 'user.name',
            'firstname'         => 'Forename',
            'lastname'          => 'Surname',
            'email'             => 'admin@test.com',
            'password'          => 'badpassword123',       
            'is_active'         => 1
        ]
    );
    
    $user->setRoleId(1);
    $user->save(); 
}

6.0. Customising Magento Business Logic

Certification Exam Content
Associate Developer 16%

6.1. Product Types

Product Type Description
Simple A simple product is a physical item with a single SKU. Simple products have a variety of pricing and of input controls which makes it possible to sell variations of the product. Simple products can be used in association with grouped, bundle, and configurable products.
Configurable A configurable product appears to be a single product with lists of options for each variation. However, each option represents a separate, simple product with a distinct SKU, which makes it possible to track inventory for each variation.
Grouped A grouped product presents multiple, standalone products as a group. You can offer variations of a single product, or group them for a promotion. The products can be purchased separately, or as a group.
Bundle A bundle product let customers “build their own” from an assortment of options. The bundle could be a gift basket, computer, or anything else that can be customized. Each item in the bundle is a separate, standalone product.
Virtual Virtual products are not tangible products, and are typically used for products such as services, memberships, warranties, and subscriptions. Virtual products can be used in association with grouped and bundle products.
Downloadable A digitally downloadable product that consists of one or more files that are downloaded. The files can reside on your server or be provided as URLs to any other server.
Gift Card There are three kinds of gift cards: virtual gift cards which are sent by email, physical gift cards which are shipped to the recipient, and combined gift cards which are a combination of the two. Each has a unique code, that is redeemed during checkout. Gift cards can also be included in a grouped product.

How would you obtain a product of a specific type?

To obtain a specific product type, build search criteria and retrieve them from the product repository:

use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Bundle\Model\Product\Type;

...

public function getBundleProducts()
{
    $searchCriteria = $this->searchCriteriaBuilder
        ->addFilter(ProductInterface::TYPE_ID, Type::TYPE_CODE)
        ->create();
    
    return $this->productRepository->getList($searchCriteria)->getItems();
}

What tools (in general) does a product type model provide?

The product type model is responsible for:

  • Loading and configuring product options
  • Preparing the product for the cart
  • Processing product data to/from the database
  • Checking whether the product can be sold
  • Loading child products, when applicable

6.2. Category Properties

How do you create and manage categories?

Categories can be made in the admin panel under Category menu item and is a tree-link structure. Categories can be made programmatically using CategoryInterfaceFactory object and saving with CategoryInterfaceRepository.

6.3. Product/Category Relations

How do you assign and unassign products to categories?

Navigate to Catalog > Inventory > Products in Magento Admin, select the product you wish to add to a category, and use the Categories drop down selection options to assign it to categories.


6.4. Product Behaviour In The Cart

How are configurable and bundle products rendered?

view/frontend/layout/checkout_cart_item_renderers.xml define how products are rendered in the cart.

Configurable products are shown as a single line item. It is shown with the parent product's title and the simple product option selected by the customer.

Each product in the Bundle product is rendered as a single line item.


How can you create a custom shopping cart renderer?

You can customize the shopping cart by overriding with a module at vendor/module/view/frontend/layout/checkout_cart_item_renderers.xml. The block class depends upon the Magento\Checkout\Block\Cart\Item\Renderer class and includes Actions like /Renderer/Action/Edit and /Renderer/Action/Remove.


6.5. Native Shipping Functionality

How do you customize the shipment step of order management?

Basic steps of customizing shipping includes adding an etc/config.xml file and an etc/adminhtml/system.xml file. In order to extend and customize shipping, you must extend \Magento\Shipping\Model\Carrier\AbstractCarrier and implement \Magento\Shipping\Model\Carrier\CarrierInterface.


6.6. Customer Account Area Customisation

How would you add another tab in the “My Account” section?

To add an additional menu tab in the customer "My Account" area create the layout file in Your_Company/Your_Module/view/frontend/layout/customer_account.xml:

<body>
    <referenceContainer name="content">
        <referenceBlock name="customer_account_navigation">
            <block class="Magento\Customer\Block\Account\SortLinkInterface" 
                   name="yourBlockName"
                   after="customer-account-navigation-address-link">
                <arguments>
                    <argument name="label" xsi:type="string" translate="true">
                        Your Label
                    </argument>
                    <argument name="path" xsi:type="string">
                        path/to/your/module/view/
                    </argument>
                    <argument name="sortOrder" xsi:type="number">
                        10
                    </argument>
                </arguments>
            </block>
        </referenceBlock>
    </referenceContainer>
</body

How do you customize the order history page?

To customise the "Order History" page create the layout file in Your_Company/Your_Module/view/frontend/layout/sales_order_history.xml. The sales.order.history.info container is a common location for modifications to be made.


6.7. Add/Modify Customer Attributes

How do you add or modify customer attributes in a setup script?

Create Your_Company/Your_Module/Setup/UpgradeData.php with an upgrade() function:

use Magento\Customer\Model\Customer;

// ...

$attribute = $this->eavConfig->getAttribute(Customer::ENTITY, Attribute::CUSTOMER_PROMOTION_PREFERENCE);
$attribute->setData('used_in_forms', ['adminhtml_customer', 'customer_account_edit']);
$attribute->save();

6.8. Customising Customer Addresses

How do you add another field to the customer address entity using a setup script?

To add another field to customer address using a setup script, you use setup/InstallData.php while using EAV. Make sure the attribute is assigned to a form (such as customer_form_attribute table) to make sure it is saveable. The customer address field must be manually added just like other attributes.


References

Magento 2 Dev Docs

Component Load Order

Name Your Component

Create Your Component File Structure

Plugins (Interceptors)

About Magento Modes

Layout Instructions

Product Types

Declarative Schema