Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
Magento Extensions Development
Magento Extensions Development

Magento Extensions Development: Click here to enter text.

eBook
$31.99 $35.99
Paperback
$43.99
Subscription
Free Trial
Renews at $19.99p/m

What do you get with Print?

Product feature icon Instant access to your digital copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Redeem a companion digital copy on all Print orders
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Table of content icon View table of contents Preview book icon Preview Book

Magento Extensions Development

Chapter 1. Introduction to Extension Development

Before I was a Magento Developer, I sold fair trade music from my own e-commerce website. Ten years ago, it was difficult to propose a technically new website to buy and download music from hundreds of artists; so much so that I spent all my time developing this part. There were a lot of other functionalities to develop, such as the customer relationship interface, the artist relationship interface, and much more; I said to myself that they would arrive later.

Later, my society, DiskOverMusic, began to organize concerts; what an exciting new challenge! Concert halls, technicians, lights, drinks, there were thousands of things to do for it. But how could I sell tickets to the millions of fans?.

Now, Magento exists and offers us a fantastic playground to develop everything our clients need in order to make the Internet innovative and secure. Standard development and the Magento framework allow you to develop clean, fast, and secure code to bring new functionalities to the community.

In our very first chapter, we will discuss the need for complex extensions in the Magento Marketplace. We will discover that marketable extensions fulfil a complex purpose.

Thanks to Magento, we will create TicketBlaster, a module which will enable a store owner to sell seated tickets to events at a venue.

Magento is an out of the box e-commerce platform with many features, such as catalog navigation, promotion rules, tax rules, reports, and order management, which enable the store owner to begin to sell his products. However, all this out of the box functionality does not allow him to differentiate his store from others, interface with third party web applications, and offer good quality marketing and social services to the customer, as well as—maybe the most important requirement—providing an answer to the specificities of the profession the store owner needs.

Thus, Magento's community, composed of hundreds of developers and editors, distribute a lot of free and paid complex extensions in the Magento Marketplace. The extensions cover usage in customer experience (gifts, social, and so on), site management (administration, automations, and so on), integrations (payment, shipping, gateways, and so on), marketing (ads, email marketing, SEO, and so on), tech utilities, and themes. We will explore the Marketplace in detail in Chapter 8. Optimization for Teamwork Development.

In this chapter, we will cover the following topics:

  • Creating an extension
  • Registering dependencies with Composer
  • Managing our work with Git source control

Getting started

This book assumes you have an intermediate knowledge of Magento development and installation. You will see many examples and screenshots of the Magento I use for this book; I use a local web server running with Apache (only) on an Ubuntu desktop OS.

The Magento I use is the latest beta version at the time of writing: Magento 2 C.E. version. 1.0.0-beta. That's why my local server is reachable at the following local address: http://magento2.local.com/.

My Magento admin panel is located at http://magento2.local.com/backoff.

Note

One of the first good practices is to use another admin panel URL, other than admin.

Obviously, this installation isn't recommended for a production environment, but can teach you where the main problems can appear with a web server that runs a Magento. And it is perfect for web development, because you are not limited by an Internet connection and you can immediately resolve problems.

Note

If you are interested in a production server installation, or if you have a development server in your organization, you can find a complete installation script at https://bitbucket.org/jeremie_blackbird/iams.

Creating an extension

When you want to create an extension, the first step is to think about its goal and functionalities. Take this important time to define and draft a prototype of the main functionalities and how they will be managed by the admin. For this step, you can use some tools available on the web, such as Proto.io, Balsamiq, or Moqups; they allow you to create and share prototypes that look and work like your extension should, but without code.

Note

Visit http://proto.io, http://balsamiq.com, and http://moqups.com to discover these useful tools.

Another step is to look at others extensions, in order to determine whether you are writing an already existing extension, that performs the same function as yours. It doesn't matter, but if this is the case, I recommend you make a better extension than the original!

Finally, open your favourite IDE and continue to read this chapter. Here, we will begin to create TicketBlaster, a module which will enables a store owner to sell seated tickets to events at a venue.

The files that handle our extension

In the following steps, we will create the files necessary to our extension:

  1. Create the extension structure by creating the following folder structure:
    • app/code/Blackbird
    • app/code/Blackbird/TicketBlaster
    • app/code/Blackbird/TicketBlaster/etc
  2. Register the extension by creating the module.xml file in the app/code/Blackbird/etc folder and add this content to it:
    <?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="Blackbird_TicketBlaster" setup_version="1.0.0" />
    </config>

    This code informs Magento that a module named TicketBlaster with the namespace Blackbird, located in the app/code/Blackbird folder can be loaded and activated.

    Note

    Blackbird is the namespace of the module; it will be visible to developers and integrators of the Magento on which it will be installed. Be sure to use a namespace which identifies you, and use this namespace for all your extensions.

  3. Open a terminal and change the directory to the Magento project root folder.
  4. Enable the module by running the two following commands:
    php bin/magento module:enable
    php bin/magento setup:upgrade
    
  5. Create the [extension_path]/registration.php file and add the following code:
    <?php
    /**
     * Copyright © 2015 Magento. All rights reserved.
     * See COPYING.txt for license details.
     */
    
    \Magento\Framework\Component\ComponentRegistrar::register(
        \Magento\Framework\Component\ComponentRegistrar::MODULE,
        'Blackbird_TicketBlaster',
        __DIR__
    );
  6. You should see mentions of your new module, as in the following screenshot:
    The files that handle our extension
  7. You can already check that your module is taken into account by Magento by connecting to the admin and navigating to Stores| Configuration | Advanced | Advanced | Disable Modules Output:
    The files that handle our extension

