Technical Notes
Technical Notes
E-commerce : It is a process of purchasing and selling goods or services over the Internet
and transfers money and data to execute these transactions.
B2B : Wholesaler to Retailer OR manufacturer to Wholesaler
B2C : Sell Directly To Consumer By Business
C2C : Consumer to Consumer.
C2B : Consumer To Business.
Useful Links :
https://www.linkedin.com/advice/1/how-do-you-prevent-cross-site-scripting-attacks-skills-html
5
https://amasty.com/blog/magento-2-security-features-101/
Magento Community vs Enterprise :
● Support : Magento CE, you’re responsible for your own hosting, support, and
development. This means you’ll need to find a competent hosting provider and have
your own team of developers to help customise the platform and keep everything
running smoothly. In other words, you’re on your own to troubleshoot and fix all the
issues. In Magento Enterprise Edition, you will get access to premium support from
packages of Magento development services. This can be a big advantage, especially
if you don’t have an in-house team of developers.
● Security : Magento Enterprise version’s security features are its most important
selling point since the most significant disadvantage of the Magento Community
Edition is that it is not PCI compliant. The Magento community also does not have
credit card tokenization or extremely secure payment bridges, which are both
desirable features.
● Features :
- Targeted Promotions & Automated Email Marketing Reminder.
- Gift Registry and Gift Options
- Rewards Points and Store Credits
- Multiple Whishlist and Add To Cart By Sku Functionality
- Return Management Authorization (RMA) Support
- Scheduled Import/Export Functionality
- Customer Attribute Management
- PA-DSS Certification/Payment Bridge
Adobe Commerce (Magento 2 EE) B2B Features :
01. Shared Catalog
02. B2B Company Registration
03. Requisition Lists - Saved Access To Products For the Past Orders To Order Quickly, Its
different from the Wishlist - feature that allows customers to save products they are
interested in for future purchase, acting as a personalized shopping list, and can be shared
with others
04. Request a Quote - Fast Negotiation
05. Quick Order
06. Purchase Orders
Magento B2B for Magento Commerce
Magento Architecture :
● Persistence Layer : It describes the resource model, which is responsible for data
extraction and modification in the database using the CRUD requests. For
completing these requests, the resource model contains the SQL code.
● Domain Layer : The domain layer holds the business logic layer of a module. It
typically does not contain resource-specific or database-specific information. This
logic defines which operations can be performed on particular types of data, such as
a Customer object.
● Service Layer : The service layer provides a bridge between the presentation layer
and the domain layer and resource-specific data. This is implemented using service
contracts, which are defined using PHP interfaces.
● Presentation Layer : The presentation layer is the uppermost layer of Magento 2
architecture. When we interact with the web interface of Magento, that time, we are
interacting with the presentation layer code. It contains all controllers and View
elements such as - layouts, templates, block, and css.js, etc. The presentation layer
calls the service layer using service contracts, usually.
Initialize autoloader
$vendorDir = require BP . '/app/etc/vendor_path.php';
$vendorAutoload = BP . "/{$vendorDir}/autoload.php";
Line 5 : includes autoload file which in turn returns object of classLoader file located
at “vendor/composer/ClassLoader.php”
Last Line : Populates Autoloader and maps a namespace prefix to directories for
searching the corresponding class. Populate autoloader creates two arrays one for
each parser i.e prefixLengths and prefix Directories
Lets see how autoloader is loading files:
Let's take an example for Psr4:
Populate autoloader will create two arrays for “Psr4” i.e prefixLengthsPsr4 and
prefixDirsPsr4 as shown below .
prefixLengthsPsr4=Array(
[S] = Array(
[Symfony\CS\] = 11,
[StaticReview\] = 13,
[Seld\JsonLint\] = 14
)
[M] = Array(
[Monolog\] = 8,
[Magento\Setup\] = 14,
[Magento\Framework\] = 18,
[Magento\] = 8
)
[L] = Array(
[League\CLImate\] = 15
)
)
prefixDirsPsr4=Array(
[Symfony\CS\] = Array
(
[0] =
C:\xampp\htdocs\dev\m2\vendor/fabpot/php-cs-fixer/Symfony/CS
)
[StaticReview\] = Array
(
[0] =
C:\xampp\htdocs\dev\m2\vendor/sjparkinson/static-review/src
)
[Seld\JsonLint\] = Array
(
[0] =
C:\xampp\htdocs\dev\m2\vendor/seld/jsonlint/src/Seld/JsonLint
)
[Monolog\] = Array
(
[0] =
C:\xampp\htdocs\dev\m2\vendor/monolog/monolog/src/Monolog
)
[Magento\Setup\] = Array
(
[0] =
C:\xampp\htdocs\dev\m2/setup/src/Magento/Setup
)
[Magento\Framework\] = Array
(
[0] =
C:\xampp\htdocs\dev\m2/lib/internal/Magento/Framework
)
[League\CLImate\] = Array
(
[0] =
C:\xampp\htdocs\dev\m2\vendor/league/climate/src
)
[Magento\] = Array
(
[0] =
C:/xampp/htdocs/dev/m2/app/code/Magento/,
[1] =
C:/xampp/htdocs/dev/m2/var/generation/Magento/
)
)
○ Function createApplication()
/**
* Factory method for creating application instances
*
* @param string $type
* @param array $arguments
* @return \Magento\Framework\AppInterface
* @throws \InvalidArgumentException
*/
public function createApplication($type, $arguments = [])
{
try {
$this->initObjectManager();
$application = $this->objectManager->create($type,
$arguments);
if (!($application instanceof AppInterface)) {
throw new \InvalidArgumentException("The provided
class doesn't implement AppInterface: {$type}");
}
return $application;
} catch (\Exception $e) {
$this->terminate($e);
}
}
○ Line 6 above : Initialize Object ManagerAs clear from its name that this function is
initialising object manager and setting its instance to bootstrap variable
“objectManager” for future use. Further it retrieves Main configuration from
baseDirectory/app/etc/config.php by calling function below
/**
* Loads the configuration file
*
* @param string $configFile
* @return array
*/
public function load($configFile = null)
{
if ($configFile) {
$file = $this->dirList->getPath(DirectoryList::CONFIG) .
'/' . $configFile;
} else {
$file = $this->dirList->getPath(DirectoryList::CONFIG) .
'/' . $this->file;
}
$result = @include $file;
return $result ?: [];
}
Here $configFile is set to null, hence from the else condition i.e
$this->file=”config.php” it will include /app/etc/config.php
Line 7: Create App
Create function of object (Magento\Framework\ObjectManager\ObjectManager) will
initialise HTTP App object which in turn will return an instance of
‘Magento\Framework\App\Http’.
3. Run App
Now the run($app) function of the bootstrap instance will be called.
/** @var \Magento\Framework\App\Http $app */
$app = $bootstrap->createApplication('Magento\Framework\App\Http');
$bootstrap->run($app);
○ Run Function
/**
* Runs an application
*
* @param \Magento\Framework\AppInterface $application
* @return void
*/
public function run(AppInterface $application)
{
try {
try {
\Magento\Framework\Profiler::start('magento');
$this->initErrorHandler();
$this->initObjectManager();
$this->assertMaintenance();
$this->assertInstalled();
$response = $application->launch();
$response->sendResponse();
\Magento\Framework\Profiler::stop('magento');
} catch (\Exception $e) {
\Magento\Framework\Profiler::stop('magento');
if (!$application->catchException($this, $e)) {
throw $e;
}
}
} catch (\Exception $e) {
$this->terminate($e);
}
}
Line 12 above : initErrorHandler() initialises error Handler.
Line 13 : initObjectManager() initialises object manager if it’s not initialised.
Line 14 : assertMaintenance() inspects maintenance flag status. If set ‘yes’, the
maintenance page will display at frontend.
Line 15 : assertInstalled() checks if installation is completed, if not then throws an
exception and exception handler will redirect it to setup directory.
Line 16 : launch()
/**
* Run application
*
* @throws \InvalidArgumentException
* @return ResponseInterface
*/
public function launch()
{
$areaCode =
$this->_areaList->getCodeByFrontName($this->_request->getFrontName());
$this->_state->setAreaCode($areaCode);
$this->_objectManager->configure($this->_configLoader->load($areaCode)
);
/** @var \Magento\Framework\App\FrontControllerInterface
$frontController */
$frontController =
$this->_objectManager->get('Magento\Framework\App\FrontControllerInter
face');
$result = $frontController->dispatch($this->_request);
// TODO: Temporary solution till all controllers are returned
not ResultInterface (MAGETWO-28359)
if ($result instanceof ResultInterface) {
$this->registry->register('use_page_cache_plugin', true,
true);
$result->renderResult($this->_response);
} elseif ($result instanceof HttpInterface) {
$this->_response = $result;
} else {
throw new \InvalidArgumentException('Invalid return
type');
}
// This event gives possibility to launch something before
sending output (allow cookie setting)
$eventParams = ['request' => $this->_request, 'response' =>
$this->_response];
$this->_eventManager->dispatch('controller_front_send_response_before'
, $eventParams);
return $this->_response;
}
Routing :
Routing has an algorithm to find a matching controller, determined by request.
In web applications, such as Adobe Commerce and Magento Open Source, routing is the act
of providing data from a URL request to the appropriate class for processing. Adobe
Commerce and Magento Open Source routing uses the following flow :
Magento routing is one of the most important parts. Complete application (Magento 2) flow
depends on processing URL requests and router classes which are responsible for matching
and processing those requests.
Line 4 : is looping routerList and extracting the required one. Get Active routers list
Get routers list from modules di.xml
Let's take an example of frontend Magento Store module’s di.xml
<type name="Magento\Framework\App\RouterList" shared="true">
<arguments>
<argument name="routerList" xsi:type="array">
<item name="standard" xsi:type="array">
<item name="class"
xsi:type="string">Magento\Framework\App\Router\Base</item>
<item name="disable" xsi:type="boolean">false</item>
<item name="sortOrder" xsi:type="string">20</item>
</item>
<item name="default" xsi:type="array">
<item name="class"
xsi:type="string">Magento\Framework\App\Router\DefaultRouter</item>
<item name="disable" xsi:type="boolean">false</item>
<item name="sortOrder" xsi:type="string">100</item>
</item>
</argument>
</arguments>
</type>
Above config is adding two routers (standard and default) in routerList.
It can check Line number 20 and 25. In both, the disable parameter is set to false means
both are active.
Similarly you can use the same method in your custom module for creating your own router.
Line 6: match()
It is looping through each router and calling a match function for every router.
Match function will search for module’s frontend name, controller and action.
Let's take the router “Magento\Framework\App\Router\Base” so line 6 will call the match
function of Magento\Framework\App\Router\Base.
Then the match function will further call matchAction of the same instance.
If a match is found then it will call the create function of the factory which will create an
interceptor class file of the found controller and then return an instance of it.
Controller :
● LoadLayout
This function is responsible for adding default handlers as well as handlers defined
by the current controller. After that it loads the layout configuration of all handlers
added in the previous step. Prepares collection of all blocks associated with
handlers.
● RenderLayout
It renders all the handler's layout added previously and generates html output and
appends it to an output variable.
HTTP Response :
This is the end phase of magento execution where prepared output will be finally sent to the
requesting agent as HTTP response.
Send Response line 11
public function run(AppInterface $application)
{
try {
try {
\Magento\Framework\Profiler::start('magento');
$this->initErrorHandler();
$this->initObjectManager();
$this->assertMaintenance();
$this->assertInstalled();
$response = $application->launch();
$response->sendResponse();
\Magento\Framework\Profiler::stop('magento');
} catch (\Exception $e) {
\Magento\Framework\Profiler::stop('magento');
if (!$application->catchException($this, $e)) {
throw $e;
}
}
} catch (\Exception $e) {
$this->terminate($e);
}
}
Send Content
/**
* Send content
*
* @return Response
*/
public function sendContent()
{
if ($this->contentSent()) {
return $this;
}
echo $this->getContent();
$this->contentSent = true;
return $this;
}
Line 7 : $this->getContent() finally echo/print/output the content prepared by roaming inside
the magento application.
References
https://experienceleague.adobe.com/docs/commerce-operations/configuration-guide/setup/in
itialization.html
https://www.dckap.com/blog/request-flow-in-magento-2/
https://www.atwix.com/magento-2/request-flow-overview/
Magento 2 Design Patterns : Design patterns are typical solutions to commonly
occurring problems in software design, They are like certain patterns which framework or
software follows.
● Object Manager
● Dependency Injection (DI)
● Factories
● Proxies
● Preferences
● Argument Replacement - Type
● Virtual Types
● Event And Observers
● Plugins
● Repositories
● Injectable/Non-Injectable Object
Magento 2 Design Patterns can be very helpful if you know the right way to do it.
As all of you already know, design patterns are dispensable in software programming.
Thanks to design patterns, code becomes more organised and easier to develop and work
with.
Today we will discuss Magento 2 design patterns in detail to explore what Magento 2 Design
Patterns offers and how to handle them.
1. Object Manager
Magento 2 Object Manager is a PHP class responsible for creating and retrieving objects in
Magento 2. It also manages to create factories and proxies.
The ObjectManager is a Magento service class that instantiates objects at the beginning of
the bootstrapping process.
Object Manager takes the primary responsibility in instantiating and configuring Objects via
the two main methods: GET and CREATE.
● GET returns a singleton object (an instance of the class is used to share between
components when running Magento, on the other hand).
● CREATE returns an entirely new object (a new class instance).
Hence, if you call the GET method from 2 places, the same result will be generated. On the
contrary, you will receive a new object if you use the CREATE method.
So what is the purpose of Object Manager? Let’s find answers in the following:
● Instantiate Object Manager. Magento uses Object Manager to instantiate and insert
the class declared in the constructor.
● Implement the singleton pattern
● Manage dependencies
● Instantiate parameters automatically
Dependency simply means that something is dependent on something, like you are
dependent on your parents in the same way in programming if we create a class it can be
dependent on the objects those are created inside the class, for example:
<?php
class Product {
return $tax->getCalculateTax($id);
Injection simply means to provide something or to inject something by a third person.
Problem : You must be thinking what is the issue with that, why we should remove this
direct dependency, things are very easy without it. But imagine you are using a third party
library to calculate tax and after some update new library released which has the Taxation
class parameterized, and suppose its object is called 100 times inside hundreds of classes
then how you are going to update your code, it is a very simple situation there can be much
more complex situations like this.
Now let’s see how DI solves this situation in magento2:
<?php
class Product {
protected $_taxation;
public function __construct(
\Taxation $taxation
){
$this->_taxation = $taxation;
}
public function getTax($id) {
return $this->_taxation->getCalculateTax($id);
}
}
In the above code you can see, there is no use of new keyword for creating the object of
taxation class, but you must be thinking, in the case of non-parameterized Taxation class it is
ok but how it will manage parameterized class, this is the beauty of dependency injection
pattern and some of the oops concepts like reflection this can be managed very easily.
To handle the above situation you need to first create di.xml file in you magento2 module,
and make this entry:
<type name="/Taxation">
<arguments>
<argument name="%newParam%" xsi:type="%anyType%">%Argument%</argument>
</arguments>
</type>
making that entry means that when the ObjectManager will create the object of the Taxation
class it will first check its type declaration and will add the %newParam% value for its
object’s constructor, you can define any type of argument here in xsi:type like object, string,
int etc.
3. Factories
3.1. Overview
Factories are service classes that instantiate non-injectable classes, that is, models that
represent a database entity. They create a layer of abstraction between the ObjectManager
and business code. Magento automatically instantiates Factory (in the folder generated) with
the type as: <class-type>Factory.
For example: Magento\Catalog\Block\Product\ImageFactory
3.2. How to use Factory
● Call Factory in the Constructor:
function __construct ( \Magento\Cms\Model\BlockFactory $blockFactory) {
$this->blockFactory = $blockFactory;
}
You should always use factories for non-injectable objects, All the entities such as Product,
Customer are non-injectable and classes such as EventManager and all the Management
classes are injectable in magento2. Injectable objects don’t have identities but in the case of
non-injectable objects they have identities, so you don’t know which instance you need at
which time, so you must use Factory classes to inject non-injectable objects.
4. Proxies
Proxies are used to solve a specific problem in Magento 2. Proxies work as a substitute. In
programming, proxies are classes that can be used in place of any other classes. In
Magento 2 Proxies are used on behalf of resource hungry classes
Let’s assume that a slow loading class constructor calls a third-party API or does any
database transaction which will slow the performance. And, we are creating an object of the
slow loading class in the Fast Loading class constructor, and we need a slow loading object
when the getSlowValue() function gets called. If we don’t need the getSlowValue() function in
Our code then it will unnecessarily load class objects and perform those heavy transactions.
Magento has a solution on this proxy. We can create a proxy of the Slow Loading class and
call the main class whenever it is required, i.e. When we call any function from a
slow-loading class, Magento creates an object of the main class and calls its functions.
Proxies are generated code and therefore do not need to be manually written. Simply
reference a class in the form \Original\Class\Name\Proxy, and the class is generated if it
does not exist.
It is best to use Proxy for classes with resource-intensive constructors (with lots of
objects injected), e.g. session classes.
6. Argument Replacement
6.1. Overview
Argument Replacement is used via the di.xml file which includes dependencies and
injection. You need Argument Replacement to change some dependencies injected into the
constructor when instantiating that class. The name of Argument Replacement in the XML
file is corresponding to the name used in class.
For example: In the file: vendor/magento/module-catalog/etc/di.xml
In the constructor of Magento\Catalog\Helper\Product class:
6.2. Argument Types : Object, String, Boolean, Number, Cont, Null, Array
⇒ Strengths:
● Various types to modify class such as an object, number, array, and so on
● High flexibility
⇒ Weakness:
● Complicated structure
● Require to declare following the right structure
7. Virtual Types
Virtual Types allows us to modify existing classes without affecting the other classes and
without having to create a new class file
For example, you create a session catalog in this file:
vendor/magento/module-catalog/etc/di.xml
8.1. Events
An action of a module activates events. Events share data with observers, and you can edit
the input data. Magento also allows us to create custom events to modify data.
Event Areas
It is divided into 3 types depending on the events.xml file:
+ etc/adminhtml/events.xml – adminhtml
+ etc/frontend/events.xml – frontend
+ etc/events.xml – global
8.2. Observers
Observers are used to catching events in order for changing the input data so that you can
modify, logic, and so on.
9. Plugins
You can also consider the Plugin method to customise a function in Magento 2. It is applied
to all public methods in class, interface, and framework.
The Plugin method can be only applied for the public method, and does not cover the
following cases:
● Final method
● Final class
● Non-public method
● Static class method
● __constructor
● Virtual Type
● Object that is instantiated via Magento\Framework\Interception
⇒ Strengths:
● Easy to use with a clear structure
● High flexibility – Few conflicts with 3rd parties
● Ability to modify almost functions (public method only)
⇒ Weakness:
● Not modify protected or private method
● Not call other protected or private methods in the current plugin. You have to entirely
rewrite.
● Not be modified in case class is directly called via Object Manager
10. Repositories
Repositories are service contracts which are interface classes, and help to hide your
business logic from controller,model and helper. In this file we defined our repository file
which is an interface class.
A repository is an abstraction layer that provides an interface for working with data in a
module. Repositories are used to separate the domain logic of a module from the
persistence layer, making it easier to work with data and reducing the coupling between
different parts of the system.
In practice, a repository typically consists of a PHP interface that defines the methods for
working with a particular data entity, such as a product or customer. The interface is
implemented by a concrete class that provides the actual implementation of the methods,
using a combination of Magento's models, resource models, and collections.
For example, in the case of a product repository, the interface might define methods such as
getProductById(), saveProduct(), and deleteProduct(). The implementation of these methods
would use Magento's product model, resource model, and collection to perform the
necessary operations on the database.
📁 Api/
This directory contains Service Interfaces, which define what the module does — like
operations or actions you can perform (CRUD methods, custom service methods, etc.).
Examples of files:
● ProductRepositoryInterface.php
● CustomServiceInterface.php
📁 Api/Data/
This directory contains Data Interfaces, which define the data structure — like DTOs (Data
Transfer Objects). These are used in method signatures of service interfaces.
Examples of files:
● ProductInterface.php
● OrderDetailsInterface.php
These define the getters and setters for data fields. For example:
interface ProductInterface
{
const NAME = 'name';
References :
https://www.atwix.com/magento/design-patterns-in-magento-2-object-manager/
https://www.wishusucess.com/what-is-factory-class-in-magento-2/
https://magento.stackexchange.com/questions/75108/why-object-manager-can-not-instantiat
e-non-injectable
https://magently.com/blog/magento-2-design-patterns-preferences-virtual-types/
app/code/Jayanka/HelloWorld/Model/Car.php
<?php
namespace Jayanka\HelloWorld\Model;
use Magento\Framework\Model\AbstractModel;
use Jayanka\HelloWorld\Model\ResourceModel\Car as ResourceModel;
The Car class only has one method, _construct(), when we call the _init()method, and pass
the resource model’s name as its parameter. But what is a resource model?
Resource Model
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.
app/code/Jayanka/HelloWorld/Model/ResourceModel/Car.php
<?php
namespace Jayanka\HelloWorld\Model\ResourceModel;
use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
As we can see, the <Carclass> here also has one method, <__construct>, where we call the
<_initmethod>, and pass two parameters to it. The name of the table in the database, and
the name of the primary column in that table.
Collection
Collections are used when we want to fetch multiple rows from our table. Meaning
collections are a group of models. Collections can be used when we want to
app/code/Jayanka/HelloWorld/Model/ResourceModel/Car/Collection.php
<?php
namespace Jayanka\HelloWorld\Model\ResourceModel\Car;
use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
use Jayanka\HelloWorld\Model\Car as Model;
use Jayanka\HelloWorld\Model\ResourceModel\Car as ResourceModel;
class Collection extends AbstractCollection
{
protected function _construct()
{
$this->_init(Model::class, ResourceModel::class);
}
}
Controllers :
Java
// Backend OR Admin Controller
class Index extends \Magento\Backend\App\Action
Java
// Frontend Controller
class Index extends \Magento\Framework\App\Action\Action
JSON : This returns a response in JSON format. It can be used in API or AJAX requests.
Class: \Magento\Framework\Controller\Result\Json
Redirect : This represents a 301 or 302 redirect. It is used when a user needs to be
redirected to a different URL.
Class: \Magento\Framework\Controller\Result\Redirect
Forward : This internally forwards to another controller without changing the URL.
Class: \Magento\Framework\Controller\Result\Forward
Blocks :
Java
class Index extends \Magento\Framework\View\Element\Template
EAV stands for Entity-Attribute-Value, It is a data model which is more normalised and
substantially more scalable than Normal Models Or Flat Model. Without changing the basic
database structure, developers can add properties to any entity (product, category,
customer, order, etc.). It is a data model which encodes entities in a space-efficient manner
where the number of attributes (properties, parameters) that can be used to describe them is
vast and the number that will apply to a given entity is relatively modest.
In which:
● Entity: Magento data objects such as products, categories, customers, and orders
are represented as entities.
● Attribute: An attribute is a data piece that belongs to a specific entity. The product
entity, for example, has attributes such as name, price, and status, among others.
● Value: The value is the most straightforward, as it is simply a value associated with
an attribute.
To overcome these drawbacks, Magento 2 comes up with a new solution by combining data
into a Flat table: catalog_product_flat, for example.(When you enable Use Magento 2 Flat
Catalog Product config at Store ⇒ Configuration ⇒Catalog ⇒Catalog ⇒Storefront).
In this table, attribute data is updated/inserted when you run an index (via cron or cli) or save
the product, depending on the Product Flat Data config in Index Management. Hence, you
just need to implement queries to get data via the catalog_product_flat table. And the query
is now much more straightforward:
SELECT
1 AS `status`,
`e`.`name`,
`e`.`price`,
`e`.`description`
FROM
`catalog_product_flat_1` AS `e`
WHERE `e`.`entity_id` = 6
Magento 2 Area codes is a crucial component that helps manage different contexts within
the application, such as the frontend, admin, and web API areas.
It sets the environment for code execution and loads only the relevant code for each specific
context.
- adminhtml
- frontend
- base
- Cron
- webapi_rest
- webapi_soap
- graphql
- crontab
Modes In Magento :
- Default
- Production
- Developer
- Maintenance (Restrict The Access)