blog site of branko ajzele, senior developer / project manager

WordPress and Magento integration – One way to go

Lot of us in Magento related development have an issue of connecting their Magento with other CMS solutions out there. Lot of our clients like and want WordPress alongside Magento. WordPress is a great platform when it comes to publishing and managing articles. Not to mention the SEO stuff. One of the biggest issue with integrating two systems in PHP is the lack of the namespaces. This leads to function name redeclaration issues and so on. Integrating something into something is such a loosely term, depending on level of integrations… If you ask me :)

In this article, I’ll give you one way of how you can integrate your WordPress (or any other CMS) with Magento. If you read the article written at http://www.magentocommerce.com/blog/comments/tutorial-integrating-3rd-party-cms-content-within-magento, then you will on clear with my article. The approach is somewhat similar. There is one issue I see with the integration in the link I provided. You see, integration is done in such way that you fool no_route controller in Magento to ignore 404 template for no route and send a request to some other url then load that url content into the block that was previously used by 404 template.

Now, either I’m missing something or… The biggest issue I see with the above approach are the URL links of the content returned to us. Let’s suppose our shop is located on http://example-shop.domain/ and our WordPress at http://example-shop.domain/articles/. When we implement solution above we get some stuff under http://example-shop.domain/my-wordpress-article-no1, which is generally found under http://example-shop.domain/articles/my-wordpress-article-no1.

Now, if we had some auto generated links inside that post, my-wordpress-article-no1, pointing to other articles in my WordPress then those links would have url’s like http://example-shop.domain/articles/my-wordpress-article-no2, http://example-shop.domain/articles/my-wordpress-article-no3 and so on. Notice the /articles part in them? Clicking on such links would drove us away from Magento part of the site. We could theoretically access those articles by simply using direct link to http://example-shop.domain/my-wordpress-article-no2 since above method would interpret that as /auto and fetch it for us. How do we deal with this? Have no idea… Url rewrite? What about all of those WordPress plugins out there… Do we know what effect would above method have on that kind of integration. I don’t. That’s why I wrote another kind of integration.

Important: This is merely MY WAY of resolving this issue, and as such is more of a temporary approach. Since I’m not quite satisfied with this one as well :)

First let me define what I mean by integration of WordPress and Magento:

  • They are both installed each in it’s own directory
  • Wordpress uses Magento’s .css files
  • Wordpress uses (includes, trough class I wrote below) Magento’s header and footer
  • WordPress utilities jQuery for a little help in patching up some holes by use of COOKIES

Final result:
All of the header and footer stuff in WordPress is used from Magento so you do not need to restyle it in WordPress. All you need to do is to style and work on the content area of the WordPress template output.

Steps:
1) Do the full styling of Magento part. After that, 1column.phtml file and surround the header output stuff with comments like:

<!-- STARTHeaderContainer --><div class="header-container"><?php echo $this->getChildHtml('header') ?></div><!-- ENDHeaderContainer -->

2) Do the same for footer output stuff in same file:

<!-- STARTFooterContainer --><div class="footer"><?php echo $this->getChildHtml('footer') ?></div><!-- ENDFooterContainer -->

3) Go to Magento Admin > CMS > Manage pages > Add new… call it “empty” or whatever, set it active, assign this page to use 1column layout. You should now be able to access this page using url like http://example-shop.domain/empty. It should show minimal page with only header and footer stuff. If you see some additional block then go back to edit page and under layout updates place
4) Go to WordPress theme folder, open functions.php file, copy paste the class ActiveCodeline_ConnectWM into it.
5) Inside WordPress theme folder, open header.phtml and instantiate a class like:

<?php
$parts = new ActiveCodeline_ConnectWM('http://example-shop.domain/empty');
echo $parts->renderHeader();
?>

And here is the class content:

class ActiveCodeline_ConnectWM
{
private $_content;
private $_header;
private $_footer;
 
/**
* Assign a url to some lightweight Magento page, posible 1 column, empty CMS page
*/
public function __construct($url, $markerStartHeader = null, $markerEndHeader = null, $markerStartFooter = null, $markerEndFooter = null)
{
$this->_content = file_get_contents($url);
$this->_renderHeader($markerStartHeader, $markerEndHeader);
$this->_renderFooter($markerStartFooter, $markerEndFooter);
}
 
public function renderHeader($markerStart = null, $markerEnd = null)
{
return $this->_header;
}
 
private function _renderHeader($markerStart = null, $markerEnd = null)
{
$markerStart = (is_null($markerStart)) ? '<!-- STARTHeaderContainer -->' : (string)$markerStart;
$markerEnd = (is_null($markerEnd)) ? '<!-- ENDHeaderContainer -->' : (string)$markerEnd;
 
$headerStart = stripos($this->_content, $markerStart);
$headerEnd = stripos($this->_content, $markerEnd);
 
$this->_header = substr($this->_content, $headerStart, $headerEnd-$headerStart);
}
 
public function renderFooter()
{
return $this->_footer;
}
 
private function _renderFooter($markerStart = null, $markerEnd = null)
{
$markerStart = (is_null($markerStart)) ? '<!-- STARTFooterContainer -->' : (string)$markerStart;
$markerEnd = (is_null($markerEnd)) ? '<!-- ENDFooterContainer -->' : (string)$markerEnd;
 
$footerStart = stripos($this->_content, $markerStart);
$footerEnd = stripos($this->_content, $markerEnd);
 
$this->_footer = substr($this->_content, $footerStart, $footerEnd-$footerStart);
}
 
}

