Criar ou escrever / acrescentar no arquivo de texto

170

Eu tenho um site que, toda vez que um usuário efetua login ou efetua logoff, eu o salvo em um arquivo de texto.

Meu código não funciona anexando dados ou criando um arquivo de texto se ele não existir. Aqui está o código de exemplo

$myfile = fopen("logs.txt", "wr") or die("Unable to open file!");
$txt = "user id date";
fwrite($myfile, $txt);
fclose($myfile);

Parece que não é anexado à próxima linha depois que eu a abrir novamente.

Também acho que também haveria um erro em uma situação quando 2 usuários se conectassem ao mesmo tempo, isso afetaria a abertura do arquivo de texto e o salvamento depois?

Jerahmeel Acebuche
fonte

Respostas:

337

Tente algo como isto:

 $txt = "user id date";
 $myfile = file_put_contents('logs.txt', $txt.PHP_EOL , FILE_APPEND | LOCK_EX);
SpencerX
fonte
5
isso cria um arquivo de texto se ele não existir?
Jerahmeel Acebuche
5
Yup é criar o arquivo de texto logs.txte anexar o conteúdo nela
SpencerX
5
Eu tenho uma pergunta. usando o LOCK_EX. Eu sei que isso impedirá que outras pessoas gravem no arquivo ao mesmo tempo. mas o que acontecerá com o outro?
Jerahmeel Acebuche
13
php.net/manual/en/function.file-put-contents.php Esta função retorna o número de bytes que foram gravados no arquivo, ou FALSE em falha. Só se alguém estiver se perguntando.
Master James
7
@JerahmeelAcebuche O segundo processo para tentar adquirir o bloqueio "será bloqueado até que o bloqueio solicitado seja adquirido" ( origem ). Em outras palavras, o segundo processo aguardará até o primeiro fechar o arquivo e liberar o bloqueio.
Rinogo 6/04
102

Use o amodo Significa append.

$myfile = fopen("logs.txt", "a") or die("Unable to open file!");
$txt = "user id date";
fwrite($myfile, "\n". $txt);
fclose($myfile);
Valentin Mercier
fonte
Eu também tenho esse problema do \ n. não funciona. isso funciona para você?
Jerahmeel Acebuche
1
isso funciona se a situação acontecer como eu disse?
Jerahmeel Acebuche
1
o asinalizador criará o arquivo se ele não existir e não importará o que for realmente necessário para o appendnovo texto. Para o \nele funciona, mas apenas se dentro de aspas "aspas não único'
Valentin Mercier
refiro-me à situação do que se os dois usuários fizerem login em navegador diferente. então o php abrirá o arquivo no navegador dois ao mesmo tempo e o atualizará no mesmo horário também. haverá um problema? \
Jerahmeel Acebuche
1
Ah, sim, neste caso, use um banco de dados SQL; ele possui um mecanismo interno para evitar condições de corrida. Mas essa é uma pergunta totalmente nova.
Valentin Mercier
10

Você pode fazer da maneira OO, apenas uma alternativa e flexível:

class Logger {

    private
        $file,
        $timestamp;

    public function __construct($filename) {
        $this->file = $filename;
    }

    public function setTimestamp($format) {
        $this->timestamp = date($format)." » ";
    }

    public function putLog($insert) {
        if (isset($this->timestamp)) {
            file_put_contents($this->file, $this->timestamp.$insert."<br>", FILE_APPEND);
        } else {
            trigger_error("Timestamp not set", E_USER_ERROR);
        }
    }

    public function getLog() {
        $content = @file_get_contents($this->file);
        return $content;
    }

}

Então use-o assim .. digamos que você tenha user_namearmazenado em uma sessão (semi pseudo código):

$log = new Logger("log.txt");
$log->setTimestamp("D M d 'y h.i A");

if (user logs in) {
    $log->putLog("Successful Login: ".$_SESSION["user_name"]);
}
if (user logs out) {
    $log->putLog("Logout: ".$_SESSION["user_name"]);
}

Verifique seu log com isso:

