We sacrifice by not doing any other technology, so that you get the best of Magento.

We sacrifice by not doing any other technology, so that you get the best of Magento.

    How to create customer attribute programmatically in magento2?

    For example, when we create a mobile number customer attribute in Magento 2,  we need to create a module to add new customer attribute in Magento2.

    Create a registration.php file to the following path
    app/code/Magemonkeys/CustomerAttribute/registration.php

    <?php
    MagentoFrameworkComponentComponentRegistrar::register(
        MagentoFrameworkComponentComponentRegistrar::MODULE,
        'Magemonkeys_CustomerAttribute',
        __DIR__
    );

    Create module.xml file to the following path  app/code/Magemonkeys/CustomerAttribute/etc/module.xml which define our module setup version to setup_module table.

    <?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="Magemonkeys_CustomerAttribute" setup_version="1.0.0">
        <sequence>
          <module name="Magento_Customer"/>
        </sequence>
      </module>
    </config>

    Then, we need to create an extension_attributes.xml file to the following path app/code/Magemonkeys/CustomerAttribute/etc/extension_attributes.xml

    which defines our mobile number customer attribute.

    Pass Classname in extension_attributes.xml as MagentoCustomerApiDataCustomerInterface because its a base Customer interface to create customer attributes in Magento2.

    Set attribute code as your customer attribute code and define type as a string.

    <?xml version="1.0" ?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
        <extension_attributes for="MagentoCustomerApiDataCustomerInterface">
            <attribute code="mobile" type="string"/>
        </extension_attributes>
    </config>

    For Create Customer attribute we need to define InstallData.php file to the following path app/code/Magemonkeys/CustomerAttribute/Setup/InstallData.php which adds an entry to our database for custom mobile number attribute.

    <?php
    
    namespace MagemonkeysCustomerAttributeSetup;
    
    use MagentoFrameworkSetupInstallDataInterface;
    use MagentoFrameworkSetupModuleContextInterface;
    use MagentoFrameworkSetupModuleDataSetupInterface;
    use MagentoCustomerModelCustomer;
    use MagentoCustomerSetupCustomerSetupFactory;
    
    class InstallData implements InstallDataInterface
    {
    
        private $customerSetupFactory;
    
        /**
         * Constructor
         *
         * @param MagentoCustomerSetupCustomerSetupFactory $customerSetupFactory
         */
        public function __construct(
            CustomerSetupFactory $customerSetupFactory
        ) {
            $this->customerSetupFactory = $customerSetupFactory;
        }
    
        /**
         * {@inheritdoc}
         */
        public function install(
            ModuleDataSetupInterface $setup,
            ModuleContextInterface $context
        ) {
            $customerSetup = $this->customerSetupFactory->create(['setup' => $setup]);
    
            $customerSetup->addAttribute(MagentoCustomerModelCustomer::ENTITY, 'mobile', [
                'type' => 'varchar', // type of attribute
                'label' => 'Mobile Number',
                'input' => 'text', // input type
                'source' => '',
                'required' => false, // if you want to required need to set true
                'visible' => true,
                'position' => 500, // position of attribute
                'system' => false,
                'backend' => ''
            ]);
            
            /* Specify which place you want to display customer attribute */
            $attribute = $customerSetup->getEavConfig()->getAttribute('customer', 'mobile')
            ->addData(['used_in_forms' => [
                    'adminhtml_customer',
                    'adminhtml_checkout',
                    'customer_account_create',
                    'customer_account_edit'
                ]
            ]);
            $attribute->save();
        }
    }

    Now Run the upgrade command to install our module using SSh from the root of your Magento instance.

    php bin/magento setup:upgrade
    php bin/magento setup:static-content:deploy -f
    php bin/magento indexer:reindex
    php bin/magento cache:flush

    Now you can check your new mobile number attribute at the admin panel.

    Go To, Customers -> All Customers -> Edit any Customer.

    How To Install Magento On Server?

    In this blog, we will show you the essential steps needed to install the latest Magento CE 2. This tutorial explains the installation of Magento software on your localhost. We have used a window environment only by using a wizard to install.

    It’s an easy process, so let’s get started With Magento Community Edition 2.0 Installation.

    Flow Of Content:
    a. Find the installation that suits your business requirements.
    b. Verify your prerequisites
    c. Install Magento
    Easy Installation: Install the Magento software using the
    Setup wizard
    Install optional sample data(Setup Wizard)
    Advanced Installation with more control:
    Install Magento software using the command line
    Install optional sample data (Command line)

    Choose How to Install the Magento Software:

    1. Effortless installation via a compressed software archive
    This installation does not have any command line.

    2. Download Magento 2.0
    Pick a package as per your business requirements.

    3. System requirements

    Before you start the installation, make sure that your system has the following requirements:

    i. Operating Systems: Linux Distributions like Debian, Ubuntu, RedHat Enterprise Linux(RHEL), CenOS, etc.

    ii. Apache 2.2 or later

    iii. PHP 5.5x or PHP 5.6x (Magento 2 does not support PHP 5.4)

    iv. Essential PHP extensions:

    • PDO/MySQL
    • mbstring
    • mcrypt
    • mhash
    • simplexml
    • curl
    • gd2, ImageMagick 6.3.7 (or later) or both
    • soap
    • intl
    • bc-math
    • openssl

    v. MySQL 5.6x

    vi. Mail Transfer Agent (MTA) or SMTP server

    Suggestions:

    • php_xdebug2.2.0 or later (development environments only; can have an adverse effect on performance)
    • PHPUnit (as a command-line tool) 4.1 or later

    4. Installation Magento 2.0

    Follow below-mentioned steps to install Magento 2.0 only after verifying your prerequisites:

    1: Upload package to your Root

    2. Create a DataBase

    You can create your database by going into PHPmyadmin  create database

    3. Let’s begin Magento installation

    Follow 7 steps for a seamless installation of Magento

    Open web browser and then navigate to the location of the Magento downloader.

    Step 1: Agree and Setup

    Start the setup by pressing on Agree and Setup Magento button.

    Step 2: Verify System requirements

    For flawless Magento installation, you will have to check your hosting settings, and if error warnings appear, then you must correct the errors by contacting your hosting provider.

    Step 3: Add a Database

    • Database Server Host: Enter localhost if your server is on the same host as your web server.
    • Input Database Server Username
    • Input Database Server Password: This is optional
    • Database Name: Enter the same name of MySQL database that you created in the Create Database section.
    • Table Prefix: This field is not mandatory; Magento installation will generate a random prefix.

    Step 4: Web Configuration

    • Your Store Address: This field requires the base URL for your store.
    • Magento Admin Address: input the base URL for the store’s Admin Panel (default value is admin)

    Step 5: Customize your store

    In this step, you can set the time zone, currency and language of your store. These fields can be modified anytime later in the admin dashboard.

    Step 6: Create Admin Account

    In order to access Magento backend, you need to create an administrator account.

    • New Username: Enter the owner’s admin account.
    • New Email: Enter the email address.
    • New Password: Set a password.
    • Confirm Password: Confirm the password.

    Step 7: Install & Finish

    Click on Install Now to begin the installation.

    Conclusion

    Now, that you have learned how to install Magento on the server, it’s time for you to have your Magento store up and running in no time.

    How to Upgrade Magento version from 2.3.2 to 2.3.5?

    We had a client who hired us for Magento upgrade service. We migrated his store to Magento 2 & perform a Magento version upgrade. As a part of the maintenance service, we did Magento 2.3 upgrade for him & upgraded the store to 2.3.5.

    If you want to upgrade the Magento version from 2.3.2 to 2.3.5, then follow the below upgrade steps using SSH.

    Note: Before running the below commands, please take a full backup of your current Magento website. It will help you to undo the current scenario if you face any issues during the future Magento 2 upgrade steps.

    Step 1: Set the Magento website in maintenance mode using the below command.

    - php bin/magento maintenance:enable

    Step 2: Take a backup of composer.json file placed in Magento root using the below command.

    - cp composer.json composer.json.bak

    Step 3: Remove the current installation setup folder by using the below command.

    - composer remove magento/product-community-edition --no-update

    Step 4: Set the version in which you want to upgrade in the below command.

    - composer require magento/product-community-edition=2.3.5 --no-update

    Step 5: Run the below command.

    - composer require --dev allure-framework/allure-phpunit:~1.2.0 friendsofphp/php-cs-fixer:~2.14.0 lusitanian/oauth:~0.8.10 magento/magento-coding-standard:~3.0.0 magento/magento2-functional-testing-framework:2.4.5 pdepend/pdepend:2.5.2 phpmd/phpmd:@stable phpunit/phpunit:~6.5.0 sebastian/phpcpd:~3.0.0 squizlabs/php_codesniffer:~3.4.0 --sort-packages --no-update

    Step 6: Also run the below command.

    - composer remove --dev sjparkinson/static-review fabpot/php-cs-fixer --no-update

    Step 7: Then, update the composer using the below command.

    - composer update

    Step 8: Run below mention Magento upgrade command.

    - php bin/magento setup:upgrade
    
    - php bin/magento cache:clean

    Step 9: Remove maintenance mode using the below command.

    - php bin/magento maintenance:disable

    That’s it. The Magento 2 upgrade is done.

    Now, you can check your site’s Magento version in the admin panel.  In case, if you’re looking for a professional Magento migration service to upgrade the Magento version then contact Mage Monkeys today.

    Multi Store Switcher not working while customer is logged in to front side – Magento 2.3.3

    Please Follow Below steps to resolved such error of store switcher :

    – Follow the below steps to resolve the switcher issue.

    Step 1: You need to override the following file of the vendor module as mentioned below.

    Override this File in your module :

    vendor/magento/module-store/etc/di.xml

    Step 2: Replace the following code :

     <type name="MagentoStoreModelStoreSwitcher"> 
         <arguments> 
             <argument name="storeSwitchers" xsi:type="array"> 
                 <item name="cleanTargetUrl" xsi:type="object">MagentoStoreModelStoreSwitcherCleanTargetUrl</item> 
                 <item name="manageStoreCookie" xsi:type="object">MagentoStoreModelStoreSwitcherManageStoreCookie</item> 
                 <item name="managePrivateContent" xsi:type="object">MagentoStoreModelStoreSwitcherManagePrivateContent</item> 
                 <item name="hashGenerator" xsi:type="object">MagentoStoreModelStoreSwitcherHashGenerator</item> 
             </argument> 
         </arguments> 
     </type>

    with

     <type name="MagentoStoreModelStoreSwitcher"> 
         <arguments> 
             <argument name="storeSwitchers" xsi:type="array"> 
                 <item name="cleanTargetUrl" xsi:type="object">MagentoStoreModelStoreSwitcherCleanTargetUrl</item> 
                 <item name="manageStoreCookie" xsi:type="object">MagentoStoreModelStoreSwitcherManageStoreCookie</item> 
                 <item name="managePrivateContent" xsi:type="object">MagentoStoreModelStoreSwitcherManagePrivateContent</item> 
             </argument> 
         </arguments> 
     </type>

    Clean the cache and You are done.

     

    How to show minicart in custom popup in magento2?

    By using below codes, you can display a mini cart in the custom popup, and you can also set your popup design as per your requirement.

    Step 1:  create default.xml file inside,

    appcodeMagemonkeysPopupCartviewfrontendlayout folder and add the below code:

    <?xml version="1.0"?>
    <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
        <update handle="checkout_cart_sidebar_item_renderers"/>
        <update handle="checkout_cart_sidebar_item_price_renderers"/>
        <update handle="checkout_cart_sidebar_total_renderers"/>
        <body>
            <referenceContainer name="content">
                <block name="custom_minicart" as="custom_minicart" template="Vendor_Extension::custompopupcart.phtml">
                    <arguments>
                        <argument name="jsLayout" xsi:type="array">
                            <item name="types" xsi:type="array"/>
                            <item name="components" xsi:type="array">
                                <item name="minicart_content" xsi:type="array">
                                    <item name="component" xsi:type="string">Magento_Checkout/js/view/minicart</item>
                                    <item name="config" xsi:type="array">
                                        <item name="template" xsi:type="string">Magento_Checkout/minicart/content</item>
                                    </item>
                                    <item name="children" xsi:type="array">
                                        <item name="subtotal.container" xsi:type="array">
                                            <item name="component" xsi:type="string">uiComponent</item>
                                            <item name="config" xsi:type="array">
                                                <item name="displayArea" xsi:type="string">subtotalContainer</item>
                                            </item>
                                            <item name="children" xsi:type="array">
                                                <item name="subtotal" xsi:type="array">
                                                    <item name="component" xsi:type="string">uiComponent</item>
                                                    <item name="config" xsi:type="array">
                                                        <item name="template" xsi:type="string">Magento_Checkout/minicart/subtotal</item>
                                                    </item>
                                                </item>
                                            </item>
                                        </item>
                                        <item name="extra_info" xsi:type="array">
                                            <item name="component" xsi:type="string">uiComponent</item>
                                            <item name="config" xsi:type="array">
                                                <item name="displayArea" xsi:type="string">extraInfo</item>
                                            </item>
                                        </item>
                                        <item name="promotion" xsi:type="array">
                                            <item name="component" xsi:type="string">uiComponent</item>
                                            <item name="config" xsi:type="array">
                                                <item name="displayArea" xsi:type="string">promotion</item>
                                            </item>
                                        </item>
                                    </item>
                                </item>
                            </item>
                        </argument>
                    </arguments>
                </block>
            </referenceContainer>
        </body>
    </page>

    Step 2: Next step should be about creating custompopupcart.phtml file inside appcodeMagemonkeysPopupCartviewfrontendtemplates folder and add the below code:

    <div style="display: none" id="popup-mpdal">
        <div id="minicart-content-wrapper" data-bind="scope: 'minicart_content'">
            <!-- ko template: getTemplate() --><!-- /ko -->
        </div>
    </div>
    <script>
        window.checkout = <?=  $block->getSerializedConfig() ?>;
    </script>
    <script type="text/x-magento-init">
        {
            "[data-block='minicart']": {
                "Magento_Ui/js/core/app": <?=  $block->getJsLayout() ?>
            },
            "*": {
                "Magento_Ui/js/block-loader": "<?= $block->getViewFileUrl('images/loader-1.gif') ?>"
            }
        }
        </script>
    <script>
        require(
            [
                'jquery',
                'Magento_Ui/js/modal/modal'
            ],
            function(
                $,
                modal
            ) {
                var options = {
                    type: 'popup',
                    responsive: true,
                    innerScroll: true,
                    buttons: [{
                        text: $.mage.__('Continue'),
                        click: function () {
                            this.closeModal();
                            $('#popup-mpdal').hide();
                        }
                    }]
                };
                $('#popup-mpdal').show();
                var popup = modal(options, $('#popup-mpdal'));
                $("#popup-mpdal").modal("openModal");
            }
        );
    </script>

    Step 3:  The final step is to refresh the Cache.

    How to add Edit and Remove product button in Order summary on Checkout page?

    The default Magento 2 does not provide Edit and Remove product button in Order summary on the checkout page. But, it provides on Cart page and Mini-cart.

    Follow the below instructions to set Edit and Remove product button Order summary on the checkout page.

    Override details.html file in your theme

    /app/design/frontend/[VendorName]/[theme]/Magento_Checkout/web/template/summary/item/details.html

    And add below code in this file

    <div class="primary">
        <a data-bind="attr: {href: getConfigUrl($parent.item_id),title: $t('Edit item')}" class="action edit">
            <span data-bind="i18n: 'Edit'"></span>
        </a>
    </div>
    <div class="secondary">
        <a href="#" data-bind="attr: {'data-post': getDataPost($parent.item_id),title: $t('Delete item')}" class="action delete">
            <span data-bind="i18n: 'Remove'"></span>
        </a>
    </div>

    Override details.js file in your theme

    /app/design/frontend/[VendorName]/[theme]/Magento_Checkout/web/js/view/summary/item/details.js

    define(
        [
            'uiComponent',
            'mage/url',
            'Magento_Customer/js/customer-data',
            'jquery',
            'ko',
            'underscore',
            'sidebar',
            'mage/translate'
        ],
        function (Component,url,customerData,$,ko, _) {
            "use strict";
            return Component.extend({
                defaults: {
                    template: 'Magento_Checkout/summary/item/details'
                },
                getValue: function(quoteItem) {
                    var itemId = elem.data('cart-item'),
                    itemQty = elem.data('item-qty');
                    return quoteItem.name;
                },
                getDataPost: function(itemId) { 
                    console.log(itemId);
                    var itemsData = window.checkoutConfig.quoteItemData;
                    var obj = {};
                    var obj = {
                        data: {}
                    };
    
                    itemsData.forEach(function (item) {
                        if(item.item_id == itemId) { 
                            var mainlinkUrl = url.build('checkout/cart/delete/');
                            //var baseUrl = url.build('checkout/cart/');
                            var baseUrl = url.build('checkout/');
                            console.log(mainlinkUrl);
                            obj.action = mainlinkUrl;
                            obj.data.id= item.item_id;
                            obj.data.uenc = btoa(baseUrl);
                        }
                    });
                    return JSON.stringify(obj);
                },
                getConfigUrl: function(itemId) { 
                    var itemsData = window.checkoutConfig.quoteItemData;
                    var configUrl = null;
                    var mainlinkUrl = url.build('checkout/cart/configure');
                    var linkUrl;
                    itemsData.forEach(function (item) {
                        var itm_id = item.item_id;
                        var product_id = item.product.entity_id;
                        if(item.item_id == itemId) { 
                            linkUrl = mainlinkUrl+"/id/"+itm_id+"/product_id/"+product_id;
                        }
                    });
                    if(linkUrl != null) {
                        return linkUrl;
                    }
                    else {
                        return '';
                    }
    
                }
            });
        }
    );

    Then run below commands.

    php bin/magento setup:upgrade
    php bin/magento setup:static-content:deploy
    php bin/magento cache:flush

    That’s all folks. Hope it worked for you.

    How to add custom pagination in custom collection?

    By default, Magento 2 provides the pagination facility for the product pages, category pages, etc. It helps in easy navigation. Without pagination, the page load time increases.

    The default Magento 2 does not provide pagination for a custom collection.

    To add pagination in Magento 2 with a custom collection

    create a block file in your module :

    <?php
    namespace MagemonkeyGeneralBlock;
    
    class Monthlyspecial extends MagentoFrameworkViewElementTemplate {
    
    private $_objectManager;
    
    public function __construct(MagentoCatalogBlockProductContext $context,
    MagentoFrameworkAppConfigScopeConfigInterface $scopeConfig,
    MagentoFrameworkObjectManagerInterface $objectmanager,
    array $data = []) {
    
    parent::__construct($context, $data);
    $this->_isScopePrivate = true;
    $this->_objectManager = $objectmanager;
    $this->scopeConfig = $scopeConfig;
    
    }
    protected function _prepareLayout()
    {
    parent::_prepareLayout();
    if ($this->getMonthlySpecial()) {
    $pager = $this->getLayout()->createBlock(
    'MagentoThemeBlockHtmlPager',
    'monthlyspecial.history.pager'
    )->setAvailableLimit(array(12=>12,24=>24,36=>36,48=>48,52=>52))
    ->setShowPerPage(true)->setCollection(
    $this->getMonthlySpecial()
    );
    $this->setChild('pager', $pager);
    $this->getMonthlySpecial()->load();
    }
    return $this;
    //return parent::_prepareLayout();
    }
    
    public function getPagerHtml()
    {
    return $this->getChildHtml('pager');
    }
    
    Public function getMonthlySpecial()
    {
    $page=($this->getRequest()->getParam('p'))? $this->getRequest()->getParam('p') : 1;
    $pageSize=($this->getRequest()->getParam('limit'))? $this->getRequest
    ()->getParam('limit') : 12;
    
    $cateinstance = $this->_objectManager->create('MagentoCatalogModelCategoryFactory');
    
    $allproduct = $cateinstance->create()->load(0)->getProductCollection()->addAttributeToSelect('*')
    ->addAttributeToFilter('manager_special', 0)
    ->addAttributeToFilter('email_special', 0)
    ->addAttributeToFilter('status', 1)
    ->addAttributeToFilter('visibility', 4)
    ->setOrder('price', 'ASC');
    
    $collection = $allproduct;
    $collection->setPageSize($pageSize);
    $collection->setCurPage($page);
    return $collection;
    }
    }

    create a view phtml file where you use pagination in your module

    Just call getPagerHTML() code as per shown below.

    <?php echo $this->getPagerHtml() ?>
    <?php
    
    $allproduct = $this->getMonthlySpecial();
    
    <div id="layer-product-list">
        <div class="toolbar toolbar-products">
            <div class="pages">
            <?php echo $this->getPagerHtml() ?>
            </div>
        </div>      
        <div class="category-products products wrapper grid products-grid">
        <?php foreach ($allproduct as $key => $productdata) {
        	//add code for your data in loop
        }
        ?>
        </div>
    </div>

     

     

     

    How to fix email attachment issue in magento2.3.3?

    Follow the below steps, and the email attachment will start working as it worked previously.

    First, you have to create a “di.xml” file inside your extension folder.

    app/code/Magemonkeys/EmailAttachment/etc

    <preference for="MagentoFrameworkMailTemplateTransportBuilder" type="MagemonkeysEmailAttachmentModelMailTemplateTransportBuilder" />

    Now, you have to create one more file “transportBuilder.php” inside your Template folder with the below code.

    app/code/Magemonkeys/EmailAttachment/Model/Mail/Template/

    <?php
    declare(strict_types=1);
    namespace MagemonkeysEmailAttachmentModelMailTemplate;
    use MagentoFrameworkAppTemplateTypesInterface;
    use MagentoFrameworkExceptionLocalizedException;
    use MagentoFrameworkExceptionMailException;
    use MagentoFrameworkMailEmailMessageInterface;
    use MagentoFrameworkMailEmailMessageInterfaceFactory;
    use MagentoFrameworkMailAddressConverter;
    use MagentoFrameworkMailExceptionInvalidArgumentException;
    use MagentoFrameworkMailMessageInterface;
    use MagentoFrameworkMailMessageInterfaceFactory;
    use MagentoFrameworkMailMimeInterface;
    use MagentoFrameworkMailMimeMessageInterfaceFactory;
    use MagentoFrameworkMailMimePartInterfaceFactory;
    use MagentoFrameworkMailTemplateFactoryInterface;
    use MagentoFrameworkMailTemplateSenderResolverInterface;
    use MagentoFrameworkMailTemplateInterface;
    use MagentoFrameworkMailTransportInterface;
    use MagentoFrameworkMailTransportInterfaceFactory;
    use MagentoFrameworkObjectManagerInterface;
    use MagentoFrameworkPhrase;
    use ZendMimeMime;
    use ZendMimePartFactory;
     
    /**
     * TransportBuilder
     *
     * @api
     * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
     * @since 100.0.2
     */
    class TransportBuilder extends MagentoFrameworkMailTemplateTransportBuilder
    {
        /**
         * Template Identifier
         *
         * @var string
         */
        protected $templateIdentifier;
     
        /**
         * Template Model
         *
         * @var string
         */
        protected $templateModel;
     
        /**
         * Template Variables
         *
         * @var array
         */
        protected $templateVars;
     
        /**
         * Template Options
         *
         * @var array
         */
        protected $templateOptions;
     
        /**
         * Mail Transport
         *
         * @var TransportInterface
         */
        protected $transport;
     
        /**
         * Template Factory
         *
         * @var FactoryInterface
         */
        protected $templateFactory;
     
        /**
         * Object Manager
         *
         * @var ObjectManagerInterface
         */
        protected $objectManager;
     
        /**
         * Message
         *
         * @var EmailMessageInterface
         */
        protected $message;
     
        /**
         * Sender resolver
         *
         * @var SenderResolverInterface
         */
        protected $_senderResolver;
     
        /**
         * @var TransportInterfaceFactory
         */
        protected $mailTransportFactory;
     
        /**
         * Param that used for storing all message data until it will be used
         *
         * @var array
         */
        private $messageData = [];
     
        /**
         * @var EmailMessageInterfaceFactory
         */
        private $emailMessageInterfaceFactory;
     
        /**
         * @var MimeMessageInterfaceFactory
         */
        private $mimeMessageInterfaceFactory;
     
        /**
         * @var MimePartInterfaceFactory
         */
        private $mimePartInterfaceFactory;
     
        /**
         * @var AddressConverter|null
         */
        private $addressConverter;
     
        protected $attachments = [];
     
        protected $partFactory;
     
        /**
         * TransportBuilder constructor
         *
         * @param FactoryInterface $templateFactory
         * @param MessageInterface $message
         * @param SenderResolverInterface $senderResolver
         * @param ObjectManagerInterface $objectManager
         * @param TransportInterfaceFactory $mailTransportFactory
         * @param MessageInterfaceFactory|null $messageFactory
         * @param EmailMessageInterfaceFactory|null $emailMessageInterfaceFactory
         * @param MimeMessageInterfaceFactory|null $mimeMessageInterfaceFactory
         * @param MimePartInterfaceFactory|null $mimePartInterfaceFactory
         * @param addressConverter|null $addressConverter
         * @SuppressWarnings(PHPMD.UnusedFormalParameter)
         * @SuppressWarnings(PHPMD.ExcessiveParameterList)
         */
        public function __construct(
            FactoryInterface $templateFactory,
            MessageInterface $message,
            SenderResolverInterface $senderResolver,
            ObjectManagerInterface $objectManager,
            TransportInterfaceFactory $mailTransportFactory,
            MessageInterfaceFactory $messageFactory = null,
            EmailMessageInterfaceFactory $emailMessageInterfaceFactory = null,
            MimeMessageInterfaceFactory $mimeMessageInterfaceFactory = null,
            MimePartInterfaceFactory $mimePartInterfaceFactory = null,
            AddressConverter $addressConverter = null
        ) {
            $this->templateFactory = $templateFactory;
            $this->objectManager = $objectManager;
            $this->_senderResolver = $senderResolver;
            $this->mailTransportFactory = $mailTransportFactory;
            $this->emailMessageInterfaceFactory = $emailMessageInterfaceFactory ?: $this->objectManager
                ->get(EmailMessageInterfaceFactory::class);
            $this->mimeMessageInterfaceFactory = $mimeMessageInterfaceFactory ?: $this->objectManager
                ->get(MimeMessageInterfaceFactory::class);
            $this->mimePartInterfaceFactory = $mimePartInterfaceFactory ?: $this->objectManager
                ->get(MimePartInterfaceFactory::class);
            $this->addressConverter = $addressConverter ?: $this->objectManager
                ->get(AddressConverter::class);
            $this->partFactory = $objectManager->get(PartFactory::class);
            parent::__construct($templateFactory, $message, $senderResolver, $objectManager, $mailTransportFactory, $messageFactory, $emailMessageInterfaceFactory, $mimeMessageInterfaceFactory,
                $mimePartInterfaceFactory, $addressConverter);
        }
     
        /**
         * Add cc address
         *
         * @param array|string $address
         * @param string $name
         *
         * @return $this
         */
        public function addCc($address, $name = '')
        {
            $this->addAddressByType('cc', $address, $name);
     
            return $this;
        }
     
        /**
         * Add to address
         *
         * @param array|string $address
         * @param string $name
         *
         * @return $this
         * @throws InvalidArgumentException
         */
        public function addTo($address, $name = '')
        {
            $this->addAddressByType('to', $address, $name);
     
            return $this;
        }
     
        /**
         * Add bcc address
         *
         * @param array|string $address
         *
         * @return $this
         * @throws InvalidArgumentException
         */
        public function addBcc($address)
        {
            $this->addAddressByType('bcc', $address);
     
            return $this;
        }
     
        /**
         * Set Reply-To Header
         *
         * @param string $email
         * @param string|null $name
         *
         * @return $this
         * @throws InvalidArgumentException
         */
        public function setReplyTo($email, $name = null)
        {
            $this->addAddressByType('replyTo', $email, $name);
     
            return $this;
        }
     
        /**
         * Set mail from address
         *
         * @param string|array $from
         *
         * @return $this
         * @throws InvalidArgumentException
         * @see setFromByScope()
         *
         * @deprecated 102.0.1 This function sets the from address but does not provide
         * a way of setting the correct from addresses based on the scope.
         */
        public function setFrom($from)
        {
            return $this->setFromByScope($from);
        }
     
        /**
         * Set mail from address by scopeId
         *
         * @param string|array $from
         * @param string|int $scopeId
         *
         * @return $this
         * @throws InvalidArgumentException
         * @throws MailException
         * @since 102.0.1
         */
        public function setFromByScope($from, $scopeId = null)
        {
            $result = $this->_senderResolver->resolve($from, $scopeId);
            $this->addAddressByType('from', $result['email'], $result['name']);
     
            return $this;
        }
     
        /**
         * Set template identifier
         *
         * @param string $templateIdentifier
         *
         * @return $this
         */
        public function setTemplateIdentifier($templateIdentifier)
        {
            $this->templateIdentifier = $templateIdentifier;
     
            return $this;
        }
     
        /**
         * Set template model
         *
         * @param string $templateModel
         *
         * @return $this
         */
        public function setTemplateModel($templateModel)
        {
            $this->templateModel = $templateModel;
            return $this;
        }
     
        /**
         * Set template vars
         *
         * @param array $templateVars
         *
         * @return $this
         */
        public function setTemplateVars($templateVars)
        {
            $this->templateVars = $templateVars;
     
            return $this;
        }
     
        /**
         * Set template options
         *
         * @param array $templateOptions
         * @return $this
         */
        public function setTemplateOptions($templateOptions)
        {
            $this->templateOptions = $templateOptions;
     
            return $this;
        }
     
        /**
         * Get mail transport
         *
         * @return TransportInterface
         * @throws LocalizedException
         */
        public function getTransport()
        {
            try {
                $this->prepareMessage();
                $mailTransport = $this->mailTransportFactory->create(['message' => clone $this->message]);
            } finally {
                $this->reset();
            }
     
            return $mailTransport;
        }
     
        /**
         * Reset object state
         *
         * @return $this
         */
        protected function reset()
        {
            $this->messageData = [];
            $this->templateIdentifier = null;
            $this->templateVars = null;
            $this->templateOptions = null;
            return $this;
        }
     
        /**
         * Get template
         *
         * @return TemplateInterface
         */
        protected function getTemplate()
        {
            return $this->templateFactory->get($this->templateIdentifier, $this->templateModel)
                ->setVars($this->templateVars)
                ->setOptions($this->templateOptions);
        }
     
        /**
         * Prepare message.
         *
         * @return $this
         * @throws LocalizedException if template type is unknown
         */
        protected function prepareMessage()
        {
            $template = $this->getTemplate();
            $content = $template->processTemplate();
            switch ($template->getType()) {
                case TemplateTypesInterface::TYPE_TEXT:
                    $part['type'] = MimeInterface::TYPE_TEXT;
                    break;
     
                case TemplateTypesInterface::TYPE_HTML:
                    $part['type'] = MimeInterface::TYPE_HTML;
                    break;
     
                default:
                    throw new LocalizedException(
                        new Phrase('Unknown template type')
                    );
            }
            $mimePart = $this->mimePartInterfaceFactory->create(['content' => $content]);
            $parts = count($this->attachments) ? array_merge([$mimePart], $this->attachments) : [$mimePart];
            $this->messageData['body'] = $this->mimeMessageInterfaceFactory->create(
                ['parts' => $parts]
            );
     
            $this->messageData['subject'] = html_entity_decode(
                (string)$template->getSubject(),
                ENT_QUOTES
            );
            $this->message = $this->emailMessageInterfaceFactory->create($this->messageData);
     
            return $this;
        }
     
        /**
         * Handles possible incoming types of email (string or array)
         *
         * @param string $addressType
         * @param string|array $email
         * @param string|null $name
         *
         * @return void
         * @throws InvalidArgumentException
         */
        private function addAddressByType(string $addressType, $email, ?string $name = null): void
        {
            if (is_string($email)) {
                $this->messageData[$addressType][] = $this->addressConverter->convert($email, $name);
                return;
            }
            $convertedAddressArray = $this->addressConverter->convertMany($email);
            if (isset($this->messageData[$addressType])) {
                $this->messageData[$addressType] = array_merge(
                    $this->messageData[$addressType],
                    $convertedAddressArray
                );
            }
        }
     
        /**
         * @param string|null $content
         * @param string|null $fileName
         * @param string|null $fileType
         * @return TransportBuilder
         */
        public function addAttachment(?string $content, ?string $fileName, ?string $fileType)
        {
            $attachmentPart = $this->partFactory->create();
            $attachmentPart->setContent($content)
                ->setType($fileType)
                ->setFileName($fileName)
                ->setDisposition(Mime::DISPOSITION_ATTACHMENT)
                ->setEncoding(Mime::ENCODING_BASE64);
            $this->attachments[] = $attachmentPart;
     
            return $this;
        }
    }

    Lastly, we have to create a call to the file as shown below.

    $this->transportBuilder->addAttachment($content, $fileName, 'application/pdf');

    That’s it. Now your email attachment issue should get resolved.

     

    How to add multiple product attribute sets programmatically in Magento 2?

    Magento provides the add product attribute set from the backend, but there is no way to add multiple attribute sets at once because, in the backend, we have to add one by one, so here I’m sharing the script for adding numerous sets at once.

    Here is the script which is directly use from Magento root path:

    <?php
    
    use MagentoFrameworkAppBootstrap;
    
    require __DIR__ . '/app/bootstrap.php';
    $params = $_SERVER;
    $bootstrap = Bootstrap::create(BP, $params);
    $obj = $bootstrap->getObjectManager();
    $state = $obj->get('MagentoFrameworkAppState');
    $state->setAreaCode('frontend');
    
    $objectManager = MagentoFrameworkAppObjectManager::getInstance(); 
    $resourceConnection = $objectManager->create('MagentoFrameworkAppResourceConnection');
    $attributeSet = $objectManager->create('MagentoEavModelEntityAttributeSet');
    $entity_type = $objectManager->create('MagentoEavModelEntityType');
    $productFactory = $objectManager->create('MagentoCatalogModelProductFactory');
    $setsArray = array("Cup", "Size", "BandSize", "Color"); //You have to put here your require attribute sets
    if (!empty($setsArray)) {
        $sortOrder = 200;
        foreach ($setsArray as $checkSet) {
            $connection = $resourceConnection->getConnection();
            $select = "SELECT * from eav_attribute_set WHERE attribute_set_name = '" . $checkSet . "'";
            $result = $connection->fetchAll($select);
            if (count($result) == 0) {
                $entityType = $entity_type->loadByCode('catalog_product');
                $defaultSetId = $productFactory->create()->getDefaultAttributeSetid();
                $data = [
                    'attribute_set_name' => $checkSet,
                    'entity_type_id' => $entityType->getId(),
                    'sort_order' => $sortOrder,
                ];
    
                $attributeSet->setData($data);
                $attributeSet->validate();
                $attributeSet->save();
                $attributeSet->initFromSkeleton($defaultSetId);
                $attributeSet->save();
            }
            $sortOrder++;
        }
    
        echo 'Attribute Sets Process Finished';
    }

    First, prepare the above script in any PHP file of your Magento root then run that PHP file by CLI, and script execution will be started.

    After finishing the file execution you can clean the Magento cache and see the result in the backend. All attribute sets will get successfully added.

     

    How to Remove cart item Automatically after 30 Minutes in Magento2?

    Step 1: create a “Registration.php” file inside our extension at the following path.

    Path: appcodeMagemonkeysRemovecart

    <?php
    MagentoFrameworkComponentComponentRegistrar::register(
        MagentoFrameworkComponentComponentRegistrar::MODULE,
        'Magemonkeys_Removecart',
        __DIR__
    );

    Step 2: After that,  create a “Module.xml” file inside extension etc folder. appcodeMagemonkeysRemovecartetc

    <?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="Magemonkeys_Removecart" setup_version="1.0.0" schema_version="1.0.0">
        </module>
    </config>

    Step 3: After that, create “crontab.xml” file inside extension etc folder. appcodeMagemonkeysRemovecartetc

    <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="removecart" instance="MagemonkeysRemovecartCronRemovecart" method="getItemData">
                <schedule>* * * * *</schedule>
            </job>
        </group>
    </config>

    Step 4: Lastly, Create the “Removecart.php” file inside the Cron folder of extension. appcodeMagemonkeysRemovecartCron

    <?php
    namespace MagemonkeysRemovecartCron;
    
    class Removecart {
    
        /**
         * @var MagentoQuoteModelQuoteRepository
         */
        protected $quoteRepository;
    
        /**
         * @var MagentoQuoteModelResourceModelQuoteCollectionFactory
         */
        protected $quoteCollectionFactory;
    
        public function __construct(
            MagentoQuoteModelResourceModelQuoteCollectionFactory $quoteCollectionFactory,
            MagentoQuoteModelQuoteRepository $quoteRepository
        ) {
    
            $this->quoteCollectionFactory = $quoteCollectionFactory;
            $this->quoteRepository = $quoteRepository;
        }
        public function getItemData()
        {
            $fromTime = new DateTime('now', new DateTimezone('UTC'));
            $fromTime->sub(DateInterval::createFromDateString('30 minutes'));
    
            $fromDate = $fromTime->format('Y-m-d H:i:s');
            $quoteCollection = $this->quoteCollectionFactory->create();
    
            $quoteCollection
                ->addFieldToFilter('created_at', ['lteq' => $fromDate]);
    
            if($quoteCollection->getSize() >0){
                foreach ($quoteCollection as $quote)
                {
                    $quoteFullObject = $this->quoteRepository->get($quote->getId());
                    $quoteFullObject->delete();
                }
            }
    
    
        }
    }

    Run below command in your command prompt

    php bin/magento cron:install

    php bin/magento cron:run

    Every 30 minutes, the cron is executed. If there is an item available in the cart, it will be then removed, automatically!