Overriding Magento’s Mage_Core

This was a bit fidgety, but its possible to override core Magento files! Actually there are two ways, but one involves copy pasting the class and tweaking. That will break if the class ever changes on a Magento update, so I won’t even tell you how to do that.

Instead, we’ll create our own module. My module’s called Madskull, and I already have a folder in /app/code/local/madskull

In this example, I overrode Mage_Core_Model_Url. I had to have a custom getUrl() method.

I created (in the aforementioned folder) Url/Url.php, which extends Mage_Core_Model_Url :

<?php

/**
 * Class Madskull_Core_Model_Url
 *
 *  @author delboy1978uk
 */
class Madskull_Url_Url extends Mage_Core_Model_Url
{
    /**
     * Do a quick string replace to ditch apostrophes
     * @return string
     */
    public function getUrl($routePath = null, $params = null)
    {
        return str_replace("'",'',parent::getUrl($routePath,$params));
    }
}

Okay, next in the Url directory, create an etc folder, and create config.xml :

<config>
    <modules>
        <Madskull_Url>
            <version>1.0.1</version>
        </Madskull_Url>
    </modules>
    <global>
        <models>
            <core>
                <rewrite>
                    <url>Madskull_Url_Url</url>
                </rewrite>
            </core>
        </models>
    </global>
</config>

Finally, we activate the module by adding it to a new file /app/etc/modules/Madskull_Url_Url.xml :

<?xml version="1.0"?>
<config>
    <modules>
        <Madskull_Url>
            <active>true</active>
            <codePool>local</codePool>
            <depends>
                <Mage_Core />
            </depends>
        </Madskull_Url>
    </modules>
</config>

Job done! Now, without creating second copies of the core classes, you can extend away, and updates will not affect your code!

ASP.NET Storefront for PHP People

Hi! This post will increase in size as the scale of horror increases, but for now, you’ve been landed with the runt of the projects – an ASP dot Net Storefront Website running on IIS on a windows server. Horrible!

Anyway, when not in the backend CMS part of things, you’ll have to edit files. What are they? I’m not entirely sure, but there are a few which I have figured out:

  • In the root folder there are appears to be categorynamehere.aspx (eg. watches.aspx). This is a landing page for a specific category
  • Header and Footer are in the Controls directory
  • Display Format Stuff and other bits of the header etc is in XMLPackages
  • In the backend, store admin > products > category, the displayformat xml package = entity.sortgridwithprices.xml
  • Also in the backend,  the actual product uses product.simpleproduct.xml.config
  • You can pick what categories each product comes under in the mappings tab.
  • Home Page template for some obscure reason is found in skins/Skin_2
  • Theres a cache flush link at the top right next to your logout link – use it!

Commands: In the xml.config files there are various output things such as {aspdnsf:GetUrl()}. I will document each as I figure them out

  • {aspdnsf:GetUrl()}  the url of the page, put this anywhere to output it
  • {$pName} the product name

Update: Today I’ve been asked to convert some products to ‘In store Only’! This basically means that you can’t order the product from the website, and instead need to call to book it. This is actually quite simple to achieve, all that is required is in Manage Products, you select the item,

*Is Call to Order: NoYes

Now when you visit the product page again, the add to cart button has been replaced!
Also, if we need to edit the actual topic page, to do this we go into Content > Manage Topics, select your topic, and use the wysiwyg editor!

Meta Tag Controller Plugin for Zend Framework

Again on the never ending quest to DRY up my code, next in the targets are the head sections MetaTags!

Following on from my last post which used Zend_Config_Xml, we shall do the same for each pages title, description, and keywords.

In your application/configs directory, create a file named meta.xml :

<?xml version="1.0" encoding="UTF-8"?>
<config>
 <meta>
  <uris>
   <uri>
     <page>/</page>
     <title>My Home Page</title>
     <description>This is my websites home page</description>
     </uri>
     <uri>
       <page>/buying</page>
       <description>BUYING A HOUSE</description>
       <title>Buying a property</title>
     </uri>
     <uri>
       <page>/selling</page>
       <description>SELLING A HOUSE</description>
       <title>Selling a property</title>
     </uri>
   </uris>
 </meta>
</config>

Create a Controller Plugin in your library. For me, it’s /library/TTB/Plugin/Meta.php :

class TTB_Plugin_Meta extends Zend_Controller_Plugin_Abstract
{
 public function preDispatch(Zend_Controller_Request_Abstract $request) 
 { 
   try 
   {
     $config = new Zend_Config_Xml(APPLICATION_PATH.'/configs/meta.xml','meta');
     $uri = $request->getPathInfo();
     $defaults = true;
     $view = Zend_Controller_Front::getInstance()
             ->getParam('bootstrap')
             ->getResource('view');
     foreach ($config->uris->uri as $meta) 
     {
       if($meta->page == $uri) 
       {
         $view->headMeta()->appendName('title', $meta->title);
         $view->headMeta()->appendName('description', $meta->description);
         $defaults = false;
       }
     }
     if($defaults == true)
     {
       $view->headTitle('My Awesome Website');
       $view->headMeta()->setName('description','This is the default');
       $view->headMeta()->setName('keywords','zend framework, php, delboy1978uk');
     }
   }
   catch(Exception $e)
   {
     throw new Exception('Unable to set Meta Tags');
   }
 } 
}

We need to register the plugin in our application.ini :

autoloaderNamespaces[] = "TTB_"
resources.frontController.plugins.Meta = "TTB_Plugin_Meta"

Finally we initialise the Plugin in our bootstrap :

protected function _initMeta()
{
    $meta = new TTB_Plugin_Meta();
}

