Page 2 - Ihor Vansach
- 1 min read
Sometimes when you use Magento 2 you can get the Magento catalog_product_super_link table doesn`t exists error. It appears because some module tries to make an SQL request with SQL query that includes "catalog_product_super_link" table and the table does not exist. So actually, the error is self-explaining.
Why catalog_product_super_link table might not exist?
This table is defined in Magento 2 module Magento_ConfigurableProduct. So please make sure it is enabled in app/etc/config.php. If not, enable it by changing 0 to 1 in the right part, e.g:
'Magento_ConfigurableProduct' => 1,
Then, run the following commands:
bin/magento setup:upgradebin/magento setup:di:compilebin/magento setup:static-content:deploy
If this does not help, then you can create the table using these SQL queries (you can run them e.g. in phpMyAdmin):
Attention! Replace "prefix_" and "PREFIX_" with your actual Magento 2 database prefix, or just remove them if you don't use the prefix for the database table names.
CREATEihor
- 1 min read
UPD: "As of the morning of February 22, 2024, 528 children were killed and 1226 injured in Ukraine as a result of full-scale russian invasion of Ukraine according to Children of War Governmental portal, " - Ukrainian Prosecutor General's Office.
The Russian troops have already killed more than 100 Ukrainian kids.
Tanya, who was at the age of 6 died or dehydration under the rubble of her house.
Alice from Okhtyrka, she was 7, was killed during the shelling of the kindergarten from Grad rockets.
Sofia, from Nova Kahovka, who was 6, was shot with her family.
How many more children have to die?
How many more children have to be born in the bomb shelters?
How many more days do mothers have to fall asleep in fear that their children might not wake up tomorrow?
These murders are crimes against humanity. They kill our future — our children.
Stop killing Ukrainian children!
Stop this war!
- 2 min read
Magento 2 Registry is a class that is used to share the data between objects in Magento.
e.g. save the object to the Registry in the controller class and get in the block class.
Starting from Magento 2.3 the Registry class was declared as deprecated but a lot of developers, extension vendors, and even Magento core code still use it.
How does it work?
To get a Registry object in your class you need to define it in the constructor, for example:
/*** @var \Magento\Framework\Registry*/private $registry;/*** ...* @param \Magento\Framework\Registry $registry,*/public function __construct(...,\Magento\Framework\Registry $registry,...) {$this->registry = $registry;...}
or you can easily get it via the for the testing purpose:
$registry = \Magento\Framework\App\ObjectManager::getInstance() ->get(\Magento\Framework\Registry::class);
How to SET a new value into the Registry?
To set a new value into the register please use the public function register($key, $value, $graceful = false) methodihor
- 3 min read
There are a lot of processes in Magento 2 admin that require automation and scheduling. Updating currency rates, sending newsletters and product alerts are all handled by a handy default feature — .
Besides, plenty of Magento 2 extensions also come with custom cron jobs to execute different tasks within the module. So, if you're wondering how you can create one for your extension too, you've landed in the right place.
Today you'll learn how to create a cron job in Magento 2 step by step.
Note: before creating your custom cron job, make sure you have the crons by opening the crontab as the Magento file system owner. Run the following command:
crontab -l
The result should be as follows:
#~ MAGENTO START c5f9e5ed71cceaabc4d4fd9b3e827a2b
* * * * * /usr/bin/php /var/www/html/magento2/bin/magento cron:run 2>&1 | grep -v "Ran jobs by schedule" >> /var/www/html/magento2/var/log/magento.cron.log
#~ MAGENTO END c5f9e5ed71cceaabc4d4fd9b3e827a2b
1. Create a Simple Module
The first stepihor
- 1 min read
To set up Elasticsearch 7 on Ubuntu 20.04 please run these simple commands one-by-one in the command-line interface:
sudo apt -y install gnupgwget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -sudo apt -y install apt-transport-httpsecho "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-7.x.listsudo apt updatesudo apt -y install elasticsearch//To install a specific Elasticsearch version, specify it in the command:sudo apt -y install elasticsearch=7.10.2
By default, Elasticsearch uses 2GB RAM memory for JVM. If your server has limited memory size you can reduce it to e.g. 1gb or 512mb. To do this edit the jvm.options file, run the command:
sudo nano /etc/elasticsearch/jvm.options
and change the
-Xms2g-Xmx2g
to
-Xms1g-Xmx1g
Save the jvm.options file.
Next, enable and start elasticsearch service, run the commands:
sudo systemctl enable elasticsearch.service && sudo systemctl restart elasticsearch.serviceihor
- 2 min read
Magento 2 Preferences is used by the to extend the default implementation. You can use preferences in Magento 2 to implement some interfaces or to rewrite/override the existing PHP classes and their methods.
In this article, you'll learn how to do it and discover useful examples that will help you along the way.
Overriding classes in Magento 2
If you want to rewrite existing class methods with Magento preference follow the steps below:
1. Create the etc/di.xml file in your extension folder:
app/code/MyCompany/ModuleName/etc/di.xml
2. Add this code to it:
<?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="Magento\Checkout\Block\Onepage\Success" type="MyCompany\ModuleName\Block\Onepage\Success" /></config>
Use attribute "for" in the "preference" tag to define the PHP class that you want to override. Use attribute "type" to define the PHP class that willihor
- 1 min read
Last week the whole Magento world was really frustrated by the news from some Magento extension providers about the Switch to the Subscription Model. Now we can observe a wave of resentment from their customers.
If you are interested in whether Magefan will also switch to the Subscription Model, then you will find the answers in this letter to know what to expect.
We are discussing this within our team now. You, our customers, your success and prosperity are our top priority. So, you will continue getting benefit from our products and services as you are used to.
Even if we implement any changes in the future, none of you will be disappointed or stressed because of it, since those changes will be implemented with the “what’s better for our customers” idea in mind. We will keep our words and guarantees. And if any of such changes take place in the future, they will not confuse you.
We want to reassure you that the accessibility of our products and updates, quality of our products and servicesihor
- 1 min read
Today we have a very special announcement - the first-ever PWA conference is starting soon!
Moreover, our Magefan CEO Ihor Vansach will be among the speakers of this event tackling some hot questions for Magento developers:
How to make your current Magento 2 Extension PWA ready and build a new one for the PWA backend?
You will get a comprehensive guide on getting Magento extensions ready for PWA, that also includes the road map and pitfalls. PWA technology is more trending than it has even been before.
So, you can book a seat at GoPWA Online Conference ‘21 that will take place on September 29-30, 2021 to join our discussion. And it is absolutely free!
- 1 min read
Solved: Package exists in composer repo 1 and composer repo 2 which has a higher repository priority
When you install some new extension package in Magento 2 via the composer you can get an error:
[InvalidArgumentException] Package vendor/module-name exists in composer repo (https://repo.packagist.org) and composer repo (https://repo.magento.com) which has a higher repository priority. The packages with higher priority do not match your constraint and are therefore not installable. See https://getcomposer.org/repoprio for details and assistance.
This error message is self-explaining and contains a link to the composer documentation.
The problem is that a module you try to install has an old version in the Magento composer repository and a new version in the free public packagist.org repository. However, the Magento repository has a higher priority and that is why composer cannot install the latest version and throws this error.
What you need to do to solve the issue is to:
1. Open composer.json file in your Magento 2 root directory.
2. Find the "repositories" section.
3. Replace the followingihor
- 2 min read
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.
How does it work?
To get the object manager instance (e.g. get magento 2 object manager in phtml) use the code:
<?php $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
To add object Manager to constructor:
/
* @var \Magento\Framework\ObjectManagerInterface
*/
private $objectManager;
/
* @param \Magento\Framework\ObjectManagerInterface $objectmanager
*/
public function __construct(
\Magento\Framework\ObjectManagerInterface $objectmanager
) {
$this->objectManager = $objectmanager;
}
Using the ObjectManager you can get a singleton object (method "get") of PHP class or create a new one (method "create").
Example:
<?php $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); /* Create a new product object */ $product = $objectManager->create(\Magento\Catalog\Model\Product::class); /* Get a request objectihor
- 1 min read
Sometimes you need to run Magento 2 code externally, in the following cases:
Magento 2 integration with other frameworks or platforms that are installed on the same web server,
quick test execution of some method, for example, cron job.
For example, create a test.php file in the Magento 2 root directory and add the following code to it:
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
use Magento\Framework\App\Bootstrap;require __DIR__ . '/app/bootstrap.php';
$bootstrap = Bootstrap::create(BP, $_SERVER);
$obj = $bootstrap->getObjectManager();
$state = $obj->get(Magento\Framework\App\State::class);$state->setAreaCode('adminhtml');
$object = $obj->create(\VendorName\ModuleName\Folder\Class::class);$object->someMethod();
VendorName\ModuleName\Folder\Class - the name of the class, you want to execute;someMethod - the name of the method you want to execute;Attention! Make sure the __DIR__. '/app/bootstrap.php is the correct path to the Magento 2 app/bootstrap.php fileihor
- 4 min read
In Magento 2 you can create plugins (interceptors) that allow you to extend functionality and execute your own code before, after, or around any PHP class public method.
For example there is a PHP class with public functions "setName", "getName", "save":
<?phpnamespace VendorName\ModuleName\Folder;class SomeModel{ private $name; public function setName($name, $storeId = 0) { $this->name[0] = $name; } public function getName($storeId = 0) { return $this->name[$storeId]; } public function save($fields, $customData) { /* some save logic here */ }}
How to create plugin in Magento 2?
1. Create the etc/di.xml file in folder and add the following code there:
<?xml version="1.0"?><config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="VendorName\ModuleName\Folder\SomeModel"> <plugin name="mycompany_mymodule_plugin_modulename_Folder_somemodel" type="MyCompany\MyModule\Plugin\ModuleName\Folder\SomeModelPlugin"ihor
- 3 min read
In the you learned how to create new tables in Magento 2 database. In this one, you will learn more about the models used to work with the Magento 2 database which allows you to read, edit and delete the data.
Magento 2 and Magento 1 uses the Model/ResourceModel/Collection ORM (Object-relational mapping) for these purposes. To implement this concept you need to create 3 files (model, resource model, collection).
1. Create the Model file:
app/code/VendorName/ModuleName/Model/Somemodel.php
add the following code to it:
<?php
namespace VendorName\ModuleName\Model;
class Somemodel extends \Magento\Framework\Model\AbstractModel{ protected function _construct() { $this->_init('VendorName\ModuleName\Model\ResourceModel\Somemodel'); }}
The _construct initializes the resource model. Pass the name of the resource model class (create it in the next step) to the _init method.
Model is what you will most often work with. This class must be inherited from ihor
- 2 min read
When developing an online store based on Magento 2, you might face the problem of extending the standard Magento 2 or functionality.
Editing Magento core files or modules is not allowed because these changes will be overwritten during the .
So, how to make changes to the storefront (frontend) template file, css, js?
WARNING! The following instructions cannot be used to override the layout files.
Override module view-files in the app/code folder.
Let's say you need to change this file:
app/code/Magefan/Blog/view/frontend/templates/post/view.phtml
Make its copy in the theme folder with the following path:
app/design/frontend/ThemeVendor/themename/Magefan_Blog/templates/post/view.phtml
Make the necessary changes to the newly created theme file.
If your own theme is missing from your Magento installation, create new theme.
Override module view-files in the vendor folder.
Let's say you need to change this file:
vendor/magefan/module-blog/view/frontend/web/css/blog-custom.css
Make its copy inihor
- 2 min read
If you get an error "An element with a “root” ID already exists" in your Magento 2, it is, most likely, related to a third-party extension that calls methods to re-render a page.
To fix the "An element with a “root” ID already exists" error:
1. Find a PHP file and a line that throws an exception.
2. Open CLI (terminal), navigate to the Magento root directory, and run the following commands to find the proper file:
grep vendor/ -re ' ID already exists'grep app/ -re ' ID already exists'
As a result, you will get an output similar to this:
vendor/magento/framework/Data/Form.php: 'An element with a "' . $elementId . '" ID already exists.'vendor/magento/framework/Data/Test/Unit/FormTest.php: $this->expectExceptionMessage('An element with a "1" ID already exists.');vendor/magento/framework/Data/Structure.php: new \Magento\Framework\Phrase('An element with a "%1" ID already exists.', [$elementId])
3. Then open each file (except *Test.php) and put a and exit function before each throws an exceptionihor
- 2 min read
If you want to change type from dropdown to text in Magento 2, all you need to do is to run the following SQL queries (please make a Database backup before execution):
1. This query will change the attribute settings and convert it to a text attribute.
UPDATE eav_attribute SET backend_type = "varchar", frontend_input = "text", source_model = ""WHERE attribute_code = "MY_ATTRIBUTE_CODE";
2. This query will copy dropdown attribute data to the text attribute value table and replace the option IDs with their actual labels (text).
INSERT INTO catalog_product_entity_varchar SELECT null as value_id, pei.attribute_id, pei.store_id, pei.entity_id, aov.value as value FROM catalog_product_entity_int pei LEFT JOIN eav_attribute_option ao ON pei.attribute_id = ao.attribute_id LEFT JOIN eav_attribute_option_value aov ON ao.option_id = aov.option_id WHERE pei.value IS NOT NULL AND pei.attribute_id = (SELECT attribute_id FROM eav_attribute WHERE attribute_code = "MY_ATTRIBUTE_CODE") AND aov.store_id =ihor
- 2 min read
Sometimes, during you need to get the store Information programmatically. You may need to get a current Store ID, Store Code, Name, Website ID, or .
To retrieve this data use the singleton instance of the following class:
\Magento\Store\Model\StoreManagerInterface
For example, you can include it in your class constructor and then call:
<?phpnamespace \MyCompany\ExampleModule\Model;class Example{ private $storeManager;
public function __construct(
...
\Magento\Store\Model\StoreManagerInterface $storeManager,
...
) { ...
$this->storeManager = $storeManager;
...
}
/** * Examples */ public function execute() { /* Get Current Store ID */ $storeId = $this->storeManager->getStore()->getId(); /* Get Current Store Code */ $storeCode = $this->storeManager->getStore()->getCode(); /* Get Current Store Name */ $storeName = $this->storeManager->getStore()->getName(); /* Get Current Storeihor
- 1 min read
Get URL in the .phtml template files
1. Get URL of the store homepage (http://domain.com/):
<?= $this->getUrl() ?>
2. Get URL of some page, e.g. "Contact Us" (http://domain.com/contacts/):
<?= $this->getUrl('contacts') ?>
3. Get URL of the theme static file, e.g.:
app/design/frontend/ThemeVendor/theme_name/web/css/custom.cssapp/design/frontend/ThemeVendor/theme_name/Magefan_Blog/web/js/lazyload.jsapp/code/Magefan_Blog/view/frontend/web/js/lazyload.jsvendor/magefan/module-blog/view/frontend/web/js/lazyload.js
use the following code:
<?= $this->getViewFileUrl('css/custom.css') ?><?= $this->getViewFileUrl('Magefan_Blog::js/lazyload.js') ?>
4. Get URL of the static file in pub/media:
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();$mediaUrl = $objectManager->get(Magento\Store\Model\StoreManagerInterface::class) ->getStore() ->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
<?= $mediaUrl ?>wysiwyg/image.png
Attention! You should not use media files in the themeihor
- 2 min read
Menu Title [identifier]
Dashboard [Magento_Backend::dashboard]
Sales [Magento_Sales::sales]
Operations [Magento_Sales::sales_operation]
Orders [Magento_Sales::sales_order]
Invoices [Magento_Sales::sales_invoice]
Shipments [Magento_Sales::sales_shipment]
Credit Memos [Magento_Sales::sales_creditmemo]
Billing Agreements [Magento_Paypal::paypal_billing_agreement]
Transactions [Magento_Sales::sales_transactions]
Products [Magento_Catalog::catalog]
Inventory [Magento_Catalog::inventory]
Catalog [Magento_Catalog::catalog_products]
Categories [Magento_Catalog::catalog_categories]
Customers [Magento_Customer::customer]
All Customers [Magento_Customer::customer_manage]
Now Online [Magento_Customer::customer_online]
Marketing [Magento_Backend::marketing]
Promotions [Magento_CatalogRule::promo]
Catalog Price Rule [Magento_CatalogRule::promo_catalog]
Cart Price Rules [Magento_SalesRule::promo_quote]
Communications [Magento_Backend::marketing_communications]
Email Templates [Magento_Email::template]ihor
- 1 min read
The etc/adminhtml/menu.xml file is used to control the Magento 2 admin panel menu and add new items to it, in particular.
Create this file in folder, to add new menu element:
etc/adminhtml/menu.xml
and add the following code there:
<?xml version="1.0"?><config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd"> <menu> <add id="VendorName_ModuleName::key1" title="Title 1" module="VendorName_ModuleName" parent="OtherVendorName_OtherModuleName::content" sortOrder="10" resource="VendorName_ModuleName::key1"/> <add id="VendorName_ModuleName::key2" title="Title 2" module="VendorName_ModuleName" parent="VendorName_ModuleName::key1" sortOrder="10" action="path/controllerName" resource="VendorName_ModuleName::key2"/> </menu></config>
id - a unique ;title - text of the element;module - defines what module the element belongs to;parent - identifier of the parent menu item;sortOrderihor
- 1 min read
In the we described how to create your own section on the Magento 2 configuration page (Stores > Configuration).
In order to set the default values for the configuration fields, you need to create the following file in the folder:
etc/config.xml
and add this code:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd"> <default> <section_id> <group_id> <field_id>default_value</field_id> </group_id> </section_id> </default></config>
The section_id/group_id/field_id hierarchy has to match the structure in the system.xml file.
To clear the cache, run the CLI command:
php bin/magento cache:clean
Check the result.
In the examples, we create a module for FAQ. The modified module code can be viewed on GitHub.

