Install & Configure Varnish Cache for Magento 2

May 19, 2016  |  1 Comments  |  by Raj (MagePsycho)  |  Linux, Magento 2

The performance of a website is always the key factor for the higher conversion rate. Fortunately, Magento 2 (both CE & EE) comes by default with the support for FPC (Full Page Caching), Varnish & Redis to make your store fly.
In this tutorial we will be discussing brief info about Varnish, it’s installation and configuration so bear with me.

Magento-2-Banner

Magento 2 supports Varnish versions 3.0.5 or later or any Varnish 4.x version.
And Magento team strongly recommends using Varnish in production as the built-in full-page caching (to either the file system or database) is much slower than Varnish, and Varnish is designed to accelerate HTTP traffic.
varnishcache_rgb-gimp2-alpha

Varnish Cache is an open source web application accelerator (also referred to as an HTTP accelerator or caching HTTP reverse proxy). Varnish stores (or caches) files or fragments of files in memory; this enables Varnish to reduce the response time and network bandwidth consumption on future, equivalent requests. Unlike web servers like Apache and Nginx, Varnish was designed for use exclusively with the HTTP protocol.

Assumption

We have carried out the Varnish installation in the following enviroment:

  • Ubuntu – 14.04 LTS
  • Nginx – 1.9.6
  • MySQL – 5.6.28
  • PHP – 5.6.20 (but PHP 7 is recommended)
  • Magento EE – 2.0.5

Installation

Run the following series of command as a root user (sudo su).

apt-get install apt-transport-https
curl https://repo.varnish-cache.org/GPG-key.txt | apt-key add -
echo "deb https://repo.varnish-cache.org/ubuntu/ trusty varnish-4.1" \
     >> /etc/apt/sources.list.d/varnish-cache.list
apt-get update
apt-get install varnish

If everything goes right you should be able to see the Varnish version with:

varnishd -V

Configuration

Once Varnish is installed, you need to configure it and your web server(Nginx in our case).

Configure your Web Server(Nginx)

Configure your web server to listen on a port (say: 8080) other than the default port 80 because Varnish responds directly to incoming HTTP requests, not the web server.
For this add the ‘listen’ directive in ‘server’ block as:

server {
    listen 8080 default_server;
    server_name  your-mage2-store.dev;
    ...
}

to default nginx configuration file (generally located at /path/to/nginx/sites-enabled/default)

Configure Varnish Configuration

1. Modify Varnish System Configuration

vim /etc/default/varnish

And edit the file to have similar code:

START=yes

# Maximum number of open files (for ulimit -n)
NFILES=131072

# Maximum locked memory size (for ulimit -l)
# Used for locking the shared memory log in memory.  If you increase log size,
# you need to increase this number as well
MEMLOCK=82000

DAEMON_OPTS="-a :80 \
             -T localhost:6082 \
             -p http_resp_hdr_len=64000 \
             -f /etc/varnish/default.vcl \
             -S /etc/varnish/secret \
             -s malloc,256m"

2. Modify default.vcl
Make a backup of default one.

cp /etc/varnish/default.vcl /etc/varnish/default.vcl.bak
vim /etc/varnish/default.vcl

And edit the lines under ‘backend default’:

# Default backend definition. Set this to point to your content server.
backend default {
.host = "127.0.0.1";
.port = "8080";
}

Where

  • .host – fully qualified host name or IP address and listen port of the Varnish backend or origin server; that is, the server providing the content Varnish will accelerate. Typically, this is your web server.
  • .port – the web server’s listen port (8080 in this example)

