5 Must Have Extensions for Your Magento 2 E-Commerce Store

As we all know, Magento 2 is already very feature-rich. But, in terms of running a successful E-Commerce store, you might need to have some more feature in your store for better user experience.

Since the launch of Magento 2, several vendors have been developing and launching numerous extensions. Some are free, some are paid. To help you get started, we present you our rundown of the best 10 must-have extensions for your Magento 2 store. The following list will help expand your e-commerce store’s functionality and attract new customers as well.

Magento 2 Out of Stock Notification

You don’t need to lose a client on the off chance that one of your store’s items is out of stock. Using this module, customers can subscribe to out-of-stock items. When you’re prepared to offer that item, a notification can be triggered to customer. It can be done in both ways, automatic and manual.

GeoIP Store and Currency Switcher

If you offer your products in multiple languages or currencies, then this extension can be found very useful. You can configure the extension so that it can detect frontend user’s location and then can automatically switch language/store based on the configuration done from Admin panel.

Store Credit Extension for Magento 2.x

Magento 2 Store Credit extension by xMagestore is a powerful tool to increase customer loyalty and motivate customers. Store Credit extension significantly supports e-commerce stores to encourage customers’ purchases by awarding them credit amount which is automatically added to their account balance.

Twilio SMS Extension for Magento 2.x

You might need to send order updates via text message, or might need to verify the phone number of customer, in that case, this extension can be very useful. It uses Twilio API services, so to use this module, you will need to have an account on Twilio.

Alternatively, you can use some other extensions, if you want to use any other API service provider:

Text Local

SEO Suite Ultimate Extension for Magento 2

SEO Suite Ultimate is a full-featured SEO solution that covers a full range of onpage SEO activities: from optimizing small page elements to building a well-thought site architecture.


We sincerely hope that you found our list of the must-have extensions for your Magento 2 e-commerce store helpful and educative. As you can see, there are numerous ways to fine-tune your store, reach more customers, and provide a pleasant shopping experience.

Remove index.php from Magento Store URL

In this blog, we will see how to remove index.php from base URL of a Magento store.

To remove “index.php” from the web-site URL, the mod_rewrite module should be enabled on your server.

In case, mod_rewrite is not enabled, follow these steps:

  1. Run this command sudo a2enmod rewrite
  2. Edit your httpd configuration and write following lines
    <Directory /var/www/>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
  3. Now, restart apache service using this command (the commands might change based on the OS that you use)
    sudo service apache2 restart

You need to following these steps:

  1. Log in to your Magento store admin and go to the Store ⇒ Configuration section. (In case of Magento 1, it’s System  Configuration)
  2. Then click on the Web tab in the leftside menu.
  3. Expand the Search Engines Optimization tab and set the Use Web Server Rewrites option to Yes.
    Search Engines Optimization
  4. Then, go to the Base URLs (Secure) tab and set the Use Secure URLs on Storefront option to Yes, too. Click on the Save Config button.
    Base URLs (Secure) ⇒ Use Secure URLs on Storefront
  5. Make sure your Secure and Unsecure base urls should end with “/”.

Sending Email with Attachment in Magento 2.3.x

Some of the functionalities in Magento 2.3.x is different from previous page. The reason is that in most cases the 2.3.x framework uses Zend Framework 2 (ZF2) and almost totally refuses to applyZend Framework 1 (ZF1). So, due to this, the previous method Magento\Framework\Mail\MailMessageInterface::createAttachment() is deprecated and there is no direct method to do so. In this blog, we will see how to add attachment to emails.

To understand this process, it’s recommened to get an Idea of some of the ZF2 components such as:

As createAttachment() method is no more available, we will override Magento\Framework\Mail\Message and create a class which will implement Magento\Framework\Mail\MailMessageInterface.

In this method, we will redifine/create some methods which would be responsible for different MIME parts which would be merged later before being sent. Let’s see some of the important ones:

Message::setBodyText() Method

public function setBodyText($content)
    $textPart = $this->partFactory->create();


    $this->parts[] = $textPart;

    return $this;

In this method, we are adding the text MIME part to the email and storing in $this->parts array.

Message::setBodyHtml() Method

public function setBodyHtml($content)
    $htmlPart = $this->partFactory->create();


    $this->parts[] = $htmlPart;

    return $this;

In this method, we are doing the same as above but we are setting the HTML part and storing in the same $this->parts array.

Message::setBodyAttachment() Method

public function setBodyAttachment($content, $fileName, $fileType)
    $attachmentPart = $this->partFactory->create();


    $this->parts[] = $attachmentPart;

    return $this;