Upon refresh of WordPress home page you should now see the Mageno header loaded. Now, for the sweet part, transfering customer related info, like cart item status and so on.

Inside WordPress header file you can use stuff like:

...
<?php wp_head(); ?>

<script type="text/javascript">
jQuery(document).ready(function() {
jQuery("#totalItemsCount").html("<?php echo $_COOKIE['my_cart_items'] ?>");
jQuery("#totalItemsPrice").html("<?php echo $_COOKIE['my_cart_total'] ?>");
});
...
</script>

Notice the $_COOKIE['my_cart_items'] ?>. Let’s say we wish to see total number of items in cart and total price of added items. Nice little feature inside our header that lots of clients look for. Here is how, open your header.phtml from Magento folder, and copy paste the code:

$totalNumOfCartItem = Mage::helper('checkout/cart')->getCart()->getItemsCount();
 
$totalPrices = Mage::helper('checkout/cart')->getCart()->getQuote()->getTotals();
 
$subtotalPrice = $totalPrices['subtotal'];
$subtotalPrice = $subtotalPrice->getData('value');
 
$grandTotal = $totalPrices['grand_total'];
$grandTotal = $grandTotal->getData('value');
 
setcookie('my_cart_items', $totalNumOfCartItem);
setcookie('my_cart_total', Mage::helper('core')->currency($grandTotal, true, false));

Combined with something like (inside header.phtml)

 
<div id="mini_mycart">
<ul>
<li id="tnpart_mycart">
<p>items: <span id="totalItemsCount"><?php if(isset ($totalNumOfCartItem)) { echo $totalNumOfCartItem; } else { echo '0'; } ?></span><br />
total: <span id="totalItemsPrice"><?php if(isset($grandTotal)) { echo Mage::helper('core')->currency($grandTotal, true, false); } else { echo Mage::helper('core')->currency('0', true, false); } ?></span></p>
</li>
<li id="tnpart_view_mycart"><a href="<?php echo $this->getUrl().'checkout/cart/'; ?>" title="View my cart"><span class="b1">View my cart</span></a></li>
<li id="tnpart_wishlist"><a href="<?php echo $this->getUrl().'wishlist/'; ?>" title="My wishlist"><span class="b1">My wishlist</span></a></li>
<li id="tnpart_checkout"><a href="<?php echo $this->getUrl().'checkout/onepage/'; ?>" title="Checkout"><span class="b1">Checkout</span></a></li>
</ul>
 
<p id="submini_account_action">
<a href="#" title="My account">my account</a>
<span class="delimiter1">|</span>
<a href="#" title="Login">login</a>
</p>
</div><!-- /mini_mycart -->

