Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP include doesn't read changes of source file

Tags:

php

My problem (probably doesn't occur in your computer)

I have 2 PHP scripts.

The first script read include the second script to get a variable, change the value, and do file_put_contents to change the second script.

<?php
include('second.php'); // in second.php, $num defined as "1" 
$num ++;               // now $num should be "2"
// Change content of second.php
file_put_contents('second.php', '<?php $num='.$num.'; ?>'); 
include('second.php'); // Now here is the problem, $num's value is still "1"
echo $num;             // and I get an unexpected result "1"
?>

The second script simply contains a variable

<?php $num=1; ?>

I expect the result to be "2", but it seems that the second include doesn't read changes made by file_put_contents.

My first guess was there might be concurrency issue in file_put_contents function, so that the second file was not really changed when the second include executed.

I try to test my guess by changing the first script into this:

<?php
include('second.php');
$num ++;
file_put_contents('second.php', '<?php $num='.$num.'; ?>');
// show the contains of second.php
echo '<pre>' . str_replace(array('<','>'), array('&lt;', '&gt;'),
    file_get_contents('second.php')) . '</pre>'; 
include('second.php');
echo $num;
?>

I was really surprised to find that the result of the program is this:

<?php $num=4; ?>
3

This means that file_put_contents read the file correctly (in other words, the file has really been physically changed), but "include" still use the first value.

My Questions

  1. Can anyone explain this?
  2. Is there any workaround (instead of "sleep()") to make "include" read the changes?

I have read this question and found no answer:

Dynamically changed files in PHP. Changes sometimes are not visible in include(), ftp_put()

Temporary workaround

Using eval seems to be temporary workaround. This is not elegant since eval is usually associated with security hole.

<?php
require('second.php');
$num ++;
file_put_contents('second.php', '<?php $num='.$num.'; ?>');
echo '<pre>' . str_replace(array('<','>'), array('&lt;', '&gt;'), file_get_contents('second.php')) . '</pre>';
require('file.php');
echo $num . '<br />';
eval(str_replace(array('<?php','?>'), array('', ''), file_get_contents('second.php')));
echo $num;
?>

This is the result:

<?php $num=10; ?>
9
10
like image 903
goFrendiAsgard Avatar asked Jun 06 '14 04:06

goFrendiAsgard


People also ask

Why include is not working in PHP?

You need to try the path of functions. php within the system and not its url. Do you have console access? If so just find out what directory is the file in and include it using the full path.

What is include () in PHP?

The Include() function is used to put data of one PHP file into another PHP file. If errors occur then the include() function produces a warning but does not stop the execution of the script i.e. the script will continue to execute. Example. First of all we create a PHP file.

What is the difference between include and include_once in PHP?

The include() function is used to include a PHP file into another irrespective of whether the file is included before or not. The include_once() will first check whether a file is already included or not and if it is already included then it will not include it again.

What is __ DIR __ in PHP?

The __DIR__ can be used to obtain the current code working directory. It has been introduced in PHP beginning from version 5.3. It is similar to using dirname(__FILE__). Usually, it is used to include other files that is present in an included file.


1 Answers

Probably you have OPcache installed and enabled (Since Php 5.5: OPcache extension added), caching your second.php file?

See phpinfo() whether it is true.

If so, use opcache_invalidate('second.php') to invalidate cached file or opcache_reset() to reset all cached files.

<?php
include('second.php');
$num ++;

file_put_contents('second.php', '<?php $num='.$num.'; ?>'); 

opcache_invalidate('second.php');//Reset file cache

include('second.php');
echo $num;//2
?>
like image 66
Zudwa Avatar answered Sep 28 '22 19:09

Zudwa