Note

Be careful: this Configuration menu just allows disabling the output of a module and does not deactivate it.

Creating a helper

A helper will (this is not a surprise) help you and the extension during development by providing functions that execute little parts of code, such as getting a configuration value, executing generic functions for the extension, or testing the time zone.

Create a Helper class of the extension by adding the following code into the Helper [extension_path]/Helper/Event.php:

Note

From this point, we shall use [extension_path] to represent the path of our extension, which is app/code/Blackbird/TicketBlaster.

<?php

namespace Blackbird\TicketBlaster\Helper;

classEvent extends \Magento\Framework\App\Helper\AbstractHelper
{

    /**
     * Create just a useful method for our extension
     * 
     * @return bool
     */
public function justAUsefulMethod(){
        // Real code here
        // ...
return true;
    }
}

Creating a controller

Now, we will create a controller class to handle several issues. In our case, we prepare this controller in order to list all events at a venue. Moreover, controllers can get a request from the browser with parameters and dispatch it to the models of our extension.

  1. Before coding our controller, we need to create a new XML configuration file, in order to declare the new route. Create the [extension_path]/etc/frontend/routes.xml file and add the following code:
    <?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
    <route id="events" frontName="events">
    <module name="Blackbird_TicketBlaster" />
    </route>
    </router>
    </config>
  2. Next, create the [extension_path]/Controller/Index/Index.php file and add the following code:
    <?php
    
    namespace Blackbird\TicketBlaster\Controller\Index;
    
    class Index extends \Magento\Framework\App\Action\Action
    {
        /** @var  \Magento\Framework\View\Result\Page */
    protected $resultPageFactory;
        /**
         * @param \Magento\Framework\App\Action\Context $context
         */
    public function __construct(\Magento\Framework\App\Action\Context $context,
                                    \Magento\Framework\View\Result\PageFactory $resultPageFactory)
        {
            $this->resultPageFactory = $resultPageFactory;
            parent::__construct($context);
        }
    
        /**
         * Event Index, shows a list of recent events.
         *
         * @return \Magento\Framework\View\Result\PageFactory
         */
    public function execute()
        {
    return $this->resultPageFactory->create();
        }
    }
  3. Upgrade your Magento instance by running the following command:
    php bin/magento setup:upgrade
    

    Note

    Every time you change anything about the configuration of your extension, you will have to run this command to force Magento to handle your updates.

  4. Verify that the URL is accessible by requesting http://MAGENTO_URL/events/index/index/:
    Creating a controller

    Note

    Controllers are called by Magento when a URL is requested regarding the parameters: events corresponds to the frontName value in routes.xml, index is the name of the directory placed in the Controller folder, and index is the name of the PHP file in the Index directory. We will discover later in this chapter how controllers process requests.

Digging into these simple files

You can create this first structure at the beginning of your project, but of course, your project needs will lead you to create some other functionalities we will cover later. For now, it's just a starter. Some extensions require only controllers, others only blocks and models. Just keep in mind this simple explanation:

  • Controllers handle frontend and backend requests. They can communicate their data to models if it's needed, and eventually display data to customers or administrators.
  • Models handle data, from controllers or from a database. They are the core of your extension, do the main job, and their cap abilities are greater.
  • Blocks are here to take charge of the views: every template (.phtml file) is handled by a block that contains every necessary method for displaying data.
  • Helpers get useful core functions and can be overloaded to add some useful methods.
  • XML files, which are in the etc folder, declare the module itself and every core business configuration of our extension, and can eventually define some default values for the configuration.
  • Files that are in the Setup folder are files that create or update database tables during the installation of the extension.

Every extension comes in a single and standalone package, which will always be located in app/code/<EditorName>. In any case, you can't place your code in app/code/Magento (the core folder), because it will be overwritten when Magento is upgraded.

While writing the names of controllers and actions, make sure that they are clear and recognizable, especially by you. Their name must describe what the code does.

You can now test by yourself!

Do not hesitate to read Magento's core code, which informs you about the structure of the modules and how files work together. Make tests by using var_dump() to display text and variable values.

Tip

During all your Magento development work, use debug logs and the developer mode. These two functionalities will help you a lot and save you a lot of time! Read the http://magento.com/blog/technical/logging-approach-magento-2 page for explanations about logging; we will use it often in the up coming chapters.

Managing our work with Git source control

Once the project has begun, it may be a good thing to take care of code revision and eventually collaboration with other developers.

Git is a distributed revision control system developed by Linus Torvalds in 2005, initially for Linux kernel development. It has begun to replace the Subversion (SVN) system in a lot of companies, thanks to its full-fledged repository and independence from network access and a distant server.

As soon as you start to work with other people and developers, the repository must be always available on the Internet. You have two choices to do this: the first is to create a Git repository on your own server (a private server in your organization, or a rented dedicated server), and the second is to use a service that provides a repository for you. In this recipe, we will register our code on Bitbucket.

Note

GitHub and Sourceforge provide the same services, but Bitbucket offers more free services and is fully integrated with other Atlassian services such as Hipchat or Jira. It is up to you to make your choice according to your needs and environments.

Bitbucket registration