Here we set the content of the file, then set a file type and specify its name. In addition, we set disposition. It’s necessary for the file to be treated as an attachment.

Above we’ve described all methods that help us to add mime parts to the message. But we also added to this class one more important method – Message::setPartsToBody().

Message::setPartsToBody() Method

public function setPartsToBody()
    $mimeMessage = $this->mimeMessageFactory->create();

    return $this;

This method is used to put all the pieces together.

Now, we will create a new class TransportBuilder which will extend the actual core class Magento\Framework\Mail\Template\TransportBuilder and instead of the core class, we will be using this new class.

TransportBuilder::addAttachment() Method

public function addAttachment($content, $fileName, $fileType)
    $this->message->setBodyAttachment($content, $fileName, $fileType);

    return $this;

Now, you can call this method while sending mail as used in this file.

Further, you can find the entire module here. GitHub

Magento 2 Console Command Sortcuts

While working on Magento 2.x, you often need to run several console commands which are actually very handy in terms of managing the things such as cache, upgrades, deploy modes, indexers etc. You can check the entire list of commands by running this command:

php bin/magento list

Well, typing the full long commands are not very pleasant if it has to be done multiple times. So, we can use shortcuts instead full commands. This feature comes due to the Symphony framework which is used by each console class that implement command line functionality. The use Symfony\Component\Console\Command component to implement command line features. You can learn more in the documentation of Symphony framework. You can use shortest unambiguous name intead of full name, e.g. s instead of setup.

Now, let’s see shortcuts for some of the commonly used Magento 2 console commands:

1. Cache Commands

php bin/magento cache:clean ==> php bin/magento c:c

php bin/magento cache:disable ==> php bin/magento c:d

php bin/magento cache:enable [cache_type] ==> php bin/magento c:e [cache_type]

php bin/magento cache:flush [cache_type] ==> php bin/magento c:f [cache_type]

php bin/magento cache:status ==> php bin/magento c:s

Where cache_type is the parameter in which you can pass one or more cache types separated by whitespaces, e.g.

php bin/magento c:c config layout

2. Indexer Commands

php bin/magento indexer:reindex ==> php bin/magento i:rei

php bin/magento indexer:info ==> php bin/magento i:i

php bin/magento indexer:status ==> php bin/magento i:sta

php bin/magento indexer:show-mode ==> php bin/magento i:sho

php bin/magento indexer:reset ==> php bin/magento i:res

You may pass parameters for particular indexer type as well.

3. Compile Command

php bin/magento setup:di:compile ==> php bin/magento s:di:c

4. Setup Upgrade Command

php bin/magento setup:upgrade ==> php bin/magento s:up

5. Static Content Deploy Command

php bin/magento setup:static-content:deploy ==> php bin/magento s:s:d

6. Module Management Commands

php bin/magento module:status ==> php bin/magento mo:s

php bin/magento module:disable Namespace_Module ==> php bin/magento mo:d Namespace_Module

php bin/magento module:enable Namespace_Module ==> php bin/magento mo:e Namespace_Module

php bin/magento module:uninstall Namespace_Module ==> php bin/magento m:u Namespace_Module

Magento 2 – How to Get Base URL, Media URL, Current URL, Base Path, Media Path

In this blog, both methods are demonstrated, using Dependency Injection and using ObjectManager

Using Dependency Injection

Here is the sample code. It has been used in a block class but you may use it in any class you want. We will be using three classes:

\Magento\Framework\Filesystem\DirectoryList and
as follows:

namespace Excellence\MagentoBlog\Block;

