Magento 2: Magento 2 | What is proxies in magento 2.

Magento 2: Magento 2 | What is proxies in magento 2.:   Video link for real example. Proxies Design Pattern Proxies  is a powerful and easy technique to help you overcome a huge problem of Mag…

Puneet Kumar Magento Developer

Proxy Design Pattern in Magento 2 | Hindi

Puneet Kumar Magento Developer

Magento 2 | What is proxies in magento 2.

 

Video link for real example.

Proxies Design
Pattern

Proxies is a powerful and
easy technique to help you overcome a huge problem of Magento 2. Basically, we
can say it is design pattern, which is remove cycle of dependency injection.
However, its role and importance are still underestimated. Therefore, in this
post, I am going to help you to understand what is Magento 2 proxies and
its need in Magento 2.

What are Proxies in Magento 2

Just similar to design patterns which are created to solve a
cycle of dependency problems in the project, proxy design pattern solves a
particular problem. Proxies work as a surrogate which means it acts on behalf
of others, in programming, they are classes which could be used instead of any
other class. More specifically, in Magento 2, proxies are used to replace
resource hungry classes.

However, when replacing like that, an issue happens in Magento 2

In Magento 2 your able use constructor injection pattern to
flexibly manage your class dependencies. However, constructor injection also
means that a chain reaction of object instantiation is often the result when
you create an object. (The original object has dependencies that have
dependencies, and those objects have dependencies, and so on.)

If a
class’s constructor is particularly resource-intensive, this can lead to
unnecessary performance impact when another class depends on it, if the
expensive object does not end up being needed during a particular request. (You
can display a dependency graph of such objects
by enabling profiling.)

As an
example, consider the following two classes:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class SlowLoading
{
    public function __construct()
    {
        // ... Do something resource intensive
    }
 
    public function getValue()
    {
        return 'SlowLoading value';
    }
}
 
class FastLoading
{
    protected $slowLoading;
 
    public function __construct(
        SlowLoading $slowLoading
    ){
        $this->slowLoading = $slowLoading;
    }
 
    public function getFastValue()
    {
        return 'FastLoading value';
    }
 
    public function getSlowValue()
    {
        return $this->slowLoading->getValue();
    }
}

 

 

 





























Assume that class SlowLoading has a
non-trivial performance impact when instantiated (perhaps due to a complex
database query or a call to a third-party web API). Because of the dependency
injection in the constructor of 
FastLoading, this impact is
incurred if 
FastLoading is instantiated. Note, however, that the SlowLoading instance is used only in the method getSlowValue, meaning that the resource cost is unnecessary if this method
is never called on the 
FastLoading object.

Proxies
are generated code

Magento
has a solution for this situation: proxies. Proxies extend
other classes to become lazy-loaded versions of them. That is, a real instance
of the class a proxy extends is created only after one of the class’s methods
is actually called. A proxy implements the same interface as the original class
and so can be used as a dependency anywhere the original class can. Unlike its
parent, a proxy has only one dependency: the object manager.

Proxies
are generated code and therefore do not need to be manually written. (See Code
generation
 for more information.) Simply reference a class in the form 
OriginalClassNameProxy, and the class is generated if it
does not exist.

Using
the preceding example, a proxy can be passed into the constructor arguments
instead of the original class, using DI configuration as follows:

1
2
3
4
5
<type name="FastLoading">
    <arguments>
        <argument name="slowLoading" xsi:type="object">SlowLoadingProxy</argument>
    </arguments>
</type>


With
the proxy used in place of 
SlowLoading, the SlowLoading class will not be instantiated—and therefore, the resource
intensive constructor operations not performed—until the 
SlowLoading object is used (that is, if the getSlowValue method is called).

Because
DI configuration is used to inject a proxy, proxies can be dropped in to
replace their corresponding classes – or proxy replacements removed –
without touching application code.

As a
practical example of a proxy, you can see the StoreManager class and
then see the generated 
StoreManager proxy
class.

The
following excerpt from the Magento code passes the 
storeManager argument as a proxy to the MagentoStoreModelResolverStore class. The StoreManagerInterface model is defined as a proxy
class by the added 
Proxy at the end of the original class in the di.xml file.


1
2
3
4
5
<type name="MagentoStoreModelResolverStore">
    <arguments>
        <argument name="storeManager" xsi:type="object">MagentoStoreModelStoreManagerInterfaceProxy</argument>
    </arguments>
</type>
Puneet Kumar Magento Developer

Magento 2 order missing while place with online payment gateway.

Magento 2 order missing while place with online payment gateway. 

I am getting an issue very long time with online payment gateway. Some orders are not created in backend but payment was successful in payment gateway portal and user is also getting mail of order confirmation with order id. But order is missing in Magento2.3.x-p1 backend. 

