Latest posts

Magento 2: How to get admin panel URL in a block

If you need to get the admin panel URL in a block, you can do the following:
1. use the \Magento\Framework\App\DeploymentConfig\Reader in your construct:

public function __construct(
        //other stuff you need here
        \Magento\Framework\App\DeploymentConfig\Reader $configReader
    ) {
        $this->configReader = $configReader;
        //other stuff you need here, like parent::__construct($context, $data);

2. Using following lines anywhere in the class:

$config = $this->configReader->load();
$adminSuffix = $config['backend']['frontName'];
$adminUrl = $this->_storeManager->getStore()->getBaseUrl() . $adminSuffix;

There are probably some better methods for that, it’s just what I found to be working.

Magento 2: How to get Magento 2 base path (base directory)

If you need to get the base directory of your Magento 2 installation, you can use the BP constant. So for example:

echo BP;


$myModuleDir = BP . '/app/code/MyVendor/MyModule';

will work just fine.

When searching for this on the Internet you can also find answers using ObjectManager to do it, but:
1. You don’t need to make your code more difficult than it needs to be if you just need the base dir and nothing more fancy
2. The ObjectManager way will not always work. For example it won’t work in Unit Tests (you can try to instantiate one that works, but then we’re back to point 1)
So it’s better to just use the BP constant.

Magento 2 and PhpStorm: URI is not registered

When working on Magento 2 XML files, you may encounter some URI is not registered errors with URIs like urn:magento:framework:Module/etc/module.xsd in the etc/module.xml

Edit: Thanks to Dmitriy Kvashnin, we have a great PhpStorm module that gets rid of this error and does some other useful stuff as well. Check it out here:

If for some reason you don’t want to install it, but still want to get rid of the error and enjoy xsd rules when working on your XMLs, place the cursor on the URI, press ALT + Enter and select Manually setup external resource from the menu that should show up. Then, select module.xsd ([magento 2 base dir]/lib/external/Magento/Framework/Module/etc/module.xsd) (or some other file if you’re not fixing it for module.xml) and press OK.
After that, PhpStorm will be able to catch any errors you may make when working on the XML structure (like defining illegal tags or tag attributes).

Magento 2: Enable exception printing on website

By default, Magento 2 doesn’t display exception messages on website, if the execution fails then “There has been an error processing your request” is shown instead.
If you wish to see exception messages directly on the page, you need to copy the [magento 2 root directory]/pub/errors/local.xml.sample to [magento 2 root directory]/pub/errors/local.xml (or just rename it to remove the .sample file extension, but copying is better).
Additionally, remember to add the /pub/errors/local.xml to your .gitignore file on your dev copy, so it never makes its way to production website.

Also, remember that even if exceptions are not printed directly on the website, you can still see them in [magento 2 root directory]/var/report or preview any errors/exceptions in [magento 2 root directory]/var/log, just like in Magento 1.

Magento 1.8 Development Cookbook

Recently, Packt published a new Magento book that I had been reviewing named Magento 1.8 Development Cookbook, by Bart Delvaux and Nurul Ferdous.
The book covers topics from very easy like installing Magento and setting up a sample configuration to more advanced, like creating a module (a useful one, not just a most basic Hello World!) or performance optimization.

The quality of code and hints inside the book is very good – you don’t have to fear that after reading it you’ll learn bad practices and nasty code hacks.
I would definitely recommend the book for novice and experienced Magento developers and I think that even after a year or two of making Magento websites you still can learn something from this book!

Here’s the link to a website where you can buy it:

Magento 2: add CSS to your custom module

Note: this post applies to Magento ver. It may not be valid in later versions anymore.

Thanks to improved modularity in Magento 2, you can place CSS files straight in the module directory (instead of placing some things in the app directory and other things in skin directory).

The CSS file itself goes into the view directory, where all the view-related things go. If you want to add it on the frontend, it goes into view/frontend and to the view/backend if it’s supposed to be included in the admin panel. You can place it in subdirectories as well. I, for example, like to keep CSS files in a separate directory, so when developing a test module named CookieInformation, I placed my CSS file in the app/code/Bgorski/CookieInformation/view/frontend/css directory.

The next thing you need to do is to actually include the file where it needs to be included. In Magento 1.* layout handles were actually XML nodes inside the <layout> node, like this:

<?xml version="1.0" encoding="UTF-8"?>


It’s no longer the case in Magento 2. Each layout handle has actually its separate file named after the handle (like default.xml or adminhtml_system_config_edit.xml). Let’s say we want to add out CSS file on every page in the frontend. This means that we should create a view/frontend/layout directory and create a default.xml inside of it (because the default layout handle is used on every page along with any module_controller_action xml files specific to a given page). In my case (the CookieInformation module I mentioned above), the content of the file looks like this:


Notice that there’s no layout handle defined in the file (no <default> node), because as I mentioned above, the handle is defined in the file name. Also, notice that there is css/cookie-information.css in the argument string. It’s because my file is in the css subdirectory. If it was directly in view/frontend/ directory, there would be no css/ as part of the string, so the <argument> node would have just Bgorski_CookieInformation::cookie-information.css inside.

Magento 1.7 and 1.8: Redirect to referer in an observer

Normally, redirection is handled by controllers. However, if you want to do it in an observer, you can use the following piece of code inside its function that gets invoked when listening to an event:

$url = Mage::helper('core/http')->getHttpReferer() ? Mage::helper('core/http')->getHttpReferer()  : Mage::getUrl();

In the code above, the system checks if there’s any referer. If so, Magento redirects to it and if not – there’s a fallback provided.

IMPORTANT: if you decide to make a redirect in an observer, you have to be aware that no further observers listening to the event (or next events from the same request) will be processed. There’s a good reason this is by default done in controllers and you should consider avoiding it in observers. However, if you decide to do it in an observer anyway, make double sure you know what you’re doing (and what doesn’t get processed as a result) and consider making a note about it in your project’s documentation.

Magento 1.7 and 1.8: JavaScript translations (translate.js)

Most Magento programmers know about the way things can be translated in Magento in the PHP code. You just have to use a syntax like that:

echo $this->__('Text to translate'); //in blocks, defined by Mage_Core_Block_Abstract
echo Mage::helper('somemodule/somehelper')->__('Text to translate'); // defined by Mage_Core_Block_Abstract
echo $this->__('There are %s things here',$this->countThingsHere()); //if you need something more dynamic

But what if you need to translate something that’s in JavaScript? Of course, sometimes you can make an inline script like this one:

<script type="text/javascript">
confirm("<?php echo $this->__('Are you sure?') ?>");

Or, you can use the Translator object that’s available in Magento. It has two methods – one for adding translations and the other one returning a translated string – much like the .csv-based translations do. You can use it inline in your php scripts like this:

Translator.add('Some text to translate','<?php echo Mage::helper('yourmodule')->__('Translated text') ?>'); //adds a translation
alert(Translator.translate('Some text to translate')); //returns an alert with 'Translated text' inside

But most of the time, you want your JavaScript code separated from HTML code and placed in .js files. Obviously, you can’t use any PHP translating functions there. Instead of that, you can put your translations in a jstranslator.xml in the etc directory of your module. The file looks like that:

        Some text to translate
        Some other text

When having this, you can add translations to a .csv file, like for normal, PHP-based translations, and you use them just like this:

alert(Translator.translate('Some text to translate')); 

It returns a translated text, if it exists in some csv file – and it doesn’t need adding the transiation via Translator.add() function anymore.

IMPORTANT: this method won’t work on Magento versions lesser than, as this feature wasn’t implemented there yet. You have to use other methods I described above.

Magento 1.7 and 1.8: What’s in the quote model when you add a configurable product to cart

When working with a quote (an object containing all the items in the cart, among other data), it’s important to know what’s actually there.

A configurable product contains simple products – one for every attributes values set available. For example, if you sell a t-shirt available in blue and red colors from which every one is available in in S, M and L sizes, you have six simple products tied to a configurable one. If you decide not to sell blue one in S size, you have five.

When you add a configurable product to your cart, you actually add two items to the quote item:

  • the configurable product you wanted to add
  • a simple product containing options values you added (for example: a blue t-shirt with a size of M)
  • The configurable one has the quantity you wanted to buy. The simple one has a quantity of 1.

    But here comes a question many Magento developers ask themselves: what if I add to cart the same configurable product with a different set of options? The answer is actually not so obvious. Magento adds another two products to the quote – one being the same configurable product with a new quantity (containing the quantity of the product with new set of options) and the other one being a simple product with a quantity of one.

    If you want to take a look what’s really inside the quote object when you add products to it, you can paste the following debug code to some place available everywhere – for example header.phtml (remember that it’s only for testing purposes and should never go live with any project):

    foreach (Mage::getSingleton('checkout/session')->getQuote()->getAllItems() as $item) {
        echo "There's an item named " . $item->getName() . " in qty of " . $item->getQty() . "
    "; }

    This way you’ll list all the items in the quote – no matter if they represent configurable, simple or other available types of products.

Magento 1.7 and 1.8: setting up a .gitignore file for development environment

If you chose Git as your favorite version control system and use it in your Magento project, you probably want to exclude some files from your Magento installation when pushing it to a remote repository – for example files that contain passwords or ones that could compromise safety or of your project in any other way. Such files should be only kept locally – imagine what would happen if you made an automatic deployment from Git repository to your client’s server, overwriting his local.xml file with your development one. One client less to worry about.

Here is a list of files that should be put in the .gitignore file in the main directory of your project:


app/etc/local.xml contains all the settings for your Magento installation, including database username and password. Media-related entries are for temporary files and for auto-generated thumbnails and small images that Magento generates from bigger product images provided. The errors/local.xml, if it’s there, manages error reporting – and by default print errors on the screen, so if there are any errors on the website, users see them in their browsers. Bad for business, believe me. Next directory, var stores auto-generated information like sessions states, cached files or error reports. You don’t want it in your repository, because every fresh website instance should have its sessions and cache cleaned out to ensure that the system really takes your files you modify into consideration when displaying things. The last directory there, the downloader directory, stores information about extensions downloaded from Magento Connect. It’s irrelevant for development purposes, because once they’re installed, they are in the rest of directories (e.g. app/code/community or skin/frontend/base/default – depending on extensions themselves) and you don’t need the info that they were installed via connect or how their ready-to-install packages look like.

The last declaration in the .gitignore also require some explanation. It’s an exlusion made for .htaccess files inside directories other than root. These files exist in various of places, including your ignored var and downloader directories. They shouldn’t be ignored, because they contain some important information, like denying access to session-related files. That’s why, though we ignore entire var and downloader directories, there is this one file in each of them that we want to keep.

It’s also worth mentioning that because we don’t ignore .htaccess files in var and downloader, those directories will still show up when you use git status or any other command that shows files and directories. But although they’re there, Git sees only .htaccess files inside – so don’t worry about using git add var/. command, or anything like that. You won’t add any unnecessary files this way.

There may be situations when you don’t want to ignore only Magento-related files. There may be other files, like project files/directories created by IDEs that you, or other developers working on the same project work or worked on. You may also see projects containing .httpasswd files – they also should be ignored for security reasons. Here is a .gitignore file ignoring .htpasswd file and files created by some major PHP IDEs like NetBeans (nbproject dir), PhpStorm (.idea dir), Eclipse (.project file) and Aptana Studio (based on Eclipse, so the file is the same):