Note:This is the minimal configuration. You need to use the configuration which you get from Magento 2’s Varnish Export (Ref – #3).

3. Configure Magento to use Varnish
Instead of manually editing default.vcl, Magneto 2 comes up with an export option for it.
First enable the Full Page Cache to use Varnish (Go to Admin > Stores > Configuration > Advanced > System > Full Page Cache), you will see as:
magepsycho-magento-2-varnish-cache
Save the settings and hit the Export VCL button (Varnish 3 or 4 as per your Varnish Version).
And use this default.vcl to replace the file in /etc/varnish/default.vcl

Finally, restart the Varnish & Nginx

service nginx restart
service varnish restart

Verification

I assume You have followed all the above steps (Installation & Configuration). Now lets check if Varnish cache server is taking into account for HTTP response or not.

Check if Varnish is listening to port 80
Run the following command:

netstat -tulpn | grep varnishd

varnishd-listing-toport-80

Verify contents in var/cache, var/page_cache folder is not regenerated
Since FPC is configured to serve the content from Varnish, once cleared, cache folders (var/cache, var/page_cache) should always be empty .

Verify the HTTP response headers
Load your Magento 2 Frontend and check the response from browser console, you will see similar as shown in the below screenshot:
magepsycho-varnish-http-response-headers

Or you can simply use CLI as:

curl -I http://your-mage2-store.dev/

And You will see some similar Varnish keywords.

Voila, you’re done. Let your store fly!
Please do comment or contact us if you have any issues regarding Varnish + Magento2 Installation & Configuration.

Assign group to the customer using dropdown or group code in Magento

January 5, 2016  |  No Comments  |  by Raj (MagePsycho)  |  Magento

If you are looking for functionality which allows customers to select their required customer group at registration & checkout either by using group dropdown or group code, then Customer Group Selector / Switcher Extension is for you.

Customer-Group-Selector

1. Associate Customer Group Using Dropdown

You can show the selected list of customer groups as dropdown at registration, checkout and my account edit pages. So that customer can select the group of their choice while registration . This feature can be very handy for your B2B stores.

1.1 Group Dropdown at Registration

It’s pretty straight forward to have customer group dropdown at registration, see the settings below:

Customer Group Selector Type - Dropdown

Registration – Customer Group Dropdown

Note: If you are using your own customized registration template (.phtml), then you can simply use the following code in your template:

<!-- Customer Group Field Widget -->
<li>
<?php
echo $this->getLayout()
->createBlock('magepsycho_customerregfields/customer_widget_type')
->setObject($this->getFormData())
->setIsEditPage(false)
->toHtml()
?>
</li>
<!-- //Customer Group Field Widget -->

1.2 Group Dropdown at Checkout

You can also enable customer group dropdown at Checkout Page which will be shown at Billing Address form (as shown below).
In order to enable it, just make ‘Is Enabled to Checkout?’ to Yes from the setting.

Customer Group Selector Type - Dropdown at Checkout Page

Checkout – Customer Group Dropdown

Note: If you are using custom billing address template (.phtml) file, then you can simply use the following code:

<!-- Customer Group Field Widget -->
<li>
<?php
echo $this->getLayout()
->createBlock('magepsycho_customerregfields/customer_widget_type')
->setObject($this->getQuote())
->setIsEditPage(false)
->setFieldIdFormat('billing:%s')
->setFieldNameFormat('billing[%s]')
->toHtml()
?>
</li>
<!-- //Customer Group Field Widget -->

1.3 Group Dropdown at My Account Edit Page

If you want the customer group to be editable from My Account Edit page, you can simply enable it from the extension settings (refer below screenshot)

Customer Group Selector Type - Dropdown - My Account Edit Page

My Account Edit Page – Customer Group Dropdown –


Note: If you have customized edit page, then you can use following snippet of code in order to show the field in the form:

<!-- Customer Group Field Widget -->
<li>
<?php
echo $this->getLayout()
->createBlock('magepsycho_customerregfields/customer_widget_type')
->setObject($this->getCustomer())
->setIsEditPage(true)
->toHtml()
?>
</li>
<!-- //Customer Group Field Widget -->

2. Associate Customer Group Using Code

If you want to associate customer group based on some code, then this option is for you. It allows customers to enter group code and the customer will be assigned to the group associated with the code.
For this you just have to chose ‘Group Selector Type’ to ‘Group Code’ and add group codes from settings (refer to the below screenshot).

Group Settings: Customer Group Selector Type - Group Code

Group Settings: Customer Group Selector Type – Group Code

2.1 Group Code at Registration

Similarly to group dropdown, you can have group code field at Registration, Checkout and My Account Edit Page.

Registration Page - Customer Group Code

Registration Page – Customer Group Code

2.2 Group Code at Checkout

Checkout Page - Customer Group Code

Checkout Page – Customer Group Code

2.3 Group Code at My Account Edit Page

My Account Edit Page - Customer Group Code (Editable)

My Account Edit Page – Customer Group Code (Editable)

Note: You can use the same code as above if you have want to include the group selector field at registration, checkout & account edit pages.

(This extension comes bundled with Store Restriction Pro & Custom Login Redirect Pro)

Create Custom Shipping Module in Magento 2

November 25, 2015  |  6 Comments  |  by Raj (MagePsycho)  |  Magento 2

As you know Magento 2 GA is already released on mid of November, 2015. Now the development of Magento 2 components is taking by storm and the developers are especially busy with porting their popular Magento 1 extensions.

In ours case, We are already into Magento 2 development: busy porting some of our popular Magento 1 Extensions and side by side learning new concepts introduced by Magento 2.

In this tutorial we will learn how to create a custom shipping module in Magento2 which is fairly easy as compared to CRUD & Payment modules.

Assumptions:
Namespace = MagePsycho
Module = Customshipping

Custom Shipping Module Development

1. Register the module
File: app/code/MagePsycho/Customshipping/etc/module.xml

<?xml version="1.0"?>
<!--
/**
 * @category   MagePsycho
 * @package    MagePsycho_Customshipping
 * @author     magepsycho@gmail.com
 * @website    http://www.magepsycho.com
 * @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
    <module name="MagePsycho_Customshipping" setup_version="1.0.0">
    </module>
</config>

2. Add System Configuration Settings
File: app/code/MagePsycho/Customshipping/etc/adminhtml/system.xml

<?xml version="1.0"?>
<!--
/**
 * @category   MagePsycho
 * @package    MagePsycho_Customshipping
 * @author     magepsycho@gmail.com
 * @website    http://www.magepsycho.com
 * @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Magento/Config/etc/system_file.xsd">
    <system>
        <section id="carriers" translate="label" type="text" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1">
            <group id="magepsycho_customshipping" translate="label" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
                <label>Custom Shipping</label>               
                <field id="active" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Enabled</label>
                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                </field>
                <field id="title" translate="label" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Title</label>
                </field>
                <field id="name" translate="label" type="text" sortOrder="3" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Method Name</label>
                </field>
                <field id="price" translate="label" type="text" sortOrder="4" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Shipping Cost</label>
                    <validate>validate-number validate-zero-or-greater</validate>
                </field>
                <field id="specificerrmsg" translate="label" type="textarea" sortOrder="80" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Displayed Error Message</label>
                </field>
                <field id="sallowspecific" translate="label" type="select" sortOrder="90" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Ship to Applicable Countries</label>
                    <frontend_class>shipping-applicable-country</frontend_class>
                    <source_model>Magento\Shipping\Model\Config\Source\Allspecificcountries</source_model>
                </field>
                <field id="specificcountry" translate="label" type="multiselect" sortOrder="91" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Ship to Specific Countries</label>
                    <source_model>Magento\Directory\Model\Config\Source\Country</source_model>
                    <can_be_empty>1</can_be_empty>
                </field>
                <field id="showmethod" translate="label" type="select" sortOrder="92" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Show Method if Not Applicable</label>
                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                </field>
                <field id="sort_order" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Sort Order</label>
                </field>
            </group>
        </section>
    </system>
</config>

3. Define shipping carrier model
File: app/code/MagePsycho/Customshipping/etc/config.xml

<?xml version="1.0"?>
<!--
/**
 * @category   MagePsycho
 * @package    MagePsycho_Customshipping
 * @author     magepsycho@gmail.com
 * @website    http://www.magepsycho.com
 * @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../Magento/Store/etc/config.xsd">
    <default>
        <carriers>
            <magepsycho_customshipping>
                <active>0</active>
                <sallowspecific>0</sallowspecific>
                <price>0</price>
                <model>MagePsycho\Customshipping\Model\Carrier\Customshipping</model>
                <name>Fixed</name>
                <title>Custom Shipping</title>
                <specificerrmsg>This shipping method is not available. To use this shipping method, please contact us.</specificerrmsg>
            </magepsycho_customshipping>
        </carriers>
    </default>
</config>

Notes: ‘config/default/carriers/model’ node is used to define Model class for Custom Shipping which will be responsible for handling the Shipping Charges.
In fact this file is also used to set default values for Shipping Settings.

4. Create shipping carrier model class
File: app/code/MagePsycho/Customshipping/Model/Carrier/Customshipping.php

<?php

namespace MagePsycho\Customshipping\Model\Carrier;

use Magento\Quote\Model\Quote\Address\RateRequest;

/**
 * @category   MagePsycho
 * @package    MagePsycho_Customshipping
 * @author     magepsycho@gmail.com
 * @website    http://www.magepsycho.com
 * @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 */
class Customshipping extends \Magento\Shipping\Model\Carrier\AbstractCarrier implements
	\Magento\Shipping\Model\Carrier\CarrierInterface
{
	/**
	 * @var string
	 */
	protected $_code = 'magepsycho_customshipping';

	/**
	 * @var bool
	 */
	protected $_isFixed = true;

	/**
	 * @var \Magento\Shipping\Model\Rate\ResultFactory
	 */
	protected $_rateResultFactory;

	/**
	 * @var \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory
	 */
	protected $_rateMethodFactory;

	/**
	 * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
	 * @param \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory
	 * @param \Psr\Log\LoggerInterface $logger
	 * @param \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory
	 * @param \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory
	 * @param array $data
	 */
	public function __construct(
		\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
		\Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
		\Psr\Log\LoggerInterface $logger,
		\Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory,
		\Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory,
		array $data = []
	) {
		$this->_rateResultFactory = $rateResultFactory;
		$this->_rateMethodFactory = $rateMethodFactory;
		parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);
	}

	/**
	 * @param RateRequest $request
	 * @return \Magento\Shipping\Model\Rate\Result
	 * @SuppressWarnings(PHPMD.UnusedLocalVariable)
	 */
	public function collectRates(RateRequest $request)
	{
		if (!$this->getConfigFlag('active')) {
			return false;
		}

		/** @var \Magento\Shipping\Model\Rate\Result $result */
		$result = $this->_rateResultFactory->create();

		$shippingPrice = $this->getConfigData('price');

		$method = $this->_rateMethodFactory->create();

		$method->setCarrier($this->_code);
		$method->setCarrierTitle($this->getConfigData('title'));

		$method->setMethod($this->_code);
		$method->setMethodTitle($this->getConfigData('name'));

		$method->setPrice($shippingPrice);
		$method->setCost($shippingPrice);
		
		$result->append($method);

		return $result;
	}

	/**
	 * Get allowed shipping methods
	 *
	 * @return array
	 */
	public function getAllowedMethods()
	{
		return [$this->_code => $this->getConfigData('name')];
	}
}

