PHP require_once called more than once - php

I posted the solution as an answer
I'm running into an odd issue while migrating some PHP code to a new server. The old server is running PHP 5.3 (x86) and the new server is running PHP 7.0 (x64). Both are running on IIS 7.5.
The code causing the issue has been in production without issues for almost three years. It runs fine on the current production server as well as two development systems. All three are running PHP 5.3 (x86).
These errors do not occur when I use PHP 5.3 (x86) on the new server.
A shared file (named _common_funcs.php) contains common functions that are called from many scripts. Since some of these scripts can interact I use require_once('_common_funcs.php') to include the file. This is approach pretty basic.
On the new server the first time a the script runs it generates a 'Cannot redeclare' error. Refreshing the page does not display the error - it displays the page as expected. For example:
//localhost/app/display_account.html?account=123456 generates the error.
//localhost/app/display_account.html?account=123456 again does not display the error.
Restarting the IIS server causes the error to be generated again on the first run.
Now for the odd part. Note the capitalization of the drive letters in the error below:
Cannot redeclare acct_has_graduated() (previously declared in D:\app_directory\includes\_common_funcs.php:2061) in d:\app_directory\includes\_common_funcs.php on line 2061
If I hardcode the full path in one require_once() line, and use a lowercase 'd', then the error in the log will swap the capitalization. This results is 'd:\app ...' and 'D:\app ...'.
If I hardcode both calls that happen to get called when this script runs with the error is not generated no matter what mix of capitalization I use.
And to make this just a little more interesting, the acct_has_graduated() function is the last function in the _common_funcs.php file. But if I disable OpCache in php.ini I get the following error:
Cannot redeclare update_ledger() (previously declared in D:\app_directory\includes\_common_funcs.php:7) in d:\app_directory\includes\_common_funcs.php on line 42
Two things of note: update_ledger() is the first function in the _common_funcs.php file, and "line 42" is the closing bracket of the update_ledger() function (line 7 is the declaration).
If anyone can point me in the right direction on this I would greatly appreciate it.

