A customer of mine is reporting an odd problem with some code in their Magento system (Magento is an ecommerce platform written in PHP). I don't have direct access to the system to poke around and debug, so I thought I'd ask Stack Overflow if you've ever seen anything like this.
The error they're occasionally seeing is
Warning: include(O1ucm02owqn3iwwcx5osz2m2.php): failed to open stream:
With a call stack that includes
#0 /Users/theirusername/Sites/project/lib/Varien/Autoload.php(93): mageCoreErrorHandler(2, 'include(O1ucm02...', '/Users/theiruse...', 93, Array)
#1 /Users/theirusername/Sites/project/lib/Varien/Autoload.php(93): Varien_Autoload::autoload()
#2 [internal function]: Varien_Autoload->autoload('o1ucm02owqn3iww...')
#3 [internal function]: spl_autoload_call('o1ucm02owqn3iww...')
#4 /Users/theirusername/Sites/project/app/code/local/Theirname/Commercebug/Model/Observer.php(191): defined('Mage_Core_Block...')
From this, I can deduce that PHP thinks it needs to instantiate a class named O1ucm02owqn3iwwcx5osz2m2. However, I can't figure out why PHP might be doing this. The lines that trigger the error (#4 in the callstack, around line 191 in Observer.php) should be
if(defined("Mage_Core_Block_Template::XML_PATH_DEBUG_TEMPLATE_HINTS"))
{
$path = Mage_Core_Block_Template::XML_PATH_DEBUG_TEMPLATE_HINTS;
}
These lines don't seem to mention any PHP class named O1ucm02owqn3iwwcx5osz2m2 (I say "should be" because the customer's deployed the code themselves, I'm working with them to get a copy to look for potential problems).
Does anyone have any idea what might be going on? Is this a a known PHP bug/issue with some version and/or has anyone seen an issues like this with PHP autoloaders/defined/class constants?
(I'm working with my customer to determine the version of PHP they're running, as well as getting a copy of the files they've deployed to ensure they match what I assume are there.)
The defined() function serves as a compliment to the define() function for named constants. That is to say, constants declared with define can be nicely checked with defined.
However, that code is checking a class constant, which while possible, is less typical. I suspect that the checking is triggering autoloading (just as the use of class_exists can trigger autoloading.) However, the value handed off to the autoloader through use of defined is mangled (perhaps handing off the hash of the z-val for the string.)
I'm wondering if the following change would get things working:
// force PHP to load the class first, then let defined() check for the constant
if(class_exists("Mage_Core_Block_Template") && defined("Mage_Core_Block_Template::XML_PATH_DEBUG_TEMPLATE_HINTS"))
{
$path = Mage_Core_Block_Template::XML_PATH_DEBUG_TEMPLATE_HINTS;
}
As Alan noted in his comment, Zend Guard could be causing an issue, too.
Related
I have an existing, well functional PHP Application. I am looking into an server upgrade which includes moving from PHP5 to PHP7. As far as I can tell from the documentation Smarty3 should be compatible with PHP7. However, when testing this, it turns out that Smarty refuses to compile the templates after the upgrade.
The source of the problem seems to be this line:
$this->smarty->registerPlugin('compiler', 'asset_url', array(&$this, 'asset_url'));
which causes the PHP application to crash like this:
Notice: Array to string conversion in /usr/share/php/smarty3/sysplugins/smarty_internal_templatecompilerbase.php on line 415
Notice: Undefined property: template::$Array in /usr/share/php/smarty3/sysplugins/smarty_internal_templatecompilerbase.php on line 415
Fatal error: Uncaught Error: Function name must be a string in /usr/share/php/smarty3/sysplugins/smarty_internal_templatecompilerbase.php:415
Stack trace:
#0 /usr/share/php/smarty3/sysplugins/smarty_internal_templateparser.php(3585): Smarty_Internal_TemplateCompilerBase->compileTag('asset_url', Array)
#1 /usr/share/php/smarty3/sysplugins/smarty_internal_templateparser.php(4413): Smarty_Internal_Templateparser->yy_r32()
#2 /usr/share/php/smarty3/sysplugins/smarty_internal_templateparser.php(4515): Smarty_Internal_Templateparser->yy_reduce(32)
#3 /usr/share/php/smarty3/sysplugins/smarty_internal_smartytemplatecompiler.php(118): Smarty_Internal_Templateparser->doParse(3, '}')
#4 /usr/share/php/smarty3/sysplugins/smarty_internal_templatecompilerbase.php(283): Smarty_Internal_SmartyTemplateCompiler->doCompile('<!DOCTYPE html>...')
#5 /usr/share/php/smarty3/sysplugins/smarty_internal_template.php(197): Smarty_Internal_TemplateCompilerBase->compileTemplate(Object(Smarty_Internal_Template))
#6 /usr/share/php/smarty3/sysplugins/sm in /usr/share/php/smarty3/sysplugins/smarty_internal_templatecompilerbase.php on line 415
The suspicious line 415 looks like this:
$function = $this->smarty->registered_plugins[$plugin_type][$tag][0];
if (!is_array($function)) {
return $function($new_args, $this);
} elseif (is_object($function[0])) {
return $this->smarty->registered_plugins[$plugin_type][$tag][0][0]->$function[1]($new_args, $this); <- Crash here!
} else {
return call_user_func_array($function, array($new_args, $this));
}
I assume this is some fundamental difference between PHP5 and PHP7 which is biting me, but I can't seem to figure out what it is. Could somebody give me a few pointers to how to sort this out?
If you're using an older version of Smarty, you might want to update. There were some fixes added in 3.1.28 for PHP 7 compatibility that will probably help with this.
See https://github.com/smarty-php/smarty/blob/master/change_log.txt
The explanation of this issue (besides the most common ones like "you have an outdated version") is that in PHP 7 it has been changed the way how code is parsed. In your case:
$this->smarty->registered_plugins[$plugin_type][$tag][0];
is parsed differently in PHP 5 and 7:
PHP 5: $this->smarty->{registered_plugins[$plugin_type][$tag][0]};
PHP 7: ($this->smarty->registered_plugins)[$plugin_type][$tag][0];
You can try fixing these code pieces by placing braces and brackets to indicate the parser what are your exact intentions, but I'd suggest you to upgrade Smarty.
I'm trying to understand unexpected behavior by PHPstorm. I've two files without any include or required definitions.
// file1.php
<?php
$var = new class1();
// file2.php
<?php
class class1 { }
I would expect that class1 is undefined in file1, because file2 is not included. But phpstorm shows no warning. CTRL-B jumps to the declaration in file2. The option "Ignore include and require statements" is unchecked. Could someone explain this to me?
phpstorm doesn't know everything about your context. it is possible that the files are required by some other file one after another so everything will just work. Also there is a good chance, that you are using autoloader/composer (who doesn't?) which will take care of the issue.
So, I think they wouldn't consider this an error, as they wouldn't be able to properly filter false-positives if they enabled such warning
This is most likely a bug in PHPStorm itself, since PHP throws an exception.
Fatal error: Class 'class1' not found in /srv/www/htdocs/swaggityswoogityswoo/f1.php on line 5 Call Stack: 0.0003 629360 1. {main}() /srv/www/htdocs/swaggityswoogityswoo/f1.php:0
Since I upgraded to the latest versions, it seems to behave strange. For example, when i try to merge a file where the deployed adn the local file both contain contain 'text-align: left', he wants to merge it into 'text-align: center'.
Just wait until they release another version, maybe they'll be able to fix this bug.
I'm analyzing some PHP code which is running on a server I don't have full access to. I can read the phpinfo though. The code seems to run fine on the server. In my local environment I just can't get the code to run as I get a "Catchable Fatal Error" at some call of a method using type hinting.
someMethod(string $str) {
// Do something...
}
The error says the following: "Argument 1 passed to ... must be an instance of path\of\namespace\string, string given ...".
There is no use keyword with a string class nor can I find anything trough a grep command in the folders of the development environment.
Are there any PHP modules, extensions that can make such a type hinting work? The server and my development environment are using PHP 5.4.25.
What could the live system possibly provide to make such code run? Might it use some other programming language based on PHP like Hack? The rest of the code is pretty straight PHP!
You mention that there is no use statement or namespace declaration that alludes to a 'string' class in the code. Does the code use an Autoloader?
Two possible issues at hand here:
Paths - It is possible that the live environment has another path set up, and/or that a file/class is being loaded/searched for via this 'other path' (outside the code you may be looking at).
Error Handling - Another possible cause is if there is an error handler in the production environment that always returns true.
I had this exact issue where a type-hint wasn't resolving in development, but I didn't realize until we pushed it live and the error handler was no longer registered.
Obviously a fatal parse error can not be stopped, but it turns out a catch-able error can be ignored if the error handler returns true. And this is what I am putting my money on in your case.
Additionally, it is very important to note that there is no way to type-hint a scalar, as one user pointed out.
A simpler way to say it is "it is not possible to type-hint anything that can be represented by a string." This is due to the way in which PHP handles it's more primitive variables, they can all be type-cast to one another, and therefore (because 1, "1" and true can all be == 1, == '1' and == true) it is not actually possible for the interpreter as it is written to actually catch and enforce scalar type-hints.
Answer this question: Is that variable supposed to be $str = "something"; or $str = new string(); (ie, a string or an object)?
If it is supposed to be a string, remove the type-hint, as nothing in PHP allows this support (save for HHVM, but you would know this if you were using it).
Since you say you do not have access to the code, I suggest notifying someone who does.
I have an application that is built around Wordpress. It is fairly bespoke but none-the-less I still leverage and appreciate a lot of what comes with Wordpress too. Now what I'm trying to do is provide a RESTful API that will work off of the Wordpress database. I'm using an open source product called Restler that I'm very happy with so far which makes providing this service very easy with PHP but I'd like to have this PHP load the Wordpress machine so that I can leverage my already built code more easily as well as the handy Wordpress functions.
With Restler you have a PHP class file that defines the interface; I added the import at the beginning to load the WP environment:
<?php
include "AddWordpress.php"; // loads wordpress in AJAX mode
/**
* All actions that the system will process through this service.
*
* #package lg-api
* #return json LG_JSON_Activity
*/
class Actions {
/**
* LIST action types
*
* List all the action-types available
*
* #url GET /
*/
function list_actions() {
$actions = new LG_TAX_Action();
$action_list = $actions->dataset();
return "\n" . json_encode($action_list) . "\n\n";
}
}
where AddWordpress.php is (debugging set on for dev env):
<?php
error_reporting(E_ALL);
$site_name='yoursite';
$site_domain='www.yoursite.com';
/**
* Construct a fake $_SERVER global to get WordPress to load a specific site.
* This avoids alot of messing about with switch_to_blog() and all its pitfalls.
*/
$_SERVER=array(
'HTTP_HOST'=>$site_domain,
'REQUEST_METHOD'=>'GET',
'REQUEST_URI'=>"/{$site_name}/",
'SERVER_NAME'=>$site_domain,
);
// Remove all our bespoke variables as they'll be in scope as globals and could affect WordPress
unset($site_name,$site_domain);
// Pretend that we're executing an AJAX process. This should help WordPress not load all of the things.
define('DOING_AJAX',true);
// Stop WordPress doing any of its normal output handling.
define('WP_USE_THEMES',false);
// turn on debugging
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
// Load WordPress - intentionally using an absolute URL due to issues with relative paths on the CLI.
include "/[path-to-root-www]/wp-load.php";
This approach is great for creating command-line test files before jumping into the real code and testing through a browser but for some reason when I run it with Restler I get a slew of errors such as this:
Notice: is_404 was called incorrectly. Conditional query tags do not work before the query is run. Before then, they always return false. Please see Debugging in WordPress for more information. (This message was added in version 3.1.) in /[path-to-www-root]/wp-includes/functions.php on line 294
Notice: is_home was called incorrectly. Conditional query tags do not work before the query is run. Before then, they always return false. Please see Debugging in WordPress for more information. (This message was added in version 3.1.) in /[path-to-www-root]/wp-includes/functions.php on line 2944
Notice: is_search was called incorrectly. Conditional query tags do not work before the query is run. Before then, they always return false. Please see Debugging in WordPress for more information. (This message was added in version 3.1.) in /[path-to-www-root]/wp-includes/functions.php on line 2944
Notice: is_archive was called incorrectly. Conditional query tags do not work before the query is run. Before then, they always return false. Please see Debugging in WordPress for more information. (This message was added in version 3.1.) in /[path-to-www-root]/wp-includes/functions.php on line 2944
Notice: is_404 was called incorrectly. Conditional query tags do not work before the query is run. Before then, they always return false. Please see Debugging in WordPress for more information. (This message was added in version 3.1.) in /[path-to-www-root]/wp-includes/functions.php on line 2944
Notice: is_tag was called incorrectly. Conditional query tags do not work before the query is run. Before then, they always return false. Please see Debugging in WordPress for more information. (This message was added in version 3.1.) in /[path-to-www-root]/wp-includes/functions.php on line 2944
Notice: is_search was called incorrectly. Conditional query tags do not work before the query is run. Before then, they always return false. Please see Debugging in WordPress for more information. (This message was added in version 3.1.) in /[path-to-www-root]/wp-includes/functions.php on line 2944
Notice: is_category was called incorrectly. Conditional query tags do not work before the query is run. Before then, they always return false. Please see Debugging in WordPress for more information. (This message was added in version 3.1.) in /[path-to-www-root]/wp-includes/functions.php on line 2944
If I were to simply add the following code to the bottom of the class file and then run it from the command line it works without a problem:
$foo = new Actions();
echo $foo->list_actions();
Can anyone give any pointers on why this might be occurring?
UPDATE
I've changed the error handling to give me a stack trace and get the following:
#0 /[path-to-www-root]/wp-includes/query.php(708): _doing_it_wrong('is_404', 'Conditional que...', '3.1')
#1 /[path-to-www-root]/wp-content/themes/pagelines/includes/library.functions.php(68): is_404()
#2 /[path-to-www-root]/wp-content/themes/pagelines/includes/library.options.php(43): is_pagelines_special(Array)
#3 /[path-to-www-root]/wp-content in /[path-to-www-root]/wp-includes/functions.php on line 2944
So the initial call seems from my theme making calls into query.php. It's more information but I'm not sure how much insight it really provides as I'm pretty sure the way to solve this is to tackle why initial state of the import varies between running from the command line versus trying to trace back all the problems occuring from the poor state it started in.
if (class_exists('PhpThumb')) {
$pt = PhpThumb::getInstance();
$pt->registerPlugin('GdReflectionLib', 'gd');
}
if (in_array('PhpThumb', get_declared_classes())) {
$pt = PhpThumb::getInstance();
$pt->registerPlugin('GdReflectionLib', 'gd');
}
Either of these codes blocks throw the following error: "PHP Fatal error: Class 'PhpThumb' not found"
Can anyone explain why? Is this a bug in PHP?
I've encountered the same bug. In my case problem was due to mixed Russian and English letters in class name which looks similar.
I had a legacy code running under a newer version of PHP (5.3.10). I had some require_once() statements that was not doing their job. As I could change, I changed them do include() and it worked again.
I guess it have something to do with the PHP version, because running under a previous version the website was ok.
This happened for me when I was requiring a file not needed by a phpunit class I was running. The file was there, but I got the error.
Yet for a test that does need that class, the same include call works.
My work around was to have 2 config files, where 1 requires that class file and the 2nd file doesn't. So when not needed, I use the latter.
A little clunky with 1 extra small file (that I shouldn't have to create .. cse' la vie), but unblocks the issue here
After spending few hours on practicing with this mistakefullish fatal error...I've admitted that this function doesn't work with SPL autoload! And I've finally found a solution :
I replace 'class_exists()' by 'file_exists()' with a little bit more process to find out the real path of the class file (my classes have the same name as their filename).
Hope it helps.