That’s all from development point of view.
Now you need to enable the module by running following series of commands(from root of your Magento 2 installation):

php bin/magento module:enable MagePsycho_Customshipping --clear-static-content
php bin/magento setup:upgrade

Go to the backend: System > Configuration > Sales > Shipping Methods > You will see new tab named ‘Custom Shipping’. And the settings looks like:

Magento 2 - Custom Shipping Method

Magento 2 – Custom Shipping Method

And the frontend looks like:

Magento2  - Custom Shipping at Checkout

Magento2 – Custom Shipping – Checkout

Magento2 - Custom Shipping - Checkout Summary

Magento2 – Custom Shipping – Checkout Summary

This module is available on GitHub.
In order to install the module from github:
Installation Using Composer

composer config repositories.magesycho-magento2-custom-shipping git git@github.com:MagePsycho/magento2-custom-shipping.git
composer require magepsycho/magento2-custom-shipping:dev-master

Installation Using Zip
Download the zip file, extract & upload the files to path: app/code/MagePsycho/Customshipping/

After installation, don’t forget to enable the Module as described above.

Please do comment below if you have any queries regarding Shipping Module development in Magento 2.
Happy Magento 2 Coding!

Install Magento 2 module from github or bitbucket repository using composer

October 30, 2015  |  No Comments  |  by Raj (MagePsycho)  |  Magento 2