Magento 2 sales dashboard screenshot.

Puneet Kumar Magento Developer

Dependency Injection in Magento 2

 Dependency Injection in Magento 2

Magento 2

In Magento 2 Dependency Injection is one of
the most useful design patterns.

We all are aware about class and objects,
class is collection of objects and methods, while object is an instance of
class.

Dependency means the class will use objects to
perform some function. Injection is process of passing required dependency to
that Class / Object. In other words, you can use functions of parent class with
the help of dependency injection to reuse code.

If you have one class (MagentoCustomerBlockForm)
that fetches data from other class (MagentoCustomerModelURL), then it is
conceived that one class has dependency on other class to provide some data or
results.

There are mainly two types of dependency
injection in 
Magento 2 which are as below.

Constructor Injection:

It is the basic type of dependency injection
used in Magento 2, where you just have to add parameter in class constructor to
inject dependency.

In Magento 2, if you want to get current
customer’s data then you can inject dependency of customer session in the
created class easily, there is no need to write whole code to get customer
data.

To understand this in detail, we take an
example. Data block class of custom module to get customer’s data and also it
has used viewHelper dependency to get customer name.

<?php

namespace PkgroupCustomBlockData;

 

class Data extends MagentoFrameworkViewElementTemplate

{

          
protected $_customerSession
;

          
protected $_viewHelper
;

 

        public
function __construct(

            
   MagentoFrameworkViewElementTemplateContext
$context
,

               
MagentoCustomerModelSession $customerSession
,

                MagentoCustomerHelperView
$viewHelper

           
)

        {

                       /* dependency injection of customerSession
and viewHelper for Data class */

                       $this->_customerSession = $customerSession;

                       $this->_viewHelper = $viewHelper;

               parent::__construct($context);

        }

 

        public
function getCustomer()

        {

              return  $this->_customerSession->getData(); // retrive customer
data

 

        }

                public function getName()

               {

                  /* get customer name with the help of
viewHelper object’s dependency injection using

                      customer data*/

                   return $this->_viewHelper->getCustomerName($this->getCustomer());

 

                }

}

?>

Code Sample: Data.php
(Constructor Injection)

In above sample code, a defined Data class for
custom module is created that will fetch data of customer session.

In this example, Data class has used object
customerSession to call the logic of getData() method, where you don’t have to
write separate code to get customer session data.

Method Injection:

When a particular method is dependent on class
then we have to pass that class as dependency in our method. The best example
to understand this concept is Magento Event’s Observer.

To understand this in detail, consider below
code sample of sales_order_place_after event’s OrderNumber Observer.

<?php

namespace PkgroupCustomObserver;

 

use
MagentoFrameworkEventObserverInterface
;

 

class OrderNumber implements ObserverInterface {

 

    /**

     *
@param MagentoFrameworkEventObserver $observer

    
*/

   
public
function execute(MagentoFrameworkEventObserver
$observer
) {

       
$order
= $observer->getEvent()->getOrder();

       
// Do Something Here

    }

}

 

?>

Code Sample:
OrderNumber.php(Method Injection)

In the above sample code,
MagentoFrameworkEventObserver will be served as a Dependency Injection for
OrderNumber class’s execute () method Or we can say that “execute()” method
function of OrderNumber class will be dependent on
MagentoFrameworkEventObserver to get order object $order.

ObjectManager:

The ObjectManager is class which handles
`automatic` Dependency Injection in Magento 2. When any class is constructed,
ObjectManager automatically injects class’s dependencies which is provided
directly (Constructor Injection) and defined in all di.xml files of modules.

The di.xml file defines which dependencies are
injected by ObjectManager which can be better understood with the use of
following di.xml code sample.

<? Xml version=“1.0”?>

<config xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=“urn:magento:framework:ObjectManager/etc/config.xsd”>

         
<preference for=“MagentoCustomerApiCustomerNameGenerationInterface”

                type=“MagentoCustomerHelperView” />

</config>

Code Sample: di.xml

According to the above code sample di.xml of
customer module has specified dependency of class “MagentoCustomerHelperView”
on Interface “CustomerNameGenerationInterface”. Preferences defines which class
will be used to instantiate an object.

Consider Constructor Injection Code Sample, in
which “ObjectManager” directly injects dependency of “viewHelper”, which will
use “MagentoCustomerApiCustomerNameGenerationInterface” to instantiate “viewHelper”
object according to above di.xml code sample.

Dependency Injection Object Types:

There are mainly two types of Objects in
Dependency Injection:

Injectable:

Injectable objects are singleton objects which
use “di.xml’s” configuration for Dependency Injection. Constructor Injection is
one of the examples of Injectable Objects.

Newable:

It can be also known as non-injectable
objects. These objects are used when we will require input from user or
database.