You should already have this in your layout file, but if not you want this in the <head> section of your layout.phtml :

echo $this->headTitle();
echo $this->headMeta();

There we have it! Meta Tags – sorted!
Again Brownie Points will be awarded to he/she who replies with code to populate the XML from DB data!

If you need to override the defaults from within a controller, (eg. if you were populating the title with db data), you can use this sort of thing:

$this->view->headTitle('Dynamic Page Title', 'SET');
 $this->view->headMeta()->setName('description','Dynamic Description');
 $this->view->headMeta()->setName('keywords','dynamic keywords');

Cheers amigos! 😀

Navigation, Breadcrumbs, & Sitemap with Zend Framework

Let Zend Framework do all the work when it comes to your Navigation, and stop hard coding stuff in either layouts or view files!

First up, in the configs folder, create an XML file called navigation.xml :

<?xml version="1.0" encoding="UTF-8"?>
<configdata>
 <nav>
  <home>
   <label>Home</label>
   <uri>/</uri>
   <pages>
     <buying>
       <label>Buying</label>
       <uri>/buying</uri>
     </buying>
     <selling>
       <label>Selling</label>
       <uri>/selling</uri>
     </selling>
     <tenants>
       <label>Tenants</label>
       <uri>/tenants</uri>
     </tenants>
     <landlord>
       <label>Landlord</label>
       <uri>/landlord</uri>
     </landlord>
     <about>
       <label>About Us</label>
       <uri>/about-us</uri>
     </about>
     <contact>
       <label>Contact Us</label>
       <uri>/contact-us</uri>
     </contact>
     <sitemap>
       <label>Site Map</label>
       <uri>/sitemap</uri>
     </sitemap>
     <privacypolicy>
       <label>Privacy Policy</label>
       <uri>/privacypolicy</uri>
     </privacypolicy>
     <termsofuse>
       <label>Terms of Use</label>
       <uri>/termsofuse</uri>
     </termsofuse>
   </pages>
  </home>
 </nav>
</configdata>

Stick this _init method into your bootstrap :

protected function _initNavigation()
{
 $this->bootstrap('layout');
 $layout = $this->getResource('layout');
 $view = $layout->getView();
 $config = new Zend_Config_Xml(APPLICATION_PATH.'/configs/navigation.xml','nav');
 $nav = new Zend_Navigation($config);
 $view->navigation($nav);
}

This loads the XML into a Zend Config, which gets passed to Zend_Navigate, and finally to the view. To get this stuff displaying on your pages, go into your layout.phtml and add this:

echo $this->navigation()->menu();

For breadcrumbs, put this into your Controllers _init method. This figures out where in the XML tree we are:

$uri = $this->getRequest()->getPathInfo();
if (($activeNav = $this->view->navigation()->findByHref($uri)) !== null) 
{
 $activeNav->active = true;
} 
else if (($activeNav = $this->view->navigation()->findByUri($uri)) !== null) 
{
 $activeNav->active = true;
}

And back in the layout, add this:

echo $this->navigation()->breadcrumbs()->setMinDepth(0)->setLinkLast(false)->setSeparator(' | ');

The setLinkLast false makes the last breadcrumb non linkable (I mean we’re on that page!), and setSeparator can contain any HTML.

Finally, to get a sitemap that Google can accept, in your sitemap’s controller action, we only need to add this :

Zend_Layout::getMvcInstance()->disableLayout(); 
 $this->_helper->viewRenderer->setNoRender(true);
 echo $this->view->navigation()->sitemap();

And thats us! Nice n easy! Bonus brownie points for anyone who posts a reply showing how to separate footer links from the nav!

Outputting results in different formats with ZF

So no doubt somewhere on your site, you’ll have a page displaying a list of items or whatnot. In this example it’s a search results page.
We’ll have a controller action with a corresponding view (in my case its the searchAction() )
We have a view file that uses HTML markup with a PHP foreach loop to iterate through each row in the result.

But who says we want HTML? We could equally be asking for XML, JSON, CSV, anything!

This is where Zend Framework’s context switcher comes into use. It’s really simple!

In your init() method of your controller class, use something like this:

public function init()
 {       
         // initialize context switch helper
         $contextSwitch = $this->_helper->getHelper('contextSwitch');
         $contextSwitch->addActionContext('search', 'xml')
                                       ->initContext();
}

This allows us to use the URL parameter ?format=xml or /format/xml
We need a different view instead of search.phtml, so create search.xml.phtml

<?php
// create XML document 
$dom = new DOMDocument('1.0', 'utf-8');   
// create root element 
$root = $dom->createElementNS( 'http://yoursite, 'del:document'); 
$dom->appendChild($root);   
// convert to SimpleXML 
$xml = simplexml_import_dom($dom);   
// add summary element 
$xml->addChild('matches', count($this->results)); 
$xml->addChild('searchTime', time());   
// add resultset elements 

$results = $xml->addChild('results'); 
foreach ($this->results as $r) 
{   
$result = $results->addChild('result');   
$result->addChild('id', $this->escape($r->id));   
$result->addChild('name', $this->escape($r->name));   
$result->addChild('age', $this->escape($r->age));   
$result->addChild('height', $this->escape($r->height));   
$result->addChild('country', $this->escape($r->Country));   
$skills = $result->addChild('skills');   
$skills->addChild('primary', $this->escape($r->primary));
$skills->addChild('secondary', $this->escape($r->secondary)); 
}   
// return output
 echo $xml->asXML();

Now we can browse to /index/search or /index/search/format/xml and get our results displayed in a custom format! Nose in to the Zend Docs to find out more! 😀