Perform the following steps for Bitbucket registration:

  1. Sign up to Bitbucket (https://bitbucket.org) by following the instructions on the website:
    Bitbucket registration
  2. In the upper-right corner of any page, click on Create, and then click Create repository:
    Bitbucket registration
  3. Enter your repository name and choose whether your repository will be public or private.

    Tip

    Check This is a private repository if you want to hide your repository from the general public, so that only selected people can see it.

    Bitbucket registration
  4. That's it for Bitbucket. Keep this window open for future instructions.
    Bitbucket registration
  5. Go to your terminal and install Git on your computer by running the following command line:
    sudo apt-get install git
    

Committing our work

In the following step, we will commit our code to a new repository, and then we will push the repository to Bitbucket:

  1. Initialize an empty repository by going to your Magento source folder and running the following command:
    git init
    
  2. Check that your repository has been created and is empty:
    git status
    
  3. Create a .gitignore file in the root of the repository and add the following content to it:
    #Git ignore for extensions writing
    /app/code/Magento/*
    /dev/tests/
    /lib/
    [...]
    

    Note

    The source code can be found in the by-chapter branch of the Git repository, in the Chapter1 folder.

  4. Verify that the .gitignore file is taken into account by running git status again:
    git status
    
    Committing our work
  5. You can see that only .gitignore is taken into account by Git.

    Note

    What happened? In fact, in a Magento project, especially with Magento CE, the source files are always available online and are the same for all. That's why you can presume that each of your collaborators first, and every client next, will run Magento. This is your code, it is unique and important, and that's why your code is the only thing to keep in your repository. Note for later: if you need to add another folder in your repository, just remove the corresponding ignore line.

  6. Run the following commands to add and commit the .gitignore file:
    git add .gitignore
    git commit .gitignore -m "Ignoring all resources files"
    
  7. Now your repository needs to be filled with the files of our project. Repeat the operation for all the files the extension needs with the command git add <folder | filename>:
    git -f add app/code/Blackbird/
    

    Note

    Note the -f option, to force Git to add the file even if it is stored in an ignored folder. If you don't use this option, Git will inform you that it can't add the file.

  8. Commit your additions:
    git commit -m "Adding the first extension files"
  9. Link your repository to the Bitbucket repository:
    git remote add originhttps://YOUR_USERNAME@bitbucket.org/blackbirdagency/ticket-blaster.git
    

    Tip

    This line is to modify your repository configuration.

  10. Finally, send the files and commit comments to Bitbucket by pushing the repository:
    git push -u origin master
    

    You will find your files by clicking on your repository name on https://bitbucket.org/, proving that the files have been sent and are available for other users.

    Note

    Take note not to send useless files.

    When you are creating an extension, the people who install your code will already have a Magento instance. It is very important to share only the extension files and not Magento and customizable files, which are already modified or installed by your client.

    That's why we have chosen to ignore almost all files by default, and to force a git add with the -f option when the file we need to share is placed in an ignored folder.

Discovering other Git servers!

There are others Git storage services online, such as https://github.com/ or https://sourceforge.net/, which offer different storage spaces and different public/private repo policies.

You can create your own private Git server too, which can be dedicated to your company or organization.

Registering dependencies

If your module wants to override some preference values, or just change the default work of a module, you must be able to specify that your configuration must be loaded after the one you override.

In another way, your module could use some class methods defined by other modules and extensions to do its work.

We will discover dependency registering, and we are going to use it for our extension.

Discovering Composer

Composer is a package manager for PHP that provides a standard format for managing dependencies and handling complete complex installation processes. Magento 2 decided to base all platform development on Composer because it's very powerful, open source, and can manage autoloading for third party libraries and code (such as our extension).

We will now see how to use it to manage our extension and its dependencies, which are now published in a public repository on Bitbucket:

  1. Create the [extension_path]/composer.json file and add the following code:
    {
        "name": "blackbird/ticketblaster",
        "description": "Ticket manager for events",
        "type": "magento2-module",
        "version": "1.0.0",
        "license": [
            "OSL-3.0",
            "AFL-3.0"
        ],
        "require": {
            "magento/magento-composer-installer": "*",
            "magento/catalog":"*"
        },
        "extra": {
            "map": [
                [
                    "*",
                    "Blackbird/TicketBlaster"
                ]
            ]
        },
        "authors": [
            {
                "name": "Blackbird",
                "homepage": "http://black.bird.eu/",
                "role": "Developer"
            }
        ]    
    }

    Note

    The dependencies for our extension are listed in the require key.

  2. Commit and push this file to your repository.
  3. Update the main Magento 2 composer.json file by running the following command:
    composer config repositories.blackbird vcs https://bitbucket.org/blackbirdagency/ticket-blaster
    
  4. Install the extension by running the following command:
    composer require blackbird/ticketblaster
    

    Note

    This method is only recommended when you develop private projects, which are not destined to be published. Use Packagist.org registering in other cases!

Discovering packagist

https://packagist.org/ is the main and default Composer repository. It aggregates public PHP packages installable with Composer.

When you use the Composer binary to add a new extension, the first thing that Composer will do is read the main composer.json file of Magento. If your required extension isn't listed or documented, it will ask https://packagist.org/ to get more information.

In the case of TicketBlaster, the extension is published in a public Git repository and we want to share it with everyone who needs it, even if they are not familiar with Composer. The simple way for all your clients to install the extension is by runnin

  1. Create an account on https://packagist.org.
  2. Once logged in, submit your package:
    Discovering packagist

    Note

    At this point, Magento 2 hasn't built its package sharing system; it will be launched in a few months.

    Discovering packagist
  3. Now you just have to run the following command to install your extension:
    composer require blackbird/ticketblaster
    

    Note

    Magento 2 uses Composer to package components and product editions. This book cannot look at all the powerful functionalities of Composer, so I recommend you read the detailed explanation on http://devdocs.magento.com/guides/v2.0/extension-dev-guide/composer-integration.html, which explains how Magento and Composer work together.

Designing TicketBlaster – the backend

We have now a basic extension structure and its dependencies. We must now think about TicketBlaster's structure and functionalities.

One of the most important things when you propose an extension for the community is that it contains the capacity to be configurable; the more you let your clients configure the extension, the more they will use it and the less likely they are to ask you whether something is available or customizable. Think of people who don't know about code development, and think of all the Magento developers who install your extension and don't have enough time to modify it.

We first need to create and manage the events. These events should be able to be created by the administrator and listed in the frontend. Furthermore, the events will have some characteristics, such as a name, a venue, and a date. You can obviously add any field you want for your event, and make it even better by creating a specific list of venues. The event will contain every ticket available for it.

The tickets (the product the customer can buy) will be based on Magento virtual products. But we are going to slightly modify the way we will use these by creating a new product type. This new product type will allow us to link the product to an event.

Creating the table for the events

Perform the following steps to create the table:

  1. Create the [extension_path]/Setup/ folder and then create the InstallSchema.php file. Add the following code:
    <?php
    
    namespace Blackbird\TicketBlaster\Setup;
    
    use Magento\Framework\Setup\InstallSchemaInterface;
    use Magento\Framework\Setup\ModuleContextInterface;
    use Magento\Framework\Setup\SchemaSetupInterface;
    use Magento\Framework\DB\Ddl\Table;
    
    class InstallSchema implements InstallSchemaInterface
    {
    [...]

    Note

    The source code can be found in the by-chapter branch of the Git repository, in the Chapter1 folder.

  2. Update the Magento database by running the following command:
    php bin/magento setup:upgrade
    

    Note

    If you want to manually relaunch the SQL installation, you have to delete the table added by the module and the line corresponding to TicketBlaster in the setup_module table, then execute the preceding command again.

  3. The extension and its table are installed! To verify this, open your database interface, for instance phpMyAdmin, and go to the setup_module table:
    Creating the table for the events

    Note

    This table is really important; Magento uses it to check whether an extension is installed, and which version.

    Creating the table for the events

Creating the backend view to list the events

Once the database table has been created, we need to allow the administrator to add, update, and remove events by using the backend.

The first thing we need is a menu to access to the listing of events, so let's create the menu:

  1. Create the [extension_path]/etc/adminhtml/menu.xml file and add the following code:
    <?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="Blackbird_TicketBlaster::ticketblaster" title="TicketBlaster" module="Blackbird_TicketBlaster" sortOrder="50" parent="Magento_Backend::content" resource="Blackbird_TicketBlaster::ticketblaster" />
    <add id="Blackbird_TicketBlaster::ticketblaster_event" title="Events" module="Blackbird_TicketBlaster" sortOrder="0" parent="Blackbird_TicketBlaster::ticketblaster" action="ticketblaster/event" resource="Blackbird_TicketBlaster::ticketblaster_event"/>
    </menu>
    </config>

    This simple code will add the menu in the global menu of Magento, in the Content main entry:

    Creating the backend view to list the events

    If you click on the menu item, you will be redirected to the dashboard, which is completely normal; we haven't created a controller to handle the request. That's what we are going to do now.

  2. Create the [extension_path]/etc/adminhtml/routes.xml file and add the following code:
    <?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="admin">
    <route id="ticketblaster" frontName="ticketblaster">
    <module name="Blackbird_TicketBlaster" before="Magento_Backend" />
    </route>
    </router>
    </config>
  3. Create a new folder, [extension_path]/Controller/Adminhtml/Event, in which you create the Index.php file. Then add the following code:
    <?php
    namespace Blackbird\TicketBlaster\Controller\Adminhtml\Event;
    
    use Magento\Backend\App\Action\Context;
    use Magento\Framework\View\Result\PageFactory;
    
    class Index extends \Magento\Backend\App\Action
    {
    const ADMIN_RESOURCE = 'Blackbird_TicketBlaster::ticketblaster_event';
    
        /**
         * @var PageFactory
         */
    protected $resultPageFactory;
    
        /**
         * @param Context $context
         * @param PageFactory $resultPageFactory
         */
    public function __construct(
            Context $context,
            PageFactory $resultPageFactory
        ) {
            parent::__construct($context);
            $this->resultPageFactory = $resultPageFactory;
        }
    
        /**
         * Index action
         *
         * @return \Magento\Backend\Model\View\Result\Page
         */
    public function execute()
        {
            /** @var \Magento\Backend\Model\View\Result\Page $resultPage */
            $resultPage = $this->resultPageFactory->create();
            $resultPage->setActiveMenu('Blackbird_TicketBlaster::ticketblaster_event');
            $resultPage->addBreadcrumb(__('Events'), __('Events'));
            $resultPage->addBreadcrumb(__('Manage Events'), __('Manage Events'));
            $resultPage->getConfig()->getTitle()->prepend(__('TicketBlaster Events'));
    
    return $resultPage;
        }
    }

    Tip

    Be careful: Magento and folder names are case-sensitive.

    The default execute() method generates the page. You will get a blank page if you click on the menu item; this is normal, and it is important to ensure you that you get this blank page before continuing. As long as you are redirected or something else, it means that your controller hasn't been read.

    Note

    From Step 4 and up to Step 20, there will be nothing to see in the backend. At most, you will have some errors and exceptions. So follow the steps strictly and test by reloading only at the end of the series.

  4. Create the [extension_path]/view/adminhtml/layout folder.
  5. Create the [extension_path]/view/adminhtml/layout/ticketblaster_event_index.xml file and add the following code:
    <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <update handle="styles"/>
    <body>
    <referenceContainer name="content">
    <uiComponent name="ticketblaster_event_listing"/>
    </referenceContainer>
    </body>
    </page>

    Note

    This code will declare the grid components to load. The filename has to correspond to <frontname>_<folder_in_controller>_<actionName>.

  6. Create the [extension_path]/view/adminhtml/ui_component/ folder.
  7. Create the [extension_path]/view/adminhtml/ui_component/ticketblaster_event_listing.xml file and add the following code:
    <?xml version="1.0" encoding="UTF-8"?>
    <listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    [...]

    Note

    The source code can be found in the by-chapter branch of the Git repository, in the Chapter1 folder.

    This code generates a grid with all these functionalities:

    • dataSource: Entity source collection, which allows the loading of all the items
    • filterSearch/filters: Adds all the filters to the grid
    • massaction: Mass action declarations to manipulate items
    • paging: Pagination configuration
    • columns: Lists all the columns we want to display and their configurations, such as type, draggable, align, label, and so on
  8. Create the [extension_path]/Controller/Adminhtml/Event/AbstractMassStatus.php file and add the following code:
    <?php
    
    namespace Blackbird\TicketBlaster\Controller\Adminhtml\Event;
    
    use Magento\Framework\Model\Resource\Db\Collection\AbstractCollection;
    use Magento\Framework\Controller\ResultFactory;
    
    /**
     * Class AbstractMassStatus
     */
    class AbstractMassStatus extends \Magento\Backend\App\Action
    {
    [...]

    Note

    The source code can be found in the by-chapter branch of the Git repository, in the Chapter1 folder.

    This code allows us to handle our mass actions in the status field.

  9. Create the [extension_path]/Controller/Adminhtml/Event/MassDisable.php file and add the following code:
    <?php
    
    namespace Blackbird\TicketBlaster\Controller\Adminhtml\Event;
    
    use Blackbird\TicketBlaster\Controller\Adminhtml\Event\AbstractMassStatus;
    
    /**
     * Class MassDisable
     */
    class MassDisable extends AbstractMassStatus
    {
        /**
         * Field id
         */
    const ID_FIELD = 'event_id';
    
        /**
         * Resource collection
         *
         * @var string
         */
    protected $collection = 'Blackbird\TicketBlaster\Model\Resource\Event\Collection';
    
        /**
         * Event model
         *
         * @var string
         */
    protected $model = 'Blackbird\TicketBlaster\Model\Event';
    
        /**
         * Event disable status
         *
         * @var boolean
         */
    protected $status = false;
    }
  10. Create the [extension_path]/Controller/Adminhtml/Event/MassEnable.php file and add the following code:
    <?php
    
    namespace Blackbird\TicketBlaster\Controller\Adminhtml\Event;
    
    use Blackbird\TicketBlaster\Controller\Adminhtml\Event\AbstractMassStatus;
    
    /**
     * Class MassEnable
     */
    class MassEnable extends AbstractMassStatus
    {
        /**
         * Field id
         */
    const ID_FIELD = 'event_id';
    
        /**
         * Resource collection
         *
         * @var string
         */
    protected $collection = 'Blackbird\TicketBlaster\Model\Resource\Event\Collection';
    
        /**
         * Event model
         *
         * @var string
         */
    protected $model = 'Blackbird\TicketBlaster\Model\Event';
    
        /**
         * Event enable status
         *
         * @var boolean
         */
    protected $status = true;
    }
  11. Create the [extension_path]/Controller/Adminhtml/Event/MassDelete.php file and add the following code:
    <?php
    
    namespace Blackbird\TicketBlaster\Controller\Adminhtml\Event;
    
    
    
    [...]

    Note

    The source code can be found in the by-chapter branch of the Git repository, in the Chapter1 folder.

    This file handles our mass action to delete several items at the same time.

  12. Create the [extension_path]/Controller/Adminhtml/Event/Delete.php file and add the following code:
    <?php
    
    namespace Blackbird\TicketBlaster\Controller\Adminhtml\Event;
    
    use Magento\Backend\App\Action;
    use Magento\TestFramework\ErrorLog\Logger;
    
    class Delete extends \Magento\Backend\App\Action
    {
    
        /**
         * @param Action\Context $context
         */
    public function __construct(Action\Context $context)
        {
            parent::__construct($context);
        }
    
        /**
         * {@inheritdoc}
         */
    protected function _isAllowed()
        {
    return $this->_authorization->isAllowed('Blackbird_TicketBlaster::ticketblaster_event_delete');
        }
    
        /**
         * Delete action
         *
         * @return \Magento\Framework\Controller\ResultInterface
         */
    public function execute()
        {
            /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
            $resultRedirect = $this->resultRedirectFactory->create();
            // check if we know what should be deleted
            $id = $this->getRequest()->getParam('event_id');
    if ($id) {
    try {
                    // init model and delete
                    $model = $this->_objectManager->create('Blackbird\TicketBlaster\Model\Event');
                    $model->load($id);
                    $model->delete();
                    // display success message
                    $this->messageManager->addSuccess(__('You deleted the event.'));
                    // go to grid
    return $resultRedirect->setPath('*/*/');
                } catch (\Exception $e) {
                    // display error message
                    $this->messageManager->addError($e->getMessage());
                    // go back to edit form
    return $resultRedirect->setPath('*/*/edit', ['event_id' => $id]);
                }
            }
            // display error message
            $this->messageManager->addError(__('We can\'t find a event to delete.'));
            // go to grid
    return $resultRedirect->setPath('*/*/');
        }
    }

    Note

    This code handles the deletion of one piece of content at a time. It will also be used in the edit page.

  13. Create the [extension_path]/Model/Event.php file and add the following code:
    <?php
    
    namespace Blackbird\TicketBlaster\Model;
    
    use Blackbird\TicketBlaster\Api\Data\EventInterface;
    use Magento\Framework\Object\IdentityInterface;
    
    class Event extends \Magento\Framework\Model\AbstractModel implements EventInterface, IdentityInterface
    {
    
    [...]

    Note

    The source code can be found in the by-chapter branch of the Git repository, in the Chapter1 folder.

    This code declares our model for handling our events.

  14. Create the [extension_path]/Model/Resource/Event.php file and add the following code:
    <?php
    
    namespace Blackbird\TicketBlaster\Model\Resource;
    
    class Event extends \Magento\Framework\Model\Resource\Db\AbstractDb
    {
        [...]

    Note

    The source code can be found in the by-chapter branch of the Git repository, in the Chapter1 folder.

    This class declares our link between the model and the database.

  15. Create the [extension_path]/Model/Resource/Event/Collection.php file and add the following code:
    <?php
    
    namespace Blackbird\TicketBlaster\Model\Resource\Event;
    
    class Collection extends \Magento\Framework\Model\Resource\Db\Collection\AbstractCollection
    {
        /**
         * Define resource model
         *
         * @return void
         */
    protected function _construct()
        {
            $this->_init('Blackbird\TicketBlaster\Model\Event', 'Blackbird\TicketBlaster\Model\Resource\Event');
        }
    
    }

    Note

    This code declares our collection of content of the Event type.

  16. Create the [extension_path]/Model/Event/Source/IsActive.php file and add the following code:
    <?php
    
    namespace Blackbird\TicketBlaster\Model\Event\Source;
    
    class IsActive implements \Magento\Framework\Data\OptionSourceInterface {
    
        /**
         * @var \Blackbird\TicketBlaster\Model\Event
         */
    protected $_event;
    
        /**
         * Constructor
         *
         * @param \Blackbird\TicketBlaster\Model\Event $event
         */
    public function __construct(\Blackbird\TicketBlaster\Model\Event $event) {
            $this->_event = $event;
        }
    
        /**
         * Get options
         *
         * @return array
         */
    public function toOptionArray() {
            $options[] = ['label' => '', 'value' => ''];
            $availableOptions = $this->_event->getAvailableStatuses();
    foreach ($availableOptions as $key => $value) {
                $options[] = [
                    'label' => $value,
                    'value' => $key,
                ];
            }
    return $options;
        }
    
    }

    Note

    This code lists the available statuses to be used in the grid.

  17. Create the [extension_path]/Api/Data/EventInterface.php file and add the following code:
    <?php
    
    namespace Blackbird\TicketBlaster\Api\Data;
    
    interface EventInterface
    {
    const EVENT_ID       = 'event_id';
    const URL_KEY       = 'url_key';
    const TITLE         = 'title';
    const VENUE         = 'venue';
    const EVENT_TIME       = 'event_time';
    const CREATION_TIME = 'creation_time';
    const UPDATE_TIME   = 'update_time';
    const IS_ACTIVE     = 'is_active';
    
    [...]

    Note

    The source code can be found in the by-chapter branch of the GIT repository, in the Chapter1 folder.

    This code lists all the methods available for an API to use in Magento. This part will be studied later in this book.

  18. Create the [extension_path]/etc/acl.xml file and add the following code:
    <?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation=" urn:magento:framework:Acl/etc/acl.xsd">
    <acl>
    <resources>
    <resource id="Magento_Backend::admin">
    <resource id="Magento_Backend::content">
    <resource id="Blackbird_TicketBlaster::ticketblaster" title="TicketBlaster" sortOrder="10" >
    <resource id="Blackbird_TicketBlaster::ticketblaster_event" title="Events" sortOrder="40">
    <resource id="Blackbird_TicketBlaster::ticketblaster_event_save" title="Save" sortOrder="10" />
    <resource id="Blackbird_TicketBlaster::ticketblaster_event_delete" title="Delete" sortOrder="20" />
    </resource>
    </resource>
    </resource>
    </resource>
    </resources>
    </acl>
    </config>

    Note

    This code lists all the permissions that can be used to restrict access for specific users in the admin panel.

  19. Create the [extension_path]/etc/di.xml file and add the following code:
    <?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="Blackbird\TicketBlaster\Api\Data\EventInterface" type="Blackbird\TicketBlaster\Model\Event" />
    <virtualType name="EventGridFilterPool" type="Magento\Framework\View\Element\UiComponent\DataProvider\FilterPool">
    <arguments>
    <argument name="appliers" xsi:type="array">
    <item name="regular" xsi:type="object">Magento\Framework\View\Element\UiComponent\DataProvider\RegularFilter</item>
    <item name="fulltext" xsi:type="object">Magento\Framework\View\Element\UiComponent\DataProvider\FulltextFilter</item>
    </argument>
    </arguments>
    </virtualType>
    <virtualType name="EventGridDataProvider" type="Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider">
    <arguments>
    <argument name="collection" xsi:type="object" shared="false">Blackbird\TicketBlaster\Model\Resource\Event\Collection</argument>
    <argument name="filterPool" xsi:type="object" shared="false">EventGridFilterPool</argument>
    </arguments>
    </virtualType>
    </config>

    Note

    This XML code declares some virtual types that provide filtered data to the grid.

  20. Create the [extension_path]/Ui/Component/Listing/Column/EventActions.php file and add the following code:
    <?php
    
    namespace Blackbird\TicketBlaster\Ui\Component\Listing\Column;
    
    use Magento\Framework\View\Element\UiComponent\ContextInterface;
    use Magento\Framework\View\Element\UiComponentFactory;
    use Magento\Ui\Component\Listing\Columns\Column;
    use Magento\Framework\UrlInterface;
    
    class EventActions extends Column
    {
        /** Url path */
    const TICKETBLASTER_URL_PATH_EDIT = 'ticketblaster/event/edit';
    const TICKETBLASTER_URL_PATH_DELETE = 'ticketblaster/event/delete';
    
        /** @var UrlInterface */
    protected $urlBuilder;
    
        /**
         * @var string
         */
    private $editUrl;
    
        /**
         * @param ContextInterface $context
         * @param UiComponentFactory $uiComponentFactory
         * @param UrlInterface $urlBuilder
         * @param array $components
         * @param array $data
         * @param string $editUrl
         */
    public function __construct(
            ContextInterface $context,
            UiComponentFactory $uiComponentFactory,
            UrlInterface $urlBuilder,
    array $components = [],
    array $data = [],
            $editUrl = self::TICKETBLASTER_URL_PATH_EDIT
        ) {
            $this->urlBuilder = $urlBuilder;
            $this->editUrl = $editUrl;
            parent::__construct($context, $uiComponentFactory, $components, $data);
        }
    
        /**
         * Prepare Data Source
         *
         * @param array $dataSource
         * @return void
         */
    public function prepareDataSource(array & $dataSource)
        {
    if (isset($dataSource['data']['items'])) {
    foreach ($dataSource['data']['items'] as & $item) {
                    $name = $this->getData('name');
    if (isset($item['event_id'])) {
                        $item[$name]['edit'] = [
                            'href' => $this->urlBuilder->getUrl($this->editUrl, ['event_id' => $item['event_id']]),
                            'label' => __('Edit')
                        ];
                        $item[$name]['delete'] = [
                            'href' => $this->urlBuilder->getUrl(self::TICKETBLASTER_URL_PATH_DELETE, ['event_id' => $item['event_id']]),
                            'label' => __('Delete'),
                            'confirm' => [
                                'title' => __('Delete "${ $.$data.title }"'),
                                'message' => __('Are you sure you wan\'t to delete a "${ $.$data.title }" record?')
                            ]
                        ];
                    }
                }
            }
        }
    }

    Note

    This class handles the action column of our grid by adding two links: delete and edit.

  21. Update Magento by running the following command:
    php bin/magento setup:upgrade
    

    Note

    This command, which we use a lot, is very important during Magento development: it clears the cache, upgrades the DB data and schema, generates interceptors and factories, and more!

    Hurrah! We can reload our page to see the grid:

    Creating the backend view to list the events

Summary

We now have all the necessary bases for writing an efficient extension that can already do a lot of work, such as saving data and managing it. It only lacks the ability for users to manage this data, and that's exactly what we will provide in the following chapter.

Note

All the code in this book is freely available here:

https://bitbucket.org/blackbirdagency/ticket-blaster.

Do not hesitate to download it, update it, and maybe even send new modifications!

Left arrow icon Right arrow icon
Download code icon Download Code

Key benefits

  • Deploy a complete real-world extension step by step
  • Construct your extension with the best and most up-to-date development methods
  • Learn about team working and code sharing

Description

Magento has been revealed as the best and the most popular open source e-commerce platform in the world, with about 250k+ online stores. Magento 2 is the most recent version of this awesome toolset: every new and modern development techniques are used to offer a real modular approach and powerful architecture. The book will support you in the writing of innovative and complex extensions. Starting from the beginning, we will cover how to set up a development environment that allows you to be really efficient in your functionality writing, including GIT registering and many other development tools. We then move on to provide a large overview of the best practices to scale your module in a high-load environment. After these foundations, you will see how to use test driven-development (TDD) and unit tests to handle your code. We then build a complex extension together, step by step, and internationally-ready. Next, you will find out how to protect the users’ data. Finally, we will take a look a publishing the extension on the new Magento Connect marketplace and how to protect your intellectual property. After you read this book, you will know everything you need to know to become an invaluable extension editor, whether it is for your customers’ needs or for your own requirements.

Who is this book for?

If you want to write a specific customization or a large new and full-featured extension on Magento 2, this book is intended for you. You must be an intermediate to professional-level developer in PHP to appreciate this book.

What you will learn

  • Build a fully-functional complex extension to add new functionality to Magento
  • Register your code with GIT and work with your team
  • Write new layouts and templates
  • Set up a fully configurable grid and forms in the backend
  • Create code unit tests and run them through TDD
  • Propose localized contents
  • Develop optimized extensions for a high-load environment
  • Publish extensions on the Magento Connect Marketplace
Estimated delivery fee Deliver to United States

Economy delivery 10 - 13 business days

Free $6.95

Premium delivery 6 - 9 business days

$21.95
(Includes tracking information)

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Jun 30, 2016
Length: 240 pages
Edition : 1st
Language : English
ISBN-13 : 9781783286775
Languages :
Concepts :
Tools :

What do you get with Print?

Product feature icon Instant access to your digital copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Redeem a companion digital copy on all Print orders
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Estimated delivery fee Deliver to United States

Economy delivery 10 - 13 business days

Free $6.95

Premium delivery 6 - 9 business days

$21.95
(Includes tracking information)

Product Details

Publication date : Jun 30, 2016
Length: 240 pages
Edition : 1st
Language : English
ISBN-13 : 9781783286775
Languages :
Concepts :
Tools :

Packt Subscriptions

See our plans and pricing
Modal Close icon
$19.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
$199.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts
$279.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total $ 124.97
Magento 2 Theme Design
$38.99
Magento 2 Developer's Guide
$41.99
Magento Extensions Development
$43.99
Total $ 124.97 Stars icon

Table of Contents

10 Chapters
1. Introduction to Extension Development Chevron down icon Chevron up icon
2. Deeper Extension Development Chevron down icon Chevron up icon
3. Best Practices and Scaling for the Web Chevron down icon Chevron up icon
4. Magento and Test-driven Development Chevron down icon Chevron up icon
5. Internationalization Chevron down icon Chevron up icon
6. Optimizing for Speed and Measuring Conversion Rates Chevron down icon Chevron up icon
7. Module Creation Etiquette Chevron down icon Chevron up icon
8. Optimization for Teamwork Development Chevron down icon Chevron up icon
9. Magento Marketplace Chevron down icon Chevron up icon
Index Chevron down icon Chevron up icon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is the digital copy I get with my Print order? Chevron down icon Chevron up icon

When you buy any Print edition of our Books, you can redeem (for free) the eBook edition of the Print Book you’ve purchased. This gives you instant access to your book when you make an order via PDF, EPUB or our online Reader experience.

What is the delivery time and cost of print book? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
What is custom duty/charge? Chevron down icon Chevron up icon

Customs duty are charges levied on goods when they cross international borders. It is a tax that is imposed on imported goods. These duties are charged by special authorities and bodies created by local governments and are meant to protect local industries, economies, and businesses.

Do I have to pay customs charges for the print book order? Chevron down icon Chevron up icon

The orders shipped to the countries that are listed under EU27 will not bear custom charges. They are paid by Packt as part of the order.

List of EU27 countries: www.gov.uk/eu-eea:

A custom duty or localized taxes may be applicable on the shipment and would be charged by the recipient country outside of the EU27 which should be paid by the customer and these duties are not included in the shipping charges been charged on the order.

How do I know my custom duty charges? Chevron down icon Chevron up icon

The amount of duty payable varies greatly depending on the imported goods, the country of origin and several other factors like the total invoice amount or dimensions like weight, and other such criteria applicable in your country.

For example:

  • If you live in Mexico, and the declared value of your ordered items is over $ 50, for you to receive a package, you will have to pay additional import tax of 19% which will be $ 9.50 to the courier service.
  • Whereas if you live in Turkey, and the declared value of your ordered items is over € 22, for you to receive a package, you will have to pay additional import tax of 18% which will be € 3.96 to the courier service.
How can I cancel my order? Chevron down icon Chevron up icon

Cancellation Policy for Published Printed Books:

You can cancel any order within 1 hour of placing the order. Simply contact customercare@packt.com with your order details or payment transaction id. If your order has already started the shipment process, we will do our best to stop it. However, if it is already on the way to you then when you receive it, you can contact us at customercare@packt.com using the returns and refund process.

Please understand that Packt Publishing cannot provide refunds or cancel any order except for the cases described in our Return Policy (i.e. Packt Publishing agrees to replace your printed book because it arrives damaged or material defect in book), Packt Publishing will not accept returns.

What is your returns and refunds policy? Chevron down icon Chevron up icon

Return Policy:

We want you to be happy with your purchase from Packtpub.com. We will not hassle you with returning print books to us. If the print book you receive from us is incorrect, damaged, doesn't work or is unacceptably late, please contact Customer Relations Team on customercare@packt.com with the order number and issue details as explained below:

  1. If you ordered (eBook, Video or Print Book) incorrectly or accidentally, please contact Customer Relations Team on customercare@packt.com within one hour of placing the order and we will replace/refund you the item cost.
  2. Sadly, if your eBook or Video file is faulty or a fault occurs during the eBook or Video being made available to you, i.e. during download then you should contact Customer Relations Team within 14 days of purchase on customercare@packt.com who will be able to resolve this issue for you.
  3. You will have a choice of replacement or refund of the problem items.(damaged, defective or incorrect)
  4. Once Customer Care Team confirms that you will be refunded, you should receive the refund within 10 to 12 working days.
  5. If you are only requesting a refund of one book from a multiple order, then we will refund you the appropriate single item.
  6. Where the items were shipped under a free shipping offer, there will be no shipping costs to refund.

On the off chance your printed book arrives damaged, with book material defect, contact our Customer Relation Team on customercare@packt.com within 14 days of receipt of the book with appropriate evidence of damage and we will work with you to secure a replacement copy, if necessary. Please note that each printed book you order from us is individually made by Packt's professional book-printing partner which is on a print-on-demand basis.

What tax is charged? Chevron down icon Chevron up icon

Currently, no tax is charged on the purchase of any print book (subject to change based on the laws and regulations). A localized VAT fee is charged only to our European and UK customers on eBooks, Video and subscriptions that they buy. GST is charged to Indian customers for eBooks and video purchases.

What payment methods can I use? Chevron down icon Chevron up icon

You can pay with the following card types:

  1. Visa Debit
  2. Visa Credit
  3. MasterCard
  4. PayPal
What is the delivery time and cost of print books? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela