Magento2 – How to add block to contact us page and change the layout

I’ve recently started my journey into Magento 2 loveliness. It’s been ruddy hard to get used to but I can appreciate a lot has changed for the better.

Today a client asked if they could include their address in the contact form page. I remember in M1 it was ridiculously awkward but I found various ways around it. With M2 in its infancy, it doesn’t get any easier to find a reliable guide (Every single Magento blog assumes example is present.

Never fear, I have cobbled together a couple of guides to show you how I sorted this.

  • Step 1 – Create a static block
    Name it something memorable as usual. I won’t go into specifics on how to do this, you’re not an idiot.
  • Step 2 – Configuration (thanks goes to Steve B in the comments)
    1. Go to Content > Widgets
    2. Create new widget and choose CMS Static Block
    3. Add layout update to specific page (Contact us Page), Main Content Top Container
    4. Choose Static Block.
    5. In Layout Updates, select “Sidebar Main” (or wherever you like, but for the purposes of this tutorial, I’ll use the sidebar)
  • Step 3 – Get that contact page working spiffingly.
    1. Create a file app/design/frontend/<vendor>/<theme>/Magento_Contact/layout/contact_index_index.xml
    2. Within that file add the code:

    <?xml version="1.0"?>
    <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
     <body>
     <referenceBlock name="contactForm">
     <action method="setTemplate">
     <argument name="template" xsi:type="string">Magento_Contact::form.phtml</argument>
     </action>
     </referenceBlock>
     <referenceBlock name="catalog.compare.sidebar" remove="true"/>
     <referenceContainer name="sidebar.additional" remove="true" />
     </body>
    </page>
    

    Essentially the only purpose of this xml file is to change the contact page to a 2 column template (so it accepts our new information).

    You’ll also notice I removed the wishlist and compare blocks. My site didn’t have these turned off, so they were appearing below the new text.

 

Obviously clear the cache and do what you need to do.

That should all be ok for you now. Happy Magento 2’ing!

Simple Configurable Products 404 Error

So because Magento V1 is horrible at handling Configurable Products, a lot of us are forced to use the prodigal SCP Extension (Simple Configurable Products) which, much like the Ryugyong Hotel, just stopped being supported. Thankfully, a lot of the features still work, but there are some issues which have been fixed by the community.

One such issue is one I’ve encountered when I tried adding a quantity of product which exceeded the availability. Because the simple product isn’t visible in the store (it’s hidden because it’s associated with the configurable product), you’re taken to a 404 page. As far as Magento is concerned, the product doesn’t exist.

After weeks of fudging this (using plugins to cover it up basically), someone posted a fix on the plugins github:

The exact fix is here.

Basically, all you need to do is append some code onto a couple of the plugin files and the plugin now redirects to the configurable product and NOT the out of stock hidden simple product.

Magento – All CMS Pages in a list w/ current page highlighted

Ok, so this might be easy for a seasoned Magento Front Ender to work out, but it’s always nice to have this type of code available for people to copy and paste.

Sometimes, you’ll be required to output a list of CMS pages on your store for easier navigation for the user. In this case, I was asked to add a sidebar to all CMS pages containing other active pages.

Firstly, create a page in your theme folder, something like template/page/html/cmsPages.phtml

Pop the following code in the file:

<?php 
	$currIdent = Mage::getSingleton('cms/page')->getIdentifier(); //We need the identifier of the current page for later use
	$currTitle   = Mage::getSingleton('cms/page')->getTitle();
?>

<div class="related-pages">
	<h2><?php echo $currTitle; ?></h2>
		<?php 
		 $pages = Mage::getModel('cms/page')->getCollection()
		        ->addFieldToFilter('is_active',1)
		        ->addFieldToFilter('identifier',array(array('nin'=>array('privacy-policy','terms-conditions')))); //Use this to exclude any pages you don't want in the list
		?>
		<ul>
			<?php
				foreach($pages as $page)
				{
				    //var_dump($page->getData()); //Unquote this if you want to see other attributes.
				    $ident = $page->getIdentifier(); //Identifier of page in loop
				    if ($ident == $currIdent) { //If current page identifier matches looped identifier
				    	$class = 'class="current"'; 
				    }else{
				    	$class = '';
				    }
					echo '<li ' . $class .'><a href="' . $this->getUrl($ident) .'">' . $page->getTitle() . '</a></li>'; 
				}
			?>
		</ul>
</div>

Once that’s created, go into your local.xml and add the following to all CMS pages. This is under the assumption that your CMS pages contain a right or left block:

    <cms_page>
        <reference name="right">
            <block type="page/html" name="cms_list" as="cms_list" template="page/html/cmsPages.phtml" />  
        </reference>
    </cms_page>

And there we go. Simple as that!

Grunt installation issues on Magento 2

I’ve been trying to install Grunt on Magento 2 and been having little luck.

This was the result of me trying to run

npm install grunt --save-dev
13609 error argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install" "grunt" "--save-dev"
13610 error node v4.2.1
13611 error npm  v2.14.7
13612 error code EPEERINVALID
13613 error peerinvalid The package grunt@1.0.1 does not satisfy its siblings' peerDependencies requirements!
13613 error peerinvalid Peer grunt-exec@0.4.6 wants grunt@~0.4
13613 error peerinvalid Peer grunt-styledocco@0.1.6 wants grunt@~0.4
13613 error peerinvalid Peer grunt-contrib-clean@0.6.0 wants grunt@~0.4.0
13613 error peerinvalid Peer grunt-banner@0.4.0 wants grunt@>=0.4.0
13613 error peerinvalid Peer grunt-autoprefixer@2.2.0 wants grunt@~0.4.2
13613 error peerinvalid Peer grunt-contrib-watch@0.6.1 wants grunt@~0.4.0
13613 error peerinvalid Peer grunt-replace@0.9.3 wants grunt@>=0.4.0
13613 error peerinvalid Peer grunt-contrib-connect@0.9.0 wants grunt@~0.4.0
13613 error peerinvalid Peer grunt-contrib-cssmin@0.10.0 wants grunt@~0.4.1
13613 error peerinvalid Peer grunt-contrib-less@0.12.0 wants grunt@~0.4.0
13613 error peerinvalid Peer grunt-contrib-jasmine@0.8.2 wants grunt@~0.4.0
13613 error peerinvalid Peer grunt-contrib-imagemin@0.9.4 wants grunt@>=0.4.0

If I simply change the original command to:

npm install grunt@0.4 --save-dev

It seems to accept it!

SCP – The category page doesn’t show a “Price From” label!

So I’ve been using the rather crazy Simple Configurable Products by Organic Internet – it’s world famous. I’m sure if you’re a Magento developer, you’d probably have heard of it.

Over the weekend, a client which relies on configurable products complained about products just showing the Final Price and not the Smallest Price. I should have really twigged by then, but alas I took the complete wrong route to working it out.

Anyway, long story short, it was because the Associated Products were outputting in the wrong order, hence Final Price taking priority over the Smallest Price.

config_issue

What did I do to fix it? Simple. I un-associated and re-associated the products in the correct order and BAM… the correct prices started showing again.

Why did this happen though? I honestly don’t know. I did import the products initially using the Magmi utility and may have imported them in the incorrect order.

Either way it’s pretty much fixed. Thankfully.

Magento | Breadcrumbs aren’t consistent

Never fear. Thanks to Palanikumar, we can override the core files.

Firstly, copy Breadcrumb.php from

app/code/core/Mage/Page/Block/Html

to

app/code/local/Mage/Page/Block/Html

And then replace the function _toHtml() (it should be easy to locate)

with the following updated function.

protected function _toHtml() {             

       $cat_id = "";

       if (Mage::registry('current_product')) {
          $product_id = Mage::registry('current_product')->getId();
          $obj = Mage::getModel('catalog/product');
          $_product = $obj->load($product_id); // Enter your Product Id in $product_id

          if ($product_id) {
             $categoryIds = $_product->getCategoryIds();
             $cat_id = $categoryIds[0];
          }

          $category = Mage::getModel('catalog/category')->load($cat_id);
          $cat_name = $category->getName();
          $cat_url =  $this->getBaseUrl().$category->getUrlPath();
       }

       if (is_array($this->_crumbs)) {
          reset($this->_crumbs);
          $this->_crumbs[key($this->_crumbs)]['first'] = true;
          end($this->_crumbs);
          $this->_crumbs[key($this->_crumbs)]['last'] = true;
       }

       if($cat_id) {
          $this->_crumbs['category'.$cat_id] = array('label'=>$cat_name, 'title'=>'', 'link'=>$cat_url,'first'=>'','last'=>'','readonly'=>'');
          ksort($this->_crumbs);
          $home = $this->_crumbs['home'];
          unset($this->_crumbs['home']);
          array_unshift($this->_crumbs,$home);
       }

       $this->assign('crumbs', $this->_crumbs);
       return parent::_toHtml();
    }

BOOM!

Category Thumbnails in my Magento menu?

Not a problem.

Firstly, from Magento 1.9 onwards, they removed the “Category Thumbnail” feature from category panels.

You can bring those back using this swift guide (from http://www.magikcommerce.com/blog/magento-1-9-1-0-missing-thumbnail-image-category/)

Go into phpmyadmin and run the following query (make sure to back up your db first).

Note: If this gives an error about duplicate key, you’ve probably already created an attribute with that value. Increase the ID of 140 to something greater (I used 240).

INSERT INTO `eav_attribute` (`attribute_id`, `entity_type_id`, `attribute_code`, 
`attribute_model`, `backend_model`, `backend_type`, `backend_table`, `frontend_model`, 
`frontend_input`, `frontend_label`, `frontend_class`, `source_model`, `is_required`, 
`is_user_defined`, `default_value`, `is_unique`, `note`) VALUES(140, 3, 'thumbnail', NULL, 
 'catalog/category_attribute_backend_image', 'varchar', NULL, NULL, 'image', 'Thumbnail
 Image', NULL, NULL, 0, 0, NULL, 0, NULL);

Now run these ones (watch the ID!):

INSERT INTO `catalog_eav_attribute` (`attribute_id`, `frontend_input_renderer`, 
`is_global`, `is_visible`, `is_searchable`, `is_filterable`, `is_comparable`, 
`is_visible_on_front`, `is_html_allowed_on_front`, `is_used_for_price_rules`, 
`is_filterable_in_search`, `used_in_product_listing`, `used_for_sort_by`, 
`is_configurable`, `apply_to`, `is_visible_in_advanced_search`, `position`, 
`is_wysiwyg_enabled`, `is_used_for_promo_rules`) VALUES 
 (140, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, NULL, 0, 0, 0, 0);
INSERT INTO `eav_entity_attribute` (`entity_attribute_id`, `entity_type_id`,  
`attribute_set_id`, `attribute_group_id`, `attribute_id`, `sort_order`) 
VALUES (337, 3, 3, 4, 140, 3);

Now, I’ve researched many ways to include thumbnails in the menu, many of them involved hacking the core (NOT recommended). However, a quick fix meant adding the following code worked with a category loop.

<?php if ($image = $_category->getThumbnail()): ?>
	<?php $imageUrl = Mage::getBaseUrl('media').'catalog/category/'.$image; ?>
<?php else: ?>
	<?php $imageUrl = Mage::getBaseUrl('media').'catalog/category/noimage.png'; ?>
<?php endif; ?>	

Again, there will be better ways to do this, but I found this offered a quick fix.

Magento – Emails not being sent out DESPITE cron.php being enabled and running

For the past 2 weeks or so, I’ve been pulling my hair out over an issue whereby order emails weren’t being sent out.
These are the most common questions I encountered on Google:

  • Was a cronjob set up correctly? You bet your arse it was.
  • Were emails sending out from the server? Yep, they were!
  • Have you installed AOE scheduler? Yes I have! (Wonderful piece of kit by the way)
  • Are you an idiot? Yes, I probably am.

After checking many MANY times those questions were answered, I stumbled across another StackOverflow question which I somehow missed, it suggested the following:

Edit file cron.php

After

 

$isShellDisabled = (stripos(PHP_OS, ‘win’) === false) ? $isShellDisabled : true;

add

 

$isShellDisabled = true;


As soon as that was saved, I got literally 500 emails containing “too late for schedule”. I made sure the timings matched the cron settings on Config > Advanced > System > Cron (ie, 15 minutes in the crontab = 15 minutes in the cron settings) – and BAM! My old orders came through, as did my tears of joy and relief.

The other question I have is that why wasn’t this running when other Magento installs I’ve worked with have no trouble?

TBC…

 

EDIT – Another interesting link which might cause discrepancies with the cronjob heartbeat error – http://magento.stackexchange.com/questions/82979/magento-1-9-2-1-cron-not-working

Magento – Newsletter Subscription Action

SEO on your back about newsletter conversions? Don’t want to install pointless extensions? Want to redirect to a newletter thank you page?

Here we go:

Find your newsletter subscription form.

Most commonly app\design\frontend\fat\default\template\newsletter\subscribe.phtml

Pop this in before the end:

<input type="hidden" name="uenc" value="<?php echo Mage::helper('core')->urlEncode(Mage::app()->getStore()->getBaseUrl() . 'your_page_url_key') ?>"/>

Remembering to replace ‘your_page_url_key’ with your desired page.

Magento: Slider without baggage

One of my main concerns about developing a Magento site in this modern device-laden industry is its lack of options for banners. There are many plugins out there, but all of them came with a degree of baggage, which really weighed the performance down.

So imagine my joy when I discovered Antoine K Slider.

The description sold it to me:

“This extension will render a simple HTML list on the frontend. You will need to add your own JS layer in order to get a real sexy slider.”

And that’s essentially all I was looking for – an extension with repeatable fields which output a simple list on the front end.

slider

Once I create the slider, I get presented with some XML to place in the design section of whatever page/category/product I’d like.

What’s more is that it’s relatively easy to expand (I added the subtitle field in the screenshot). I have admittedly no knowledge in the structure of Magento extensions, but within an hour, my extra field was up and running.