Mise à jour
J'ai résolu le problème et publié une réponse. Cependant, ma solution n'est pas idéale à 100%. Je préfère de loin ne retirer que symlink
le cache
avec clearstatcache(true, $target)
ou clearstatcache(true, $link)
mais cela ne fonctionne pas.
Je préfère également empêcher la mise en cache des liens symboliques en premier lieu ou supprimer le lien symbolique du cache immédiatement après l'avoir généré. Malheureusement, je n'ai pas eu de chance avec ça. Pour une raison quelconque, la clearstatcache(true)
création d'un lien symbolique ne fonctionne pas, il est toujours mis en cache.
Je remettrai volontiers la prime à toute personne qui pourra améliorer ma réponse et résoudre ces problèmes.
Éditer
J'ai essayé d'optimiser mon code en générant un fichier à chaque clearstatcache
exécution, de sorte que je n'ai besoin d'effacer le cache qu'une seule fois pour chaque lien symbolique. Pour une raison quelconque, cela ne fonctionne pas. clearstatcache
doit être appelé à chaque fois que a symlink
est inclus dans le chemin, mais pourquoi? Il doit y avoir un moyen d'optimiser la solution que j'ai.
J'utilise PHP 7.3.5
avec nginx/1.16.0
. file_get_contents
Retourne parfois la mauvaise valeur lors de l'utilisation de a symlink
. Le problème est qu'après avoir supprimé et recréé un lien symbolique, son ancienne valeur reste dans le cache. Parfois, la valeur correcte est renvoyée, parfois l'ancienne valeur. Cela semble aléatoire.
J'ai essayé de vider le cache ou d'empêcher la mise en cache avec:
function symlink1($target, $link)
{
realpath_cache_size(0);
symlink($target, $link);
//clearstatcache(true);
}
Je ne veux pas vraiment désactiver la mise en cache mais j'ai toujours besoin d'une précision de 100% avec file_get_contents.
Éditer
Je ne peux pas poster mon code source, car il est beaucoup trop long et complexe, j'ai donc créé un exemple reproductible minimal (index.php) qui recrée le problème:
<h1>Symlink Problem</h1>
<?php
$dir = getcwd();
if (isset($_POST['clear-all']))
{
$nos = array_values(array_diff(scandir($dir.'/nos'), array('..', '.')));
foreach ($nos as $no)
{
unlink($dir.'/nos/'.$no.'/id.txt');
rmdir($dir.'/nos/'.$no);
}
foreach (array_values(array_diff(scandir($dir.'/ids'), array('..', '.'))) as $id)
unlink($dir.'/ids/'.$id);
}
if (!is_dir($dir.'/nos'))
mkdir($dir.'/nos');
if (!is_dir($dir.'/ids'))
mkdir($dir.'/ids');
if (isset($_POST['submit']) && !empty($_POST['id']) && ctype_digit($_POST['insert-after']) && ctype_alnum($_POST['id']))
{
$nos = array_values(array_diff(scandir($dir.'/nos'), array('..', '.')));
$total = count($nos);
if ($total <= 100)
{
for ($i = $total; $i >= $_POST['insert-after']; $i--)
{
$id = file_get_contents($dir.'/nos/'.$i.'/id.txt');
unlink($dir.'/ids/'.$id);
symlink($dir.'/nos/'.($i + 1), $dir.'/ids/'.$id);
rename($dir.'/nos/'.$i, $dir.'/nos/'.($i + 1));
}
echo '<br>';
mkdir($dir.'/nos/'.$_POST['insert-after']);
file_put_contents($dir.'/nos/'.$_POST['insert-after'].'/id.txt', $_POST['id']);
symlink($dir.'/nos/'.$_POST['insert-after'], $dir.'/ids/'.$_POST['id']);
}
}
$nos = array_values(array_diff(scandir($dir.'/nos'), array('..', '.')));
$total = count($nos) + 1;
echo '<h2>Ids from nos directory</h2>';
foreach ($nos as $no)
{
echo ($no + 1).':'.file_get_contents("$dir/nos/$no/id.txt").'<br>';
}
echo '<h2>Ids from using symlinks</h2>';
$ids = array_values(array_diff(scandir($dir.'/ids'), array('..', '.')));
if (count($ids) > 0)
{
$success = true;
foreach ($ids as $id)
{
$id1 = file_get_contents("$dir/ids/$id/id.txt");
echo $id.':'.$id1.'<br>';
if ($id !== $id1)
$success = false;
}
if ($success)
echo '<b><font color="blue">Success!</font></b><br>';
else
echo '<b><font color="red">Failure!</font></b><br>';
}
?>
<br>
<h2>Insert ID after</h2>
<form method="post" action="/">
<select name="insert-after">
<?php
for ($i = 0; $i < $total; $i++)
echo '<option value="'.$i.'">'.$i.'</option>';
?>
</select>
<input type="text" placeholder="ID" name="id"><br>
<input type="submit" name="submit" value="Insert"><br>
</form>
<h2>Clear all</h2>
<form method="post" action="/">
<input type="submit" name="clear-all" value="Clear All"><br>
</form>
<script>
if (window.history.replaceState)
{
window.history.replaceState( null, null, window.location.href );
}
</script>
Cela semblait très probablement être un problème de Nginx
configuration. Ne pas avoir ces lignes peut provoquer le problème:
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
Voici ma Nginx
configuration (vous pouvez voir que j'ai inclus les lignes ci-dessus):
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.websemantica.co.uk;
root "/path/to/site/root";
index index.php;
location / {
try_files $uri $uri/ $uri.php$is_args$query_string;
}
location ~* \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $realpath_root$fastcgi_path_info;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $realpath_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
fastcgi_param HTTPS $https;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
fastcgi_index index.php;
fastcgi_read_timeout 3000;
}
if ($request_uri ~ (?i)^/([^?]*)\.php($|\?)) {
return 301 /$1$is_args$args;
}
rewrite ^/index$ / permanent;
rewrite ^/(.*)/$ /$1 permanent;
}
Actuellement, j'ai l'exemple ci-dessus en direct sur https://www.websemantica.co.uk .
Essayez d'ajouter quelques valeurs dans le formulaire. Il devrait s'afficher Success!
en bleu à chaque fois. Est parfois affiché Failure!
en rouge. Le changement de Success!
vers Failure!
ou vice-versa peut prendre quelques rafraîchissements de page . Finalement, il s'affichera à Success!
chaque fois, donc il doit y avoir une sorte de problème de mise en cache.
realpath
avec file_get_conents
et pas de chance. Il se charge encore parfois à partir du cache.
realpath
, mais quelque chose commeclearstatcache(true); file_get_conents(realpath($fileName));
realpath
page de fonction . Cela pourrait peut-être vous aider.