Solution
I found the issue and the file is absolutely being included twice. This happens under a specific set of circumstances. It affects PHP 7.0 but does not affect PHP 5.3. I did not test any other versions of PHP.
This scenario is certainly an outlier, but here it is:
I have a directory symlink from c:\inetpub\wwwroot\app_location to d:\app_location.
The IIS configuration for this site points to c:\inetpub\wwwroot\app_location.
The application's configuration file defines the include_path using c:\inetpub\wwwroot\app_location as the base.
All the files for this site are located in d:\app_location.
Using the configuration above all entries in the application's log files (tracking, audit, error and backtrace) show D:\app_location as the base location of all files.
Calling require_once() on a file more than once, while allowing the include_path to resolve the location of the file in one or both of the calls, generates the 'Cannot redeclare' error. The error reports the opposite capitalization of the 'D:' drive letter (see error text in the post above).
Changing the base of the include_path (#3 above) to d:\app_location resolved this issue.

The question is very simple.
require_once('D:\file.php');
require_once('file.php');
will run twice, because you included the absolute path!
Solution
Use relative path
require_once('../core/file.php');

Related

Laravel projects stopped suddenly

Before you continue to read - the issue has been fixed
Well... this is kinda weird.
I'm working on a web app for some friends. I have a working version uploaded to their hosting, and, suddenly, it stopped working a couple of days ago.
I haven't added anything or changed anything on the server. There is no error, simply the app stopped loading and a blank html page is loaded instead.
I've traced the problem until /vendor/composer/autoload_real.php file.
In the end of the static class inside this file, there is a loop where several other files are being included (actually requested), I've checked that when it tries to request /vendor/laravel/framework/src/Illuminate/Foundation/helpers.php, the system stops. Obviously, I've checked that the file is there, and it isn't been touched.
Well, I'm positive I've didn't changed anything on this part of the app (it's core framework, and I usually don't mess up inside), but just of a sudden it stopped working.
The working copy on my computer just works fine. I've uploaded my copy of helpers.php, but nothing changed.
Anyone had experienced similar issues recently? Anyone has any idea about how to fix it?
EDIT: It's been several days since I could check on this for the last time.
Now I've been tracing raw php execution on /vendor/laravel/framework/src/Illuminate/Foundation/helpers.php file. This is, I've started echoing messages and trying to execute just this file, to see where code execution is stopped.
I know this is very crappy debugging, but I haven't access to apache nor I can restart it, and it seems there is no easy way to get an error code without this.
So patiently trying I've reached two points where execution stops on this file:
Creation of factory method
if (! function_exists('factory')) {
/**
* Create a model factory builder for a given class, name, and amount.
*
* #param dynamic class|class,name|class,amount|class,name,amount
* #return \Illuminate\Database\Eloquent\FactoryBuilder
*/
function factory()
{
$factory = app(EloquentFactory::class);
$arguments = func_get_args();
if (isset($arguments[1]) && is_string($arguments[1])) {
return $factory->of($arguments[0], $arguments[1])->times($arguments[2] ?? null);
} elseif (isset($arguments[1])) {
return $factory->of($arguments[0])->times($arguments[1]);
}
return $factory->of($arguments[0]);
}
}
and creation of mix method
if (! function_exists('mix')) {
/**
* Get the path to a versioned Mix file.
*
* #param string $path
* #param string $manifestDirectory
* #return \Illuminate\Support\HtmlString|string
*
* #throws \Exception
*/
function mix($path, $manifestDirectory = '')
{
return app(Mix::class)(...func_get_args());
}
}
In both cases func_get_args is involved... I haven't a specific error, but I have the tingling that the problem is related somewhat to the fact that this function isn't returning anything.
EDIT2: Ok, I tried php artisan and composer commands suggested on answers to no success. The issue is still there.
I've also deleted the logs and checked that no new log was created while trying to load the site.
I've tried a clean laravel install from scriptaculous on a new directory (I've done this when I first uploaded the site, it worked perfectly for several months) and this new install doesn't reach the front page neither. A blank page (on Firefox) or a 500 error (on Chrome) is shown instead.
I forgot to mention an important data. My app is sharing space with a wordpress instance. The wordpress is installed on public_html, and my site on public_html/mySiteDirectory. This hasn't supposed any problem so far more than make me tweak lightly .htaccess file to make routing work fine.
There is also a phpbb forum sharing space on it's own directory inside public_html.
I wonder if any of those could have somewhat been upgraded and produced this strange outcome.
Also... laravel app_debug is enabled on .env file since the beginning, but never showed anything. This seems to be something that fails before laravel framework is fully loaded.
EDIT 3: IT'S FIXED.
Well... first of all, let me thank you all for your help. Actually there wasn't one answer that fixed the problem, but many of you suggested to use phpInfo() to check php version which ultimately led to the true problem.
Yes... surprisingly, although php -v on terminal showed php 7.2 running on server, and cpanel php management tools showed also php 7.2 installed and running, when I used phpInfo(); php 5.6 was showed on the response.
I used the own cpanel tools to make an upgrade/downgrade to 7.3 and again to 7.2 and et voilá phpInfo(); shows 7.2 and the page is again up and running.
I'll try to share the reward between several answers (don't know if something like that is even possible), and will +1 every answer suggesting phpInfo(); as it showed as the key to fixing this problem.
If I cannot share the reward I'll accept as final answer the one from Don't Panic, as it was the one that convinced me that there was a problem with php versions.
If you look at the code in the functions you have traced the problem to, both contain interesting or less-common PHP features:
factory() includes ??, the null coalescing operator. This was introduced in PHP 7.0.
I see in a comment you added to another answer that you are using PHP 7.2. This question describes Laravel failing in factory(), because even after upgrading to PHP 7.2, and phpinfo() showing 7.2, Apache was still using PHP 5.6. This seems unlikely, but when all else fails ... ?
mix() includes ..., the spread or splat operator. This was introduced in PHP 5.6, but there are reports of it failing in Laravel with 7.x due (AFAICT) due to mismatches between the PHP versions Apache and the CLI are using.
Considering you mentioned you uploaded the code from your local machine (rather than using php composer install), and that CPanel tends to update PHP automatically and silently, this seems like a possibility - there are 4 PHP versions in play (CLI/web on your machine, and CLI/web on server), and they all need to be in sync.
As a side note, as you've already discovered you are really working blind without the logs. Either the PHP and/or Apache logs will give you more info, typically describing exactly the problem, and save you having to manually trace things as you've been doing. If those logs aren't showing anything, maybe PHP isn't configured to log errors - try enabling that.
It probably depends on your CPanel version and config, but standard locations for your logfiles are typically:
Apache access log: /usr/local/apache/domlogs/<your-username>/
Apache error log: /usr/local/apache/logs/error_log
PHP error log: /home/<your-username>/public_html/error_log
Start wtih composer dumpautoload. Then run php artisan optimize:clear. Re-upload the whole site and you should be good to go. I have experienced a very similar issue. Do you run a pipeline on the server or are you just FTP-ing the site up? Are you able to run composer on the server and the same for artisan? If you can, you need to those commands there are as your cache is often based on your host computer drives and will fail in prod.
Simply replacing the file might not be helpful. Try enabling the error log or check if you are able to reach this file bootstrap/app.php. If yes it means there is no problem in the composer. Try checking the version of PHP installed and if it is compatible with your Laravel. Try checking PHP Error Log. It might be helpful.
Ok I should mention a few things
1: Go to storage/logs directory and delete all *.log files then you refresh the web page and you'll check out to see for any log file if there is no log file it means it's related to server configuration and etc. if there is a log file you read it and you post it in here
2: Did you pull the code on cpanel by console command using version control system like git or svn or you just uploaded it in a classic way, if you indeed pulled it with VCS you may did a composer update instead of composer install which will updates all packages as possible as defined in composer.json file and you may have got a higher version of vendor than your local and something may broke in there.
3: You may have a different php version on server vs your local which many times casing real problems.
I can't tell for sure until you post your log file here
So here is what i would have done.
If it is possible simply turn0on debugging, this will show you the error in the web browser itself (you can do that from .env file)
You can also read the laravel log file for errors as mentioned earlier.
If you do not want to do this, run the following commands
PHP artisan cache:clear
PHP artisan route:cache
PHP artisan config:cache
PHP artisan clear-compiled
PHP artisan optimize
If you could share more details that would help...
Have you checked permissions and ownership for storage and bootstrap/cache folder?
these permissions need to be set for the app to work
sudo chgrp -R www-data storage bootstrap/cache
sudo chmod -R ug+rwx storage bootstrap/cache
I tried everything and nothing worked. The best solution for me was that I deleted cpanel files and reuploaded all the codes.

