ugrás a tartalomhoz

PHP - írás fájlba és hibakezelés

Max Logan · 2009. Aug. 25. (K), 16.46
A PHP fájlkezelésével kapcsolatban kicsit tanácstalan vagyok. Adott egy script, ami ír egy fájlba. Könnyen előfordulhat, hogy egy időben két user is írna a fájlba, ezért ugye kell a lock-olás (amit fopen esetén kézileg kell megoldani, file_put_contents-nél van rá flag). Aztán érdemes lenne még írás előtt ellenőrizni, hogy a fájl létezik-e, valamint, hogy írható-e. Na és ezen feltételek összesége okoz egy kis fejtörést.

Az fopen és a file_put_contents esetében is megoldott az, hogy ha nem létezik a fájl, akkor léterhozza. Az első probléma itt van. Ugyanis, az is_writable() ellenőrzi azt is, hogy a fájl létezik-e. Viszont nekem nem kellene a fájl létezésének ellenőrzése, mert ha nem létezik, akkor az fopen vagy a file_put_contents létrehozza. Az viszont logikus, hogy az is_writable() ellenőrzi, hogy egyáltalán létezik-e a fájl, aminek egy tulajdonságát akarja megállapítani.

Előáll az a faramuci helyzet, hogy először ellenőrizni kellene, hogy létezik-e a fájl, majd ha igen, akkor az írhatóságát ellenőrizni, majd ezt követetően ha írható, akkor írni bele.

A gond az, hogy alap esetben a fájl nem létezik, az első írás alkalmával a PHP hozza létre (dinamikus néven generált fájl).

És innentől nem tudom, hogy akkor most mit csináljak.

Ne foglalkozzak az is_writable() ellenőrzéssel, mert ha nem írható, akkor az fwrite vagy a file_put_contents dob egy false-t visszatérési értéknek?
 
1

Teszt

Max Logan · 2009. Aug. 25. (K), 18.23
Közben teszteltem egy egyszerű kódon, az írásvédett fájl írását. Mind az fopen, mind a file_put_contents false-t ad vissza, valamint küld egy "failed to open stream: Permission denied" hibát.

Így nincsen szükségem a file_exists vizsgálatra, mivel a file_put_contents úgyis létrehozza, ha nem írható a fájl, akkor meg úgyis hibát dob. A lock-ot pedig egy flag beállításával meg tudom oldani.
2

egyszerü feltétel

firith · 2009. Aug. 31. (H), 12.33
Ez így miért nem jó?

if (file_exists($file) && !is_writeble($file)) {
    echo 'A file nem nyitható meg írásra';
    return;
}
3

is_writeble

Poetro · 2009. Aug. 31. (H), 15.07
Az is_writeble ellenőrzi, hogy létezik-e, és azt is hogy írható-e.
4

Felesleges kétszer

Max Logan · 2009. Aug. 31. (H), 15.10
Az általad írt feltétel kétszer ellenőrzi, hogy létezik-e a fájl, ami felesleges.

Az én esetemben a probléma az, hogy a fájlt a php hozza létre, ha nem létezik. Ha ellenőrzöm a fájl létezését file_exist-el és nem létezik, akkor nem jut el az írásig. A false ágban meg feleslegesen nem írom meg mégegyszer, hogy hozza létre a fájlt.

Ha az írhatóságot ellenőrzöm és nem létezik még a fájl, akkor szintén nem jut el az írásig az is_writable miatt, és itt is feleslegesen kellene egy false ág az első létrehozás miatt.

Mint írtam a kommentben, ha nem írható a fájl, akkor az fopen és a file_put_contents is jelzi ezt egy kedves hibaüzenetben. Ergó jelen esetben felesleges a fájl létezésének ellenőrzése, mert anélkül is kezelhető az írási sikertelenség hiba.

A lock-olás kérdését a file_put_contents-szel egyszerűen megoldottam. A fájl írhatóságával meg nem foglalkozom, mert a PHP hozza létre. Ergo a kirívó esetektől eltekintve (manuális fájl jogosultság állítás) a PHP minden esetben képes lesz írni (már ha jól gondolom).
5

csak egy ötlet

net-face · 2009. Szep. 1. (K), 13.10
tmpfile()

1 - generálja a file nevet magától
2 - létrehozza, és írható
3 - nem ír felül semmit

viszont ha nem hostolt géped van, hanem tárhelyed, akkor sose nyiss meg file-t, és sose írj. ha minden honlap az adott webserveren ezt csinálná, akkor a kernel hamar eljutna a max opened file-ig.
6

Hasznos ...

Max Logan · 2009. Szep. 1. (K), 14.06
... ez a tmpfile(). Alapvetően én osztott hosztingra fejlesztek, elsősorban honlapokat és kisebb, közepes webalkalmazásokat. Fájlokkal csak akkor dolgozom, ha nagyon muszáj.

Jelen esetben egy cache mechanizmust csináltam, ahol a fájlba tárolás a célszerű megoldás (később majd lesz memcache-ben tárolás is, de a feladatot nézve erre csak nagyon extrém látogatószám mellett lenne szükség).

Az a veszély nem fenyeget, hogy bármilyen limitet elérne a script. A cache-elés során maximum 10-15 fájl jön létre, de csak akkor, ha a cache alapjául szolgáló összetevők megváltoztak.

Ezek pedig a honlap élesítése után nem változnak. Azaz éles szituációban maximum 30-45 fájl jön létre (minden cache fájlból 3 féle lehet). Ha nem törli valaki kézzel a cache állományokat, akkor a honlap élesítése utáni rövid időszakot leszámítva nem igazán lesz fájlba írás.

Olvasás igen, de ez meg oldaltöltésenkét 1 vagy két 2 olvasás. Mekkora az a forgalom, ahol az oldaltöltésenkénti 2 fájl olvasás gondot okozhat osztott hosztingon?


Szerk.: Na jó, elárulom a konkrét programot, mert végiggondolva nem minden oldaltöltésnél kell olvasni a fájlt.

Szóval, annó volt itt egy blogmark, ami egy CSS és JS fájlok összefűzését és fájlba cachelését megvalósító kódról szólt.

Ezen program alapján írtam egy osztályt. A cucc azt csinálja, hogy a megadott css és js fájlokból generál egy cache fájlt. Ez lehet tömörítés nélküli, gzip vagy deflate tömörítéssel (ebből adódik a hármas szorzó).

Namost, ha első alkalommal jön a látogató, akkor megkapja az összefűzött és adott esetben tömörített cache-t, amit fájlból olvas be a PHP. Viszont ha már második alkalommal jön, akkor nem kap semmit, csak egy 304 Not Modified fejlécet. Így viszont már jelentősen kisebb a fájlok olvasásának száma, ergó szerintem nem okoz ez gondot a max opened file limitben.

Vélemény?

Szerk. 2: Tervben van egy lightweight verzió is, amikor a PHP csak létrehozza a cache-t. A tényleges kiszolgálást már nem a PHP, hanem az Apache végzi. A PHP csak az összefűzést és a letárolást oldja meg.

Ebben az esetben egy .htaccess beli kóddal elvileg megoldható, hogy ha támogatja a böngésző a gzip vagy deflate kódolást, akkor a támogatott tömörítéssel kapja a cuccot.