For Example, we cannot directly depend on
model like MagentoCustomerModel because it cannot be used without “customer_id”
or we have to specify customer object and we cannot specify such data in
constructor because it can’t be injectable.

In Magento 2, we can overcome this problem
with the use of factories. Factories are classes used to instantiate
non-injectable classes, so it can be called as service classes.

Models that represent a database entity is
non-injectable class and that can be instantiate using factories. Factory
classes provide one layer of abstraction to combine ObjectManager and business
code. Injectable objects depend on factories to get new able objects.

Newable objects are obtained by creating new
class instance when required with the use of create () method of factory class.
There is no need to define factory class because they are automatically
generated by ObjectManager when we define factory in class constructor.

For Example, we can directly use customer
model’s factory to get specific customer’s data or we can retrieve collection
of customer’s data from customer model object.

<?php

namespace PkgroupCustomBlock;

 

class CustomerData extends MagentoFrameworkViewElementTemplate

{

   
protected $customerFactory
;

 

    /**

     *
Construct

     *

     *
@param MagentoFrameworkViewElementTemplateContext $context

     *
@param MagentoCustomerModelCustomerFactory $customerSession

     *
@param array $data

    
*/

   
public
function __construct(

       
MagentoFrameworkViewElementTemplateContext $context
,

       
MagentoCustomerModelCustomerFactory $customerFactory
,

       
array $data
= []

    ) {

       
parent
::__construct($context, $data);

       
$this
->customerFactory = $customerFactory; // non-injectable objects used factory

    }

 

   
public
function CustomerData()

    {

       
$id
= 10 // Customer Id

       
/* create new
instance of customer model class using injectable object */

       
$customerModel
= $this->customerFactory->create()->load($id);

       
/*call this method
to get customer email from customer model object*/

       
$customerEmail
= $customerModel->getEmail();

       
/* retrive
collection of customer model  */

       
$collection
= $customerModel->getCollection();

    }

}

?>

Code Sample:
CustomerData.php (Use of Factories)

Another use of ObjectManager is that we can
directly use any model class, interfaces in templates, block or constructor.

To understand this, consider following example
of sample template code.

<?php

    
$ObjectManager
= MagentoFrameworkAppObjectManager::getInstance(); // get ObjectManager
instance

    
$customerid
= 14;

     /* create new instance of customer model
class using ObjectManager which is same as $customerModel  of above code sample */

    
$customer
= $ObjectManager->create(‘MagentoCustomerModelCustomer’)->load($customerid);

    
echo $customer
->getEmail(); // 

?>

Code Sample:
custom.phtml (Use Of ObjectManager In Template)

In above code sample, we have used
ObjectManager dependency to call customer model and the code written will also
give customer’s email from customer’s object.

Both the code (CustomerData.php and
custom.phtml) will give customer’s email but it gets differentiated because
Magento 2 supports automatic dependency injection as specified. So, when we use
factories, we don’t need to take ObjectManager dependencies, Magento 2 will
automatically inject it using customer factory; but in templates, Magento 2
does not support automatic dependency injection and we have to use
ObjectManager to get customer’s data directly.

Using ObjectManager
directly in template is not recommended because it defeats the purpose of
dependency injection and if we don’t use ObjectManager directly then our code
will be clearer to understand dependency by exploring constructors.


—————————–
Puneet Kumar Magento Developer

Composer and CLI php version change

 Compoer 

composer self-update --1

CLI php version
sudo update-alternatives --set php /usr/bin/php7.2

Puneet Kumar Magento Developer

Magento 2.4.x install | getting error Invalid credentials for ‘xxxproject-community-edition/magento-project-community-edition-2.4.2.0.zip’, aborting.

 I am trying to install Magento 2.4.x via composer but it giving below error. Have any one idea. 

Invalid credentials for ‘https://repo.magento.com/archives/magento/project-community-edition/magento-project-community-edition-2.4.2.0.zip’, aborting.

_____________________________________________________________________________________

Puneet Kumar Magento Developer

How to upgrade or downgrade install a specific version of Composer?

 Assuming a regular composer installation, to rollback to version 1 of composer, you simply execute:

composer self-update --1
When you want to go back to version 2 (which you should, after updating or 
removing the incompatible plugins):
composer self-update --2

Puneet Kumar Magento Developer

How to use magento 1 customer password in magento 2

 Magento 1 use MD5 hash to encrypt the password and Magento 2 use SHA-256.

In Magento 1, they use Mage_Core_Model_Encryption class with following functions.

1
2
3
4
5
6
7
8
public function getHash($password, $salt = false)
{
    if (is_integer($salt)) {
        $salt = $this>_helper>getRandomString($salt);
    }
    return $salt === false ? $this>hash($password) : $this>hash($salt . $password) . ‘:’ . $salt;
}
 