is there a difference in php with defines from version 5 to version 7?

I migrated to godaddy for a perma-host. Now much of my code is not working.
For years I have used the following code in my gaming site. but now I want to move it to a more permanent host. I've been using php v5 with no issues, never had a reason to change. However I did finally migrate to PDO. With that said, here is the .ini file I use:(keep in mind, it is a giagantic ini file, but the following are what is important that is NOT working..
SQL_TYPE=mysql
HOST=localhost
USER=incognito
PASS=topsecret
DATABASE=mycooldb
to pull it for defines:
$defines = parse_ini_file('defines.ini');
foreach($defines as $field=>$data)
define($field, $data);
Now there is an error when I use godaddy (which i believe is up to v7 php).
If I run
die('host = '.HOST) // gives HOST
On my local server
die('host = '.HOST) // gives localhost - as it should
Why is this happening? I supposed I could line by line the defines, but they have worked for years the way I have it.
Thanks for any input.
Since it appears I have 2 problems, I will answer what addresses my first issue for this topic and close it:
There was not a problem with the DEFINES, but instead, my .ini files that stored the information for the variables that create the DEFINES.
In this ini file, I originally had "#" for comments as was accepted at the time, (which was what I was used to see: https://en.wikipedia.org/wiki/INI_file#Format)
However, not catching some of the "depreciation errors" I got over the years from PHP v5.3 - as I was stubborn changing - "#" was among those warnings. When PHP 7 finally came, the "#" no longer worked as comments, and thus my DEFINES variable ceased to work, as the script was stuck at the first commented line.
Conclusion: As far as my error, there is NO difference in the defines between PHP: v7 and v5, however the use of "#" as comments caused the error.
Thank you #Magnus Eriksson and #Calimero for the tip to display errors to catch it.

Why does my script return: HTTP ERROR 500

There is a folder on my apache server containing several php scripts. All the php scripts in this folder work except for 1. All the php scripts including the script that doesn't work have the same rights.
When I run the script in my browser I get this error:
HTTP ERROR 500
Details that may be helpful:
PHP Version 7.0.11
Apache/2.2.15 (CentOS)
An Apache status code of 500 means "internal server error". Without seeing the code that is producing this error it is hard to say what is causing it but the first things to check are server configuration and your .htaccess file. Make sure your server is running properly then check your .htaccess file as a bad rule can force some types of PHP to malfunction. As #RiggsFolly stated, it is also possible that the problem is some very poorly written PHP which can be tested by replacing it with a simple program like:
<?php
echo "test";
?>
SOLUTION: In my case the problem of 500 error was the upgrade from php 5.x to 7; BUT: I imagine this error can come from many other reasons, so if it does not apply, good luck finding the other solutions. In this case, it worked - and the solution is to rewrite the code or downgrade to old PHP version until you re-code the incompatible parts.
EXPLANATION / DEBUGGING PROCESS: After several tests to identify what is happening (commenting parts of code, testing functions, reading documentation), I found that deprecated functions from previous versions of PHP will generate a 500 Error.
For example, in a script written for PHP<7 you may still have old mysql queryes like mysql_connect, and once your server is updated to 7 (and you must use mysqli), this script will throw 500 error.
I imagine this happens to any other function that became deprecated.
In your case, my bet is most of the scripts are compatible with 7, one is not.

Zend FR finfo error Warning: string extension `B' invalid

I have problems after updating Zend FR to 1.11
Mimetype file checking generates:
Warning: string extension `B' invalid
It looks like cause of problems the string in the Zend_Validate_File_MimeType
$finfo = finfo_open(FILEINFO_MIME_TYPE, $file);
I have created simple test case
$finfo = finfo_open(FILEINFO_MIME_TYPE, '/usr/share/misc/magic');
echo finfo_file($finfo, PUBLIC_HTML_PATH . '/images/missing.png');
finfo_close($finfo);
And i got same error :(
finfo_open(FILEINFO_MIME_TYPE, '/usr/share/misc/magic'); //generates: Warning: string extension `B' invalid.
My OS: Kbuntu 10.10
Where am i wrong?
Ran into the same error message ("Warning: string extension w' invalid in Command") as Mike Purcell, but the fix for it was different.
On our servers we had a /usr/share/misc/magic and a /usr/share/misc/magic.mgc file. The magic.mgc file had been compiled from the magic file, but PHP still wasn't happy talking directly to the /usr/share/misc/magic file (we'd shifted to that file as part of debugging that the magic.mgc file needed updating).
The fix for us was changing our putenv line back to the magic.mgc file:
putenv('MAGIC=/usr/share/misc/magic.mgc');
Then, magic-ally :-) , the whole mime-type detection system started working again.
This may not pertain to your EXACT issue, but it did resolve the issue I was having which resulted in a very similar error message: "Warning: string extension w' invalid in Command".
For us, we have a heterogenous setup where some servers are still running php 5.2 and others running php 5.3. On the 5.2 boxes the magic file resides in /usr/share/file/magic, but on the 5.3 boxes the file resides in the default path of /usr/share/misc/magic. Apparently someone tried to reconcile these path differences by symlinking the 5.2 path so the codebase could be php version agnostic. But according to some comments posted on PHP site regarding symlinks to the magic file, it will result in unexpected behavior, which of course was resulting in the aforementioned error message.
So be sure the path you are passing is to the actual magic file, and not a symlink, and see if that resolves your issue.
Depending on your PHP version the magic format may be updated. This is documented in a note at http://php.net/manual/en/function.finfo-open.php
run php -v to see your version
I got the same error when pointing to an older magic file in our source tree, and resolved it when pointing to a newer magic file from my current linux distro
I had this error in Laravel (minus Zend FR, of course). Running PHP 5.3.21 on a Windows box with IIS.
Finding very little info online I was close to giving up. It worked initially when I followed instructions in the comments on PHP.net, which were basically to add fileinfo.dll to your PHP installation, and to also download the relevant magic files and point an environment variable to them.
There was some initial confusion until I realised I didn't actually have php_fileinfo.dll, so as well as adding it to the php.ini file, I had to download the file itself and add it to my ext directory.
Now what really had me stuck, was that it worked initially. The next day it didn't. To cut a long story short, it didn't need the environment variable, MAGIC. The reason this had me stuck, is because I had tried every possible scenario, but once the environment variable had been set, it had been set. And I had to restart the Windows server after removing it, to unset it. Once I did this it worked perfectly.