class DataBlock extends \Magento\Framework\View\Element\Template
    protected $_storeManager;
    protected $_urlInterface;
    protected $_dir;

    public function __construct(
        \Magento\Backend\Block\Template\Context $context,        
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\Filesystem\DirectoryList $dir,
        \Magento\Framework\UrlInterface $urlInterface,    
        array $data = []
    ) {
        $this->_storeManager = $storeManager;
        $this->_dir = $dir;
        $this->_urlInterface = $urlInterface;
        parent::__construct($context, $data);

     * This function prints all of the required data using:
     * \Magento\Store\Model\StoreManagerInterface
    public function getStoreManagerData()
        echo $this->_storeManager->getStore()->getId() . '<br />';
        Standard Function Call:

        $this->_storeManager->getStore()->getBaseUrl(Url type);
         * Possible URL types
        const URL_TYPE_LINK = 'link';
        const URL_TYPE_DIRECT_LINK = 'direct_link';
        const URL_TYPE_WEB = 'web';
        const URL_TYPE_MEDIA = 'media';
        const URL_TYPE_STATIC = 'static';
        const URL_TYPE_JS = 'js';
        // by default: URL_TYPE_LINK is returned

        echo $this->_storeManager->getStore()->getBaseUrl() . '<br />';        
        echo $this->_storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_WEB) . '<br />';
        echo $this->_storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_DIRECT_LINK) . '<br />';
        echo $this->_storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . '<br />';
        echo $this->_storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_STATIC) . '<br />';
        /* To get custom URL based on url key */
        echo $this->_storeManager->getStore()->getUrl('url_key') . '<br />';
        /* To get Current URL */
        echo $this->_storeManager->getStore()->getCurrentUrl(false) . '<br />';

        echo $this->_storeManager->getStore()->getBaseMediaDir() . '<br />';
        echo $this->_storeManager->getStore()->getBaseStaticDir() . '<br />';    

     * This function prints all of the required data using:
     * \Magento\Framework\UrlInterface
    public function getUrlInterfaceData()
        echo $this->_urlInterface->getCurrentUrl() . '<br />';
        echo $this->_urlInterface->getUrl() . '<br />';
        /* To get custom URL based on url key */
        echo $this->_urlInterface->getUrl('url_key') . '<br />';
        echo $this->_urlInterface->getBaseUrl() . '<br />';

     * This function prints all of the directory paths using:
     *  \Magento\Framework\Filesystem\DirectoryList
    public function getDirectoryPaths()
        echo $this->_dir->getRoot()."<br>"; // Output: /var/www/html/myproject

        echo $this->_dir->getPath('media')."<br>"; // Output: /var/www/html/myproject/pub/media

        echo $this->_dir->getPath('pub')."<br>"; // Output: /var/www/html/myproject/pub

        echo $this->_dir->getPath('static')."<br>"; // Output: /var/www/html/myproject/pub/static

        echo $this->_dir->getPath('var')."<br>"; // Output: /var/www/html/myproject/var

        echo $this->_dir->getPath('app')."<br>"; // Output: /var/www/html/myproject/app

        echo $this->_dir->getPath('etc')."<br>"; // Output: /var/www/html/myproject/app/etc

        echo $this->_dir->getPath('lib_internal')."<br>"; // Output: /var/www/html/myproject/lib/internal

        echo $this->_dir->getPath('lib_web')."<br>"; // Output: /var/www/html/myproject/lib/web

        echo $this->_dir->getPath('tmp')."<br>"; // Output: /var/www/html/myproject/var/tmp

        echo $this->_dir->getPath('cache')."<br>"; // Output: /var/www/html/myproject/var/cache

        echo $this->_dir->getPath('log')."<br>"; // Output: /var/www/html/myproject/var/log

        echo $this->_dir->getPath('session')."<br>"; // Output: /var/www/html/myproject/var/session

        echo $this->_dir->getPath('setup')."<br>"; // Output: /var/www/html/myproject/setup/src

        echo $this->_dir->getPath('di')."<br>"; // Output: /var/www/html/myproject/var/di

        echo $this->_dir->getPath('upload')."<br>"; // Output: /var/www/html/myproject/pub/media/upload

        echo $this->_dir->getPath('generation')."<br>"; // Output: /var/www/html/myproject/var/generation

        echo $this->_dir->getPath('view_preprocessed')."<br>"; // Output: /var/www/html/myproject/var/view_preprocessed

        echo $this->_dir->getPath('composer_home')."<br>"; // Output: /var/www/html/myproject/var/composer_home

        echo $this->_dir->getPath('html')."<br>"; // Output: /var/www/html/myproject/var/view_preprocessed/html

You can see more functions in following classes:

Using ObjectManager

Well, this approach is never recommended as you know that using ObjectManager is never recommended in Magento 2. Find more about this here.

Though, we will see some of the methods to get work done:

$objectManager =  \Magento\Framework\App\ObjectManager::getInstance();        
$appState = $objectManager->get('\Magento\Framework\App\State');
$storeManager = $objectManager->get('\Magento\Store\Model\StoreManagerInterface');
$store = $storeManager->getStore();
echo $store->getUrl('product/33'); echo '<br>';
echo $store->getCurrentUrl(); echo '<br>';
echo $store->getBaseUrl(); echo '<br>';
echo $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_WEB); echo '<br>';
echo $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA); echo '<br>';