1
2
3
4
5
public function hash($data)
{
    return md5($data);
}
 

Magento 1 generate hash by md5(salt + password) and save in database with 1 colon like $password-hash : $salt.

Magento 2 has changed logic and written in vendor/magento/framework/Encryption/Encryptor.php

Magento 2 generate hash like hash(‘sha256’, $salt . $password); and save with 2 colons in database like

$password-hash : $salt: $version

You have to override Encryptor class via di.xml with some private functions in your module.

/**

 * Class Encryptor provides basic logic for hashing strings and encrypting/decrypting misc data

 */

class Encryptor extends MagentoFrameworkEncryptionEncryptor

{

/**

* @var array map of hash versions

*/

private $hashVersionMap = [

self::HASH_VERSION_MD5 => ‘md5’,

self::HASH_VERSION_SHA256 => ‘sha256’

];

/**

* @var array map of password hash

*/

private $passwordHashMap = [

self::PASSWORD_HASH => ”,

self::PASSWORD_SALT => ”,

self::PASSWORD_VERSION => self::HASH_VERSION_LATEST

];

/**

* @param string $hash

* @return array

*/

private function explodePasswordHash($hash)

{

$explodedPassword = explode(self::DELIMITER, $hash, 3);

foreach ($this->passwordHashMap as $key => $defaultValue) {

$this->passwordHashMap[$key] = (isset($explodedPassword[$key])) ? $explodedPassword[$key] : $defaultValue;

}

return $this->passwordHashMap;

}

/**

* @return string

*/

private function getPasswordHash()

{

return (string)$this->passwordHashMap[self::PASSWORD_HASH];

}

/**

* @return string

*/

private function getPasswordSalt()

{

return (string)$this->passwordHashMap[self::PASSWORD_SALT];

}

/**

* @return array

*/

private function getPasswordVersion()

{

return array_map(‘intval’, explode(self::DELIMITER, $this->passwordHashMap[self::PASSWORD_VERSION]));

}

    /**

     * @inheritdoc

     */

    public function isValidHash($password, $hash)

    {

        $this->explodePasswordHash($hash);

        

        $hashs = explode(“:”, $hash);

        if(count($hashs) == 2){

        $password = md5($this->getPasswordSalt() . $password);

        }

        else{

        foreach ($this->getPasswordVersion() as $hashVersion) {

        $password = $this->hash($this->getPasswordSalt() . $password, $hashVersion);

        }

        }

        

        //print $password . ” “. $this->getPasswordHash(); die;


        return Security::compareStrings(

            $password,

            $this->getPasswordHash()

        );

    }

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/**
* Class Encryptor provides basic logic for hashing strings and encrypting/decrypting misc data
*/
class Encryptor extends MagentoFrameworkEncryptionEncryptor
{
/**
* @var array map of hash versions
*/
private $hashVersionMap = [
self::HASH_VERSION_MD5 => ‘md5’,
self::HASH_VERSION_SHA256 => ‘sha256’
];
/**
* @var array map of password hash
*/
private $passwordHashMap = [
self::PASSWORD_HASH => ,
self::PASSWORD_SALT => ,
self::PASSWORD_VERSION => self::HASH_VERSION_LATEST
];
/**
* @param string $hash
* @return array
*/
private function explodePasswordHash($hash)
{
$explodedPassword = explode(self::DELIMITER, $hash, 3);
foreach ($this>passwordHashMap as $key => $defaultValue) {
$this>passwordHashMap[$key] = (isset($explodedPassword[$key])) ? $explodedPassword[$key] : $defaultValue;
}
return $this>passwordHashMap;
}
/**
* @return string
*/
private function getPasswordHash()
{
return (string)$this>passwordHashMap[self::PASSWORD_HASH];
}
/**
* @return string
*/
private function getPasswordSalt()
{
return (string)$this>passwordHashMap[self::PASSWORD_SALT];
}
/**
* @return array
*/
private function getPasswordVersion()
{
return array_map(‘intval’, explode(self::DELIMITER, $this>passwordHashMap[self::PASSWORD_VERSION]));
}
    /**
     * @inheritdoc
     */
    public function isValidHash($password, $hash)
    {
        $this>explodePasswordHash($hash);
        
        $hashs = explode(“:”, $hash);
        if(count($hashs) == 2){
         $password = md5($this>getPasswordSalt() . $password);
        }
        else{
         foreach ($this>getPasswordVersion() as $hashVersion) {
         $password = $this>hash($this>getPasswordSalt() . $password, $hashVersion);
         }
        }
        
        //print $password . ” “. $this->getPasswordHash(); die;
 
        return Security::compareStrings(
            $password,
            $this>getPasswordHash()
        );
    }
}
 

 

Now Magento 1 user will able to login their old password. New customers password logic will remain same.

Puneet Kumar Magento Developer