In previous article, we discussed about How to install Magento 2 on MEMP (Mac OS X + Nginx + MySQL + PHP-FPM) stack using Composer

In this article we will discuss on How to install Magento 2 modules from any github or bitbucket repositories.

Let’s say we have Easy Template Path Hints (a Magento 2 module used for triggering the template path hints on the fly) on github.

Install Module

In order to install the Easy Template Path Hints Module from Github, run the following commands:

composer config repositories.magesycho-magento2-easy-template-path-hints git git@github.com:MagePsycho/magento2-easy-template-path-hints.git
composer require magepsycho/magento2-easy-template-path-hints:dev-master

Breakdown

1. Registering the module git repository

composer config repositories.magesycho-magento2-easy-template-path-hints git git@github.com:MagePsycho/magento2-easy-template-path-hints.git

Composer config repository command syntax:

composer config repositories.<unique-repo-name> <vcs-type> <vcs-url-https-or-sshl>

Composer will register a new repository to composer.json (under “repositories” node). Updated composer.json looks like:

{  
  "repositories": {
    "magesycho-magento2-easy-template-path-hints": {
      "type": "git",
      "url": "git@github.com:MagePsycho/magento2-easy-template-path-hints.git"
    }
  }
}

2. Registering the module package itself

composer require magepsycho/magento2-easy-template-path-hints:dev-master