PHP "require_once" says it can't find a file in the directory

I'm debugging some PHP code written by an outsourcing company (I'm not a PHP guy at all but know the basics; we have an offshore team of PHP developers working for us on this project) that's not working; the code is supposed to be called every 30 minutes by a cron job but its not firing. I tried to run the PHP script via the command line to test if it's working, but it's giving me the following (anonymized) errror:
PHP Fatal error: require_once(): Failed opening required '/myapp/_lib/_classes/MySql.php' (include_path='.:/usr/share/pear:/usr/share/php') in /var/www/html/myapp/_lib/_base/common.inc.php on line 6
However, the file /var/www/html/myapp/_lib/_classes/MySql.php exists under the proper directory. I'm missing something simple, I'm sure, but like I said I know really nothing beyond the bare basics of PHP and I really need to get this service up and running.
EDIT: The code is using the __autoload() function with all classes in /_lib/_classes
if you start a file name with a slash, it means it's an absolute path. try instead:
require_once('/var/www/html/myapp/_lib/_classes/MySql.php');
Case sensitivity maybe? I've had that problem before.
I'm guessing it's a permissions issue - make sure both your account (for testing purposes) and whatever account cron is going to run your script under (quite possibly yours, but maybe a different one) have read privileges on the file.
Also: the path for the include says /myapp/_lib/_classes/MySql.php, whereas it exists in /var/www/html/myapp/_lib/_classes/MySql.php. Can you change the include to reference the full path?
As said, casing and in addition the correct permissions to access that file are needed.

Categories