Atualizar
Resolvi o problema e postei uma resposta. No entanto, minha solução não é 100% ideal. Eu preferiria apenas remover o symlinkdo cachewith clearstatcache(true, $target)ou clearstatcache(true, $link)mas isso não funciona.
Também prefiro evitar o cache de links simbólicos em primeiro lugar ou remover o link simbólico do cache imediatamente após gerá-lo. Infelizmente, não tive sorte com isso. Por algum motivo, clearstatcache(true)após a criação de um link simbólico não funcionar, ele ainda é armazenado em cache.
Felizmente, darei a recompensa a qualquer pessoa que possa melhorar minha resposta e resolver esses problemas.
Editar
Tentei otimizar meu código gerando um arquivo sempre que clearstatcachefor executado, para que eu só precise limpar o cache uma vez para cada link simbólico. Por alguma razão, isso não funciona. clearstatcacheprecisa ser chamado toda vez que um symlinké incluído no caminho, mas por quê? Deve haver uma maneira de otimizar a solução que tenho.
Eu estou usando PHP 7.3.5com nginx/1.16.0. Às vezes, file_get_contentsretorna o valor errado ao usar a symlink. O problema ocorre após excluir e recriar um link simbólico; seu valor antigo permanece no cache. Às vezes, o valor correto é retornado, às vezes o valor antigo. Parece aleatório.
Eu tentei limpar o cache ou impedir o cache com:
function symlink1($target, $link)
{
realpath_cache_size(0);
symlink($target, $link);
//clearstatcache(true);
}
Eu realmente não quero desativar o cache, mas ainda preciso de 100% de precisão com file_get_contents.
Editar
Não consigo postar meu código-fonte, pois é muito longo e complexo, por isso criei um exemplo mínimo e reproduzível (index.php) que recria o problema:
<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>
Parecia muito provável que fosse um problema com a Nginxconfiguração. Não ter essas linhas pode causar o problema:
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
Aqui está minha Nginxconfiguração (você pode ver que eu incluí as linhas acima):
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;
}
Atualmente, tenho o exemplo acima ao vivo em https://www.websemantica.co.uk .
Tente adicionar alguns valores no formulário. Ele deve aparecer Success!em azul sempre. Às vezes é mostra Failure!em vermelho. Pode levar algumas atualizações de página para mudar de Success!para Failure!ou vice-versa. Eventualmente, ele será exibido Success!sempre, portanto, deve haver algum tipo de problema de armazenamento em cache.
realpathcom file_get_conentse sem sorte. Às vezes, ainda é carregado do cache.
realpath, mas algo comoclearstatcache(true); file_get_conents(realpath($fileName));
realpathpágina de funções . Talvez isso possa te ajudar.