<h2>Entendendo o Sistema de Arquivos em PHP</h2>
<p>A manipulação de arquivos e diretórios é uma competência fundamental para qualquer desenvolvedor PHP. Seja lendo configurações, armazenando dados do usuário ou gerenciando uploads, você trabalhará constantemente com o sistema de arquivos. PHP oferece funções nativas poderosas que abstraem as complexidades do sistema operacional subjacente.</p>
<p>Antes de começar, compreenda que PHP trabalha com caminhos absolutos e relativos. Um caminho absoluto começa da raiz do sistema (<code>/var/www/html/arquivo.txt</code>), enquanto relativo é baseado no diretório atual do script. Use <code>__DIR__</code> e <code>__FILE__</code> (constantes mágicas do PHP) para trabalhar com caminhos de forma robusta e independente do sistema operacional.</p>
<h2>Operações Básicas com Arquivos</h2>
<h3>Criando e Escrevendo em Arquivos</h3>
<p>A função <code>file_put_contents()</code> é sua aliada principal para criar ou sobrescrever arquivos. Ela é simples, segura e retorna o número de bytes escritos ou <code>false</code> em caso de erro:</p>
<pre><code class="language-php"><?php
$caminho = __DIR__ . '/dados.txt';
$conteudo = "Olá, mundo!\nEste é meu primeiro arquivo.";
if (file_put_contents($caminho, $conteudo)) {
echo "Arquivo criado com sucesso!";
} else {
echo "Erro ao criar arquivo!";
}
?></code></pre>
<p>Para <strong>adicionar conteúdo</strong> sem sobrescrever (append), use a flag <code>FILE_APPEND</code>:</p>
<pre><code class="language-php"><?php
$caminho = __DIR__ . '/log.txt';
$mensagem = date('Y-m-d H:i:s') . " - Nova entrada no log\n";
file_put_contents($caminho, $mensagem, FILE_APPEND);
?></code></pre>
<h3>Lendo Arquivos</h3>
<p>Para ler um arquivo inteiro, <code>file_get_contents()</code> é o caminho mais direto:</p>
<pre><code class="language-php"><?php
$caminho = __DIR__ . '/dados.txt';
if (file_exists($caminho)) {
$conteudo = file_get_contents($caminho);
echo $conteudo;
} else {
echo "Arquivo não encontrado!";
}
?></code></pre>
<p>Se você precisa processar o arquivo linha por linha (útil para arquivos grandes), use <code>fopen()</code> com <code>fgets()</code>:</p>
<pre><code class="language-php"><?php
$caminho = __DIR__ . '/grande_arquivo.txt';
$arquivo = fopen($caminho, 'r');
if ($arquivo) {
while (($linha = fgets($arquivo)) !== false) {
echo trim($linha) . "\n";
}
fclose($arquivo);
}
?></code></pre>
<h2>Manipulação de Diretórios</h2>
<h3>Criando e Navegando em Diretórios</h3>
<p>Para criar um diretório, use <code>mkdir()</code>. O terceiro parâmetro permite criar diretórios aninhados recursivamente:</p>
<pre><code class="language-php"><?php
$diretorio = __DIR__ . '/uploads/2024/janeiro';
if (!is_dir($diretorio)) {
if (mkdir($diretorio, 0755, true)) {
echo "Diretório criado!";
}
}
?></code></pre>
<p>Para <strong>listar arquivos</strong> em um diretório, <code>scandir()</code> retorna um array com todos os itens:</p>
<pre><code class="language-php"><?php
$diretorio = __DIR__ . '/uploads';
if (is_dir($diretorio)) {
$arquivos = scandir($diretorio);
foreach ($arquivos as $arquivo) {
if ($arquivo !== '.' && $arquivo !== '..') {
$caminho_completo = $diretorio . '/' . $arquivo;
$tipo = is_file($caminho_completo) ? 'Arquivo' : 'Diretório';
echo "$arquivo ($tipo)\n";
}
}
}
?></code></pre>
<h3>Deletando e Movendo</h3>
<p>Para remover um arquivo, <code>unlink()</code> é suficiente:</p>
<pre><code class="language-php"><?php
$arquivo = __DIR__ . '/temp.txt';
if (file_exists($arquivo) && is_file($arquivo)) {
if (unlink($arquivo)) {
echo "Arquivo deletado!";
}
}
?></code></pre>
<p>Para remover um diretório vazio, use <code>rmdir()</code>. Se contém arquivos, você precisa deletá-los primeiro ou usar uma solução recursiva:</p>
<pre><code class="language-php"><?php
function deletar_diretorio_recursivo($diretorio) {
if (!is_dir($diretorio)) return false;
$arquivos = scandir($diretorio);
foreach ($arquivos as $arquivo) {
if ($arquivo !== '.' && $arquivo !== '..') {
$caminho = $diretorio . '/' . $arquivo;
is_dir($caminho) ? deletar_diretorio_recursivo($caminho) : unlink($caminho);
}
}
return rmdir($diretorio);
}
deletar_diretorio_recursivo(__DIR__ . '/pasta_temp');
?></code></pre>
<p>Para <strong>mover ou renomear</strong>, <code>rename()</code> funciona para arquivos e diretórios:</p>
<pre><code class="language-php"><?php
$origem = __DIR__ . '/arquivo_antigo.txt';
$destino = __DIR__ . '/arquivo_novo.txt';
if (rename($origem, $destino)) {
echo "Arquivo movido com sucesso!";
}
?></code></pre>
<h2>Informações e Validações</h2>
<h3>Verificando Propriedades</h3>
<p>Antes de manipular arquivos, sempre valide sua existência e tipo. PHP oferece funções específicas e eficientes:</p>
<pre><code class="language-php"><?php
$caminho = __DIR__ . '/dados.txt';
echo "Existe? " . (file_exists($caminho) ? 'Sim' : 'Não') . "\n";
echo "É arquivo? " . (is_file($caminho) ? 'Sim' : 'Não') . "\n";
echo "É diretório? " . (is_dir($caminho) ? 'Sim' : 'Não') . "\n";
echo "Legível? " . (is_readable($caminho) ? 'Sim' : 'Não') . "\n";
echo "Gravável? " . (is_writable($caminho) ? 'Sim' : 'Não') . "\n";
echo "Tamanho: " . filesize($caminho) . " bytes\n";
echo "Última modificação: " . date('d/m/Y H:i:s', filemtime($caminho)) . "\n";
?></code></pre>
<h3>Exemplo Prático: Upload Seguro</h3>
<p>Combine validações para criar um sistema de upload robusto:</p>
<pre><code class="language-php"><?php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['arquivo'])) {
$arquivo = $_FILES['arquivo'];
$extensoes_permitidas = ['jpg', 'png', 'pdf'];
$tamanho_maximo = 5 1024 1024; // 5MB
$extensao = strtolower(pathinfo($arquivo['name'], PATHINFO_EXTENSION));
if ($arquivo['size'] > $tamanho_maximo) {
echo "Arquivo muito grande!";
} elseif (!in_array($extensao, $extensoes_permitidas)) {
echo "Extensão não permitida!";
} elseif ($arquivo['error'] !== UPLOAD_ERR_OK) {
echo "Erro no upload!";
} else {
$destino = __DIR__ . '/uploads/' . uniqid() . '.' . $extensao;
if (move_uploaded_file($arquivo['tmp_name'], $destino)) {
echo "Upload realizado com sucesso!";
}
}
}
?></code></pre>
<h2>Conclusão</h2>
<p>Dominar manipulação de arquivos em PHP é essencial para qualquer desenvolvedor. Os três pontos principais que você deve internalizar:</p>
<ol>
<li><strong>Use as funções nativas apropriadas</strong>: <code>file_put_contents()</code> e <code>file_get_contents()</code> para operações simples, <code>fopen()</code> para arquivos grandes, e sempre valide com <code>file_exists()</code>, <code>is_file()</code> e <code>is_writable()</code>.</li>
</ol>
<ol>
<li><strong>Segurança em primeiro lugar</strong>: Sempre valide entradas, use caminhos absolutos com <code>__DIR__</code>, implemente restrições de tamanho e tipo, e sanitize nomes de arquivo antes de armazenar.</li>
</ol>
<ol>
<li><strong>Estruture seus diretórios logicamente</strong>: Crie estruturas organizadas com <code>mkdir()</code> recursivo, separe uploads temporários de permanentes, e implemente limpeza de arquivos antigos regularmente.</li>
</ol>
<p>A prática é crucial — comece criando scripts simples que leiam, criem e deletem arquivos antes de avançar para sistemas complexos como gerenciadores de mídia.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://www.php.net/manual/en/ref.filesystem.php" target="_blank" rel="noopener noreferrer">PHP: Filesystem Functions</a></li>
<li><a href="https://www.php.net/manual/en/function.file-put-contents.php" target="_blank" rel="noopener noreferrer">PHP: file_put_contents</a></li>
<li><a href="https://www.php.net/manual/en/features.file-upload.php" target="_blank" rel="noopener noreferrer">PHP: Handling File Uploads</a></li>
<li><a href="https://www.php-fig.org/psr/psr-4/" target="_blank" rel="noopener noreferrer">PSR-4: Autoloading Standard</a></li>
<li><a href="https://cheatsheetseries.owasp.org/cheatsheets/File_Upload_Cheat_Sheet.html" target="_blank" rel="noopener noreferrer">OWASP: File Upload Cheat Sheet</a></li>
</ul>