Composer require command syntax:

composer require <vendor>/<package>:dev-<branch>

This will add new dependent package under node “require” as:

{
  "name": "magento/magento2ce",
  "description": "Magento 2 (Community Edition)",
  "type": "project",
  "require": {
    "magepsycho/magento2-easy-template-path-hints": "dev-master"
  }
}

followed by Module installation from the repo.

Install Magento 2 Module from Github

Install Magento 2 Module from Github

Few Notes:
This approach will only work for the modules which has been packaged with composer.json
Please read more on Packaging a Magento 2 Module

If you are loading a package from VCS repository (git, svn etc.), version should be a branch name prefixed with ‘dev-‘ else you may get error like

The requested package magepsycho/magento2-easy-template-path-hints could not be found in any version, there may be a typo in the package name.

Source: https://getcomposer.org/doc/05-repositories.md#vcs

Enable Module

After the module has been downloaded from git repository, Module needs to be enabled.
1. Disable the cache under System->Cache Management
2. Run following Commands

php bin/magento module:enable MagePsycho_Easypathhints --clear-static-content
php bin/magento setup:upgrade

Go to Admin menu > Stores > Configuration, you will be able to see the ‘Easy Template Path Hints’ settings:

Easy Template Path Hints - Backend Settings

Easy Template Path Hints – Backend Settings

Disable Module

In order to disable the Module, simply run:

php bin/magento module:disable --clear-static-content MagePsycho_Easypathhints

That’s all.
Isn’t that more easier/powerful way of installing, enabling or disabling the Magento 2 Modules than Magento 1?