And you get cart info on both Magento and WordPress side (hence the jQuery stuff). This walk-trough is not for newbies. I did not go in such details so some stuff might be unclear. However, all of the code you need to make it work is here.

  • spenserbaldwin
    You're nuts that you've figured this stuff out. Does it follow logically that one can do this for almost any part of Magento into Wordpress?
  • We've made a minor up extension to supplement a Magento/Wordpress integration.

    We've made it available here: http://www.sonassi.com/knowledge-base/magento-k...
  • Thank you for posting step by step information on how to integrate magento in wordpress..
  • anxiety
    great guide. It helps especialy when WP doesnt come up to help as quick as possible
  • finch8243
    Great modification, we're using on our blog. One question -- how do you get it to work when you enable permalinks in Wordpress? The htaccess file screws up the class's call on this line:

    ActiveCodeline_ConnectWM('http://example-shop.domain/empty');

    Ideas?
  • Nick
    I second the permalink issue, that would be great if we could have SEO permalinks instead of the default ones. Is there any way to do this?
  • Hi,

    Great code guys thanks for sharing! If you are using Robert's excellent cookie code addon to get the cart items etc in wordpress, then consider using:

    if(isset($_COOKIE['frontend'])) {
    $opts = array('http' => array('method' =>
    'GET', 'header' => "Accept-language: en\r\nCookie:
    frontend=".$_COOKIE['frontend']."\r\n"));
    } else {
    $opts = array('http' => array('method' =>
    'GET', 'header' => "Accept-language: en\r\n"));
    }

    to avoid Magento choking if people visit the blog before ever visiting the store (on session_start in app/code/core/Mage/Core/Model/Session/Abstract/Varien.php).
  • David
    We're making use of Magento ver. 1.3.2.3 and we're trying to get the amount of items in the cart making use of the cookie code mentioned here, but unfortunately we're getting a fatal error: Uncaught exception 'Mage_Core_Model_Session_Exception'

    Is there something we're overlooking? Thanks in advance for your help!
  • David
    We're making use of Magento ver. 1.3.2.3 and we're trying to get the amount of items in the cart making use of the cookie code mentioned here, but unfortunately we're getting a fatal error: Uncaught exception 'Mage_Core_Model_Session_Exception'

    Is there something we're overlooking? Thanks in advance for your help!
  • Zach
    Hi,

    For step #5, there does not exist header.phtml in the WordPress theme folder. I tried completing that step in Magento's header.phtml but obviously that did not work either.

    What am I doing wrong?
  • Hello everybody,

    I tried this with magento 1.3.2.1 and Wordpress 2.8.5 without success, i think is because the css, how do i configure wordpress to use magento css? because my header appear totally broken as a text page..

    Sorry for dummy question and my bad English

    Thanks a lot
  • spenserbaldwin
    Just call for the correct stylesheet in the header.php w/i your wordpress directory.
  • any
    Thanks alot, i was just thinking how i was going to implement a blog feature into magento - which i only just came across after trying to implement a cart feature into ning platform - to no avail i looked at wordpress and learnt of magento and the big brands that use it blew me away.

    Ok, now if anyone could clear up something for me.

    Magento - do i simply register and then it will alow me to add my free theme that i have into it.

    ?
  • Oh, and later, when you want to show the header/footer just call:


    global $parts;
    echo $parts->renderHeader();
    ...
    echo $parts->renderFooter()
  • @Branko, no worries, busy is good :) I understand. I'm like that too most of the time.

    @Miquil, I have admittedly altered the Connect_WM class a little and here's the full code from [wp_root]/wp-content/themes/your_theme/functions.php


    class ActiveCodeline_ConnectWM
    {
    private $_content;
    private $_header;
    private $_footer;

    /**
    * Assign a url to some lightweight Magento page, posible 1 column, empty CMS page
    */
    public function __construct($url, $markerStartHeader = null, $markerEndHeader = null, $markerStartFooter = null, $markerEndFooter = null)
    {
    $opts = array('http' => array('method' => 'GET', 'header' => "Accept-language: en\r\nCookie: frontend=".$_COOKIE['frontend']."\r\n"));
    $context = stream_context_create($opts);
    $this->_content = file_get_contents($url, FILE_TEXT, $context);
    $this->_renderHeader($markerStartHeader, $markerEndHeader);
    $this->_renderFooter($markerStartFooter, $markerEndFooter);
    }

    public function renderHeader($markerStart = null, $markerEnd = null)
    {
    return $this->_header;
    }

    private function _renderHeader($markerStart = null, $markerEnd = null)
    {
    $markerStart = (is_null($markerStart)) ? '<!-- STARTHeaderContainer -->' : (string)$markerStart;
    $markerEnd = (is_null($markerEnd)) ? '<!-- ENDHeaderContainer -->' : (string)$markerEnd;

    $headerStart = stripos($this->_content, $markerStart);
    $headerEnd = stripos($this->_content, $markerEnd);

    $this->_header = substr($this->_content, $headerStart, $headerEnd-$headerStart);
    }

    public function renderFooter()
    {
    return $this->_footer;
    }

    private function _renderFooter($markerStart = null, $markerEnd = null)
    {
    $markerStart = (is_null($markerStart)) ? '<!-- STARTFooterContainer -->' : (string)$markerStart;
    $markerEnd = (is_null($markerEnd)) ? '<!-- ENDFooterContainer -->' : (string)$markerEnd;

    $footerStart = stripos($this->_content, $markerStart);
    $footerEnd = stripos($this->_content, $markerEnd);

    $this->_footer = substr($this->_content, $footerStart, $footerEnd-$footerStart);
    }
    }
    $parts = new ActiveCodeline_ConnectWM('http://'.$_SERVER['SERVER_NAME'].'/empty');
  • Miquil
    Thanks Branko for the script... After a couple of hours I finally got the script working.. The only problem I still have is the one Robert had.. Is it possible to explain what he did or were I should put the code Robert added as Comment?

    Thanks,
  • @Robert Thnx for the feedback. My apologies for not getting back to you or anyone else, I am truly busy for most of the time.
  • Hey, it's been a while since my previous question. I just revisited the issue of the cart items display getting lost wen switching from the Magento site to the WordPress site.

    The issue with the method in the article above is that it doesn't create a stream context when it gets the magento page. So, to preserve our header with the welcome message and cart items display, we need to create a stream context and add the 'frontend' cookie that magento sets.

    The code now becomes:


    $opts = array('http' => array('method' => 'GET', 'header' => "Accept-language: en\r\nCookie: frontend=".$_COOKIE['frontend']."\r\n"));
    $context = stream_context_create($opts);
    $this->_content = file_get_contents($url, FILE_TEXT, $context);


    And, voila, everything is fine again.

    Hope this helps someone.
  • Hi Branko,

    I have successfully implemented your Mage - WP integration and it works fine. However, I have the My Cart link in the header and, in the shop part, when you add products it displays the number of items in the cart. However, when I go to the articles section which loads wordpress in the middle, I also lose the cart items display in the header. My guess is that this must be due to the loss of cookies when the Magento empty page is retrieved from the WP side.

    Is there any way to preserve the cart items display when browsing the articles part?

    Thanks.
  • @mohan I see no reason why not. This technique is not tied to WordPress by no means. You can take simple .php file without any CMS system, include the class, and to the same.

    The point is simple, just fetch the header and footer area of some site (in this case Magento site).
  • mohan
    Hi Branko,
    can we extend this technique to drupal or joomla?
  • I forgot to mention. It is only problematic in IE.
  • Thanks so much for this tutorial. Very good code. However, I'm having a problem with the 1column.phtml file. When I add the <!-- STARTHeaderContainer --> etc., it throws off the formatting (for all pages using the 1 column layout). When I remove them, the problem goes away. Any idea why this could be happening? I'm out of ideas!

    Thanks so much!
    Matt
  • @thaddeusmt Nice to hear it helped :) Cheers.
  • Thanks for this article, it helped a lot on one of the projects I just completed. In addition to bringing some Magento content into WP, I used this technique to bring some WP content into Magento!

    I had read numerous places about how you can execute Magento code externally (Mage::app();) and access the MAgneto cookie... but in my case Magento was one directory above (/store) the WP install and I could never get it work, so this little hack did the trick instead.

    One note: I couldn't use "file_get_contents" because of my server configuration, but I was able to cURL instead.

    You make a good point about the Link problem with the "Noroute" integration method on the Magento wiki, but I noticed two other problems which kept me from using this method:

    1. The page HTTP response headers are all 404/Not Founds! Bad form to serve the right content and the wrong header.
    2. There is no clean way to get page titles and meta (keywords, description, and canonical urls) from the wordpress pages. If you override _prepareLayout() as well as _toHtml() you can set them, but it’s kind of ugly and difficult to pass some of that information from Wordpress.

    Better to bring Magento content into WP with your technique right now, I think.

    Cheers!
  • James
    Hi Branko, Thanks for sharing the code.

    I tried implementing it but is getting this error:

    Parse error: syntax error, unexpected T_STRING, expecting T_OLD_FUNCTION or T_FUNCTION or T_VAR or '}' in /home/myserver-name/public_html/wordpress/wp-content/themes/lsdnew/functions.php on line 5

    line #5 in function.php is this: "private $_content;".

    Also, it's a bit unclear to me on #4 and #5 in your instruction:


    In #4
    4) Go to WordPress theme folder, open functions.php file, copy paste the class ActiveCodeline_ConnectWM into it.

    I gather the "class ActiveCodeline_ConnectWM" is the second php code correct?


    5) Inside WordPress theme folder, open header.phtml and instantiate a class like:

    and #5 is for this correct (note: you wrote "header.phtml" so for a while I thought it's for magento's header.phtml)?
    "renderHeader();
    ?>"

    Anyway, I tried both method by paste #5 code into functions.php and #4 code into header.php, and I am getting similar error that is complaining
    "private $_content;" with different error message

    Will the server configuration cause the error? I tried implemented the wordpress-magento integration from the tutorial that Varien provided, and was having issue that was caused by server configuration.



    p/s. I have no include function in my wordpress theme.
  • @Pete

    Are you doing some kind of include? Your error should not be related to this article's walk trough steps. Since, at no point have I done include of any of the Magento files into the WordPress. I only retrieved html content from one of the Magento page url's.

    This error often happens when you try directly including Magento files into WordPress or other way round.
  • Pete
  • Thanks for sharing - that was easy to implement and the result is a much better integration than the exiting one... :)
blog comments powered by Disqus
Powered by Wordpress | Designed by Elegant Themes