Piano di emergenza per errore fopen in php
Domanda
Sto scrivendo un'app PHP che ha un 'pannello di controllo' che scrive un file prefs con determinate variabili. Su ogni POST
, se il file non esiste, viene creato. Se esiste, è unlinked
e un nuovo file è touched
con lo stesso nome file e nuove variabili. Questo file viene quindi incluso in un'altra pagina con contenuto visualizzato in base alle variabili al suo interno.
$file = "phpsettings.php";
if (!file_exists($file)) {
touch($file);
$handle = fopen ($file, 'r+');
$str = "<?php \$pref1 = \"$mypref\"; ?>";
} else {
unlink($file);
touch($file);
$handle = fopen ($file, 'r+');
$str = "<?php \$pref1 = \"$mypref\"; ?>";
}
fwrite ($handle, $str);
fclose ($handle);
È un modo sicuro per scrivere le preferenze, a condizione che questo file venga sovrascritto più volte al giorno? Qual è un buon modo per avvisare l'utente di questo pannello di controllo se il file non è stato salvato correttamente, e in tal caso, quale sarebbe un buon piano di emergenza per evitare di spezzare la pagina che questo file di prefs è incluso a breve definire set predefinito di variabili da compilare se !(file_exists)
?
Soluzione
Se memorizzi le tue impostazioni in un array, puoi serializzarle () e scriverle in un file di testo, piuttosto che scrivere php grezzo in un file php e includerlo.
Se non stai disinfettando il tuo input per quelle preferenze e dici che $ mypref1 rappresenta il nome di qualcuno, non c'è nulla che impedisca loro di riempirlo nel campo del modulo:
\"; echo \"PWNED
e il PHP risultante diventerà
<?php \$pref1 = \"$mypref\"; echo \"PWNED\"; ?>
Quindi, in primo luogo, archiviare le tue preferenze in un array e usare serialize () è molto più sicuro:
$prefs = array('mypref1' => 'somethingorother');
$handle = fopen ($file, 'w');
fwrite($handle, serialize($prefs));
fclose($h);
// example code demonstrating unserialization
$prefs2 = unserialize(file_get_contents($file));
var_dump($prefs == $prefs2); // should output "(bool) true"
Nella tua domanda, dici anche che se il file esiste, è scollegato. Puoi semplicemente troncarlo a lunghezza zero passando & Quot; w & Quot; come secondo argomento da aprire - non è necessario eliminarlo manualmente. Questo dovrebbe impostare comunque l'ora, annullando la necessità di toccare la chiamata ().
Se i valori scritti nel file sono preferenze, sicuramente ogni preferenza potrebbe avere un valore predefinito, a meno che non ce ne siano centinaia? array_merge ti consentirà di sovrascrivere in base alla chiave, quindi se fai qualcosa del genere:
// array of defaults
$prefs = array(
'mypref1' => 'pants',
'mypref2' => 'socks',
);
if (file_exists($file)) {
// if this fails, an E_NOTICE is raised. are you checking your server error
// logs regularly?
if ($userprefs = unserialize(file_get_contents($file))) {
$prefs = array_merge($prefs, $userprefs);
}
}
Se il problema è che ci sono molti cumuli e non si desidera inizializzarli tutti, è possibile disporre di un metodo get_preference che avvolge semplicemente una chiamata isset all'array prefs.
function get_preference($name, &$prefs) {
if (isset($pref[$name]))
return $pref[$name];
return null;
}
var_dump(get_preference('mypref1', $prefs));
Al di là di tutte le domande che questo solleva, la realtà è che con la tua app, nell'improbabile caso in cui qualcosa non vada storto con il fopen, dovrebbe comunque essere considerato un grave fallimento, e la manciata di utenti che probabilmente utilizzerai questa funzione ti contatteranno molto rapidamente se qualcosa va storto.
Altri suggerimenti
È sempre meglio archiviare lo stato degli utenti in una sessione e persistere solo quando necessario.
Perché non usare semplicemente le capacità di troncamento di fopen ()? Credo invece di & Quot; r + & Quot ;, dovrai passare & Quot; w + & Quot; ... Quindi se il file esiste, verrà troncato, se non lo fa ti limiterai a creare un nuovo file. Quindi il codice diventa:
$file = "phpsettings.php";
$handle = fopen( $file, 'w+' );
$str = "<?php \$pref1 = \"$mypref\"; ?>";
fwrite ($handle, $str);
fclose ($handle);