1

So, I just ran into this and scratched my head quite a few times and since the Magento bug tracker is dead, let's do it here.

Symptom:

Class 'MyNameSpace_MyModule_Helper_Data' not found in /var/www/example.com/app/Mage.php on line 547

This happens when a script is run, based on shell/abstract.php. The site works fine, so I know that the helper/model/block is working. What's going on?

3

Short version: You have php_value include_path "some_path" in /var/www/example.com/.htaccess.

Long version:

Let's take a look at shell/abstract.php:

    82      public function __construct()
    83      {
    84          if ($this->_includeMage) {
    85              require_once $this->_getRootPath() . 'app' . DIRECTORY_SEPARATOR . 'Mage.php';
    86              Mage::app($this->_appCode, $this->_appType);
    87          }
    88          $this->_factory = new Mage_Core_Model_Factory();
    89  
    90          $this->_applyPhpVariables();

At line 85 we include app/Mage.php. Among other things, just including this file sets up php's include_path to match Magento's architecture and configures the autoloader (lib/Varien/Autoload.php).

At line 90 the function _applyPhpVariables() is called. This is a mini-htaccess parser, that isn't well thought through, for two reasons:

  1. It doesn't account for .user.ini that can do the same for CGI based SAPIs,
  2. It doesn't protect against foot shooting

Number 1, I won't address here, but it's not too hard to do this, since we have parse_ini_file. Number 2 is the root cause of the problem you're seeing:

   114      protected function _applyPhpVariables()
   115      {
   116          $htaccess = $this->_getRootPath() . '.htaccess';
   117          if (file_exists($htaccess)) {
   118              // parse htaccess file
   119              $data = file_get_contents($htaccess);
   120              $matches = array();
   121              preg_match_all('#^\s+?php_value\s+([a-z_]+)\s+(.+)$#siUm', $data, $matches, PREG_SET_ORDER);
   122              if ($matches) {
   123                  foreach ($matches as $match) {
   124                      @ini_set($match[1], str_replace("\r", '', $match[2]));
   125                  }
   126              }

This looks for any line in magento_root/.htaccess that defines php_value directives in a way that mod_php understands.

The problem is that app/Mage.php just went through all the trouble of setting up the include path, yet if we have php_value include_path "/some/cool/app" in our .htaccess, we will undo all that work in line 124.

So, if our shell script fetches a helper class, like:

$helper = Mage::getHelper('mynamespace_mymodule');

Varien/Autoload won't be able to find it.

The real fix is to teach _applyPhpVariables to never mangle include_path:

--- a/shell/abstract.php
+++ b/shell/abstract.php
@@ -121,6 +121,10 @@ abstract class Mage_Shell_Abstract
             preg_match_all('#^\s+?php_value\s+([a-z_]+)\s+(.+)$#siUm', $data, $matches, PREG_SET_ORDER);
             if ($matches) {
                 foreach ($matches as $match) {
+                    // Never ever set include_path. app/Mage.php already did 
+                    // this and took the .htaccess value into account.
+                    if( $match[1] == 'include_path' )
+                        continue;
                     @ini_set($match[1], str_replace("\r", '', $match[2]));
                 }
             }

Hope this saves someone some time / hair-pulling.

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.