0

Magento block in before_body_end with form_key being cached

We use a block for login form data in the block before_body_end. Only since some time we have seen this block is cached and the form_key has a mismatch when wew submit it to Magento.

question: how can we (really) prevent the block below from being cached?

<catalog_category_default>
    <reference name="before_body_end">
    <block type="core/template" name="autologin" as="autologin">
        <action method="setTemplate" ifconfig="webmyneautologin/webmyneautologin_group/category"><template>autologin/autologin.phtml</template></action>
        <action method="setCacheLifetime" />
    </block>
    </reference>
</catalog_category_default>
0

try adding below code

<catalog_category_default>
    <reference name="before_body_end">
    <block type="core/template" name="autologin" as="autologin">
        <action method="setTemplate" ifconfig="webmyneautologin/webmyneautologin_group/category"><template>autologin/autologin.phtml</template></action>

        <action method="unsetData"><key>cache_lifetime</key></action>
        <action method="unsetData"><key>cache_tags</key></action>
    </block>
    </reference>
</catalog_category_default>
0

Depends what you want to do. We use block caching for almost all our blocks. So what we do is replace the Magento Form key with example: "$$FORMKEY$$" and than CACHE IT !

Then the onlything you need is to replace this with the REAL formkey just before sending back to client.

  <frontend>
    <events>
      <controller_front_send_response_before>
        <observers>
          <gn_blockcache>
            <type>singleton</type>
            <class>gn_blockcache/observer</class>
            <method>controllerFrontSendResponseBefore</method>
          </gn_blockcache>
        </observers>
      </controller_front_send_response_before>
    </events>
  </frontend>

This is the replace code:

    /**
     * Fix form_key in html coming from cache
     *
     * @param Varien_Event_Observer $observer
     *
     * @return boolean
     */
    public function controllerFrontSendResponseBefore($observer) {
        /** @var Zend_Controller_Response_Http $response */
        /** @noinspection PhpUndefinedMethodInspection */
        $response = $observer->getFront()->getResponse();
        $headers  = $response->getHeaders();
        $isHtml   = true; // Because it's default in PHP
        foreach ($headers as $header) {
            if ('Content-Type' == $header['name'] && false === strpos($header['value'], 'text/html')) {
                $isHtml = false;
                break;
            }
        }
        if ($isHtml) {
            $html = $response->getBody();

            /** @noinspection PhpUndefinedMethodInspection */
            $newFormKey      = Mage::getSingleton('core/session')->getFormKey();
            $templateFormkey = '$$FORMKEY$$';
            $html            = str_replace($templateFormkey, $newFormKey, $html);
            $response->setBody($html);
        }

        return true;
    }

You can also do this on the "afterToHtml()" of the block it selfs, but we have decided for a generic sollution that works for all blocks with "$$FORMKEY$$".

How to inject the $$FORMKEY$$ constant (cart example):

class Gn_BlockCache_Helper_Cart extends Mage_Checkout_Helper_Cart {

    /** @var Gn_BlockCache_Helper_Data */
    protected $helper;

    public function __construct() {
        $this->helper = Mage::helper('gn_blockcache');
    }

    /**
     * Add to url: /form_key/$$FORMKEY$$/   <== Will be replace on "controller_front_send_response_before"
     *
     * @param Mage_Catalog_Model_Product $product
     * @param array                      $additional
     *
     * @return string
     */
    public function getAddUrl($product, $additional = array()) {
        if ($this->helper->getEnabledCartFormkey()) {
            return parent::getAddUrl($product, array_merge([Mage_Core_Model_Url::FORM_KEY => '$$FORMKEY$$'], $additional));
        } else {
            return parent::getAddUrl($product, $additional);
        }
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.