$log->getLog();

O resultado é como:

Sun Jul 02 '17 05.45 PM » Successful Login: JohnDoe
Sun Jul 02 '17 05.46 PM » Logout: JohnDoe


github.com/thielicious/Logger

Thielicious
fonte
1
Muito obrigado por esta classe Logger! Eu não esperava descobrir isso quando encontrei esta página ... mas, na verdade, é a base de uma solução muito melhor do que o que eu originalmente planejava implementar.
Myke Carter
4

Isso está funcionando para mim, escrevendo (criando também) e / ou anexando conteúdo no mesmo modo.

$fp = fopen("MyFile.txt", "a+") 
Mihir Bhatt
fonte
3

Tente este código:

function logErr($data){
  $logPath = __DIR__. "/../logs/logs.txt";
  $mode = (!file_exists($logPath)) ? 'w':'a';
  $logfile = fopen($logPath, $mode);
  fwrite($logfile, "\r\n". $data);
  fclose($logfile);
}

Eu sempre uso assim, e funciona ...

Rwakos
fonte
1
Não há motivo para fazer (!file_exists($logPath)) ? 'w':'a'- a aopção já possui o comportamento correto quando o arquivo não existe. Assim, pode simplificar esta resposta removendo a linha $mode = ...;e alterando a próxima linha para $logfile = fopen($logPath, 'a');.
Home
2

Não existe um modo de abertura de arquivo como "wr" no seu código:

fopen("logs.txt", "wr") 

Os modos de abertura de arquivo no PHP http://php.net/manual/en/function.fopen.php são os mesmos de C: http://www.cplusplus.com/reference/cstdio/fopen/

Existem os seguintes modos abertos principais "r" para leitura, "w" para gravação e "a" para acrescentar e você não pode combiná-los. Você pode adicionar outros modificadores como "+" para atualização, "b" para binário. O novo padrão C adiciona um novo subespecífico padrão ("x"), suportado pelo PHP, que pode ser anexado a qualquer especificador "w" (para formar "wx", "wbx", "w + x" ou "w + bx "/" wb + x "). Esse sub-especificador força a função a falhar se o arquivo existir, em vez de substituí-lo.

Além disso, no PHP 5.2.6, o modo aberto principal 'c' foi adicionado. Você não pode combinar 'c' com 'a', 'r', 'w'. O 'c' abre o arquivo apenas para gravação. Se o arquivo não existir, ele será criado. Se existir, não será truncado (em oposição a 'w'), nem a chamada para essa função falhará (como é o caso de 'x'). 'c +' Abre o arquivo para leitura e escrita; caso contrário, ele tem o mesmo comportamento que 'c'.

Além disso, e no PHP 7.1.2 foi adicionada a opção 'e' que pode ser combinada com outros modos. Ele definiu o sinalizador close-on-exec no descritor de arquivo aberto. Disponível apenas no PHP compilado nos sistemas conformes POSIX.1-2008.

Portanto, para a tarefa como você a descreveu, o melhor modo de abertura de arquivo seria 'a'. Abre o arquivo apenas para gravação. Coloca o ponteiro do arquivo no final do arquivo. Se o arquivo não existir, ele tentará criá-lo. Nesse modo, fseek () não tem efeito, as gravações são sempre anexadas.

Aqui está o que você precisa, como já foi indicado acima:

fopen("logs.txt", "a") 
Maxim Masiutin
fonte
0

Embora existam muitas maneiras de fazer isso. Mas se você quiser fazer isso de maneira fácil e quiser formatar o texto antes de gravá-lo no arquivo de log. Você pode criar uma função auxiliar para isso.

if (!function_exists('logIt')) {
    function logIt($logMe)
    {
        $logFilePath = storage_path('logs/cron.log.'.date('Y-m-d').'.log');
        $cronLogFile = fopen($logFilePath, "a");
        fwrite($cronLogFile, date('Y-m-d H:i:s'). ' : ' .$logMe. PHP_EOL);
        fclose($cronLogFile);
    }
}
Worm PHP ...
fonte