Yli kuukauden vanha, joten jatkan tässä hieman aiheesta
Antti Laaksonen kirjoitti:
Seuraava koodi ilmoittaa, milloin jotain tiedostoa on muokattu viimeksi hakemistossa ja alihakemistoissa.
Kokeilin tuota koodia, mutta se antaa seuraavanlaisen virheilmoituksen:
Warning: Invalid argument supplied for foreach() in /var/www/vhosts/oma.domain/httpdocs/
Oma taitotasoni php-koodauksesta onneton, joten en ymmärrä mistä johtuu moinen.
Mod. lisäsi kooditagit
Parse error: syntax error, unexpected '{' in /var/www/vhosts/oma.domain/httpdocs/index.php on line 74
oli vastaus palvelimelta...
Edit.
Nopeita vastauksia...
Edit. Omani ei toiminutkaan, mutta kyllä tuo Antin versio toimii.
En tiedä, pystyykö tuon globin ottamaan pois päältä.
Hmmm.
Mikähän tuossa sitten oikein on? Koodi antaa kyllä sen päiväyksen, mutta ennen sitä herjaa tuosta invalidista argumentista.
<?php $uusin = getlastmod(); function haku($hakemisto) { global $uusin; while($tiedot == readdir(opendir($hakemisto))) { if (is_dir($tied)) { haku($tiedot); } else { $uusin = max($uusin, filemtime($tiedot)); } } } haku("."); echo "Viimeisin päivitys: " . date("j.n.Y G:i:s", $uusin); ?>
Koitappas tätä.
Nyt pelittää. Kiitos!
No ei kyllä pelitä.
Tulostettu muokkausaika on aivan väärä, ja lisäksi tulee tällainen huomautus:
PHP Notice: Undefined variable: tiedot in /tmp/mib-koe/koe.php on line 6
MIBin koodi siis avaa hakemiston ja hakee ensimmäisen tiedostonimen ja vertaa sitä muuttujaan $tiedot, jota ei ole. Vertailun tulos on väitämättä false, joten silmukkaa ei ajeta kertaakaan.
Korjaus: vaihdetaan ==:n tilalle yksi =.
Nyt päästään jo silmukkaan asti, mutta ongelmat eivät lopu tähän.
Notice: Undefined variable: tied in /tmp/mib-koe/koe.php on line 8
Notice: Undefined variable: tied in /tmp/mib-koe/koe.php on line 8
Notice: Undefined variable: tied in /tmp/mib-koe/koe.php on line 8
jne.
Korjaus: vaihdetaan nimi oikeaksi ($tiedot).
Mutta mitä ihmettä? Skripti pyörii kauan ja päättyy virheeseen!
Fatal error: Maximum execution time of 2 seconds exceeded in /tmp/mib-koe/koe.php on line 7
Koodia katselemalla voi huomata, että opendir-kutsu on while-silmukan ehdossa, jolloin hakemisto avataan joka kerta uudestaan! Niinpä readdir palauttaa joka kerta hakemiston ensimmäisen tiedostonimen eikä silmukka lopu koskaan.
Korjaus: avataan hakemisto vain kerran, sijoitetaan tulos muuttujaan ja käytetään tätä readdirin parametrina.
Ongelma ei ratkennutkaan tällä kokonaan vaan muutti muotoaan:
PHP Warning: opendir(.): failed to open dir: Too many open files in /tmp/mib-koe/koe.php on line 6
PHP Warning: readdir() expects parameter 1 to be resource, boolean given in /tmp/mib-koe/koe.php on line 7
PHP Warning: opendir(..): failed to open dir: Too many open files in /tmp/mib-koe/koe.php on line 6
PHP Warning: readdir() expects parameter 1 to be resource, boolean given in /tmp/mib-koe/koe.php on line 7
jne., kunnes
Fatal error: Maximum execution time of 2 seconds exceeded in /tmp/mib-koe/koe.php on line 7
Miten voi olla liikaa tiedostoja auki? On vain yksi selitys: ikuinen silmukka. Virheistä nähdään myös, että opendir on yrittänyt avata monta kertaa hakemistoa . (piste) eli nykyistä hakemistoa. Niinpä kyseessä tosiaan on ikuinen silmukka.
Korjaus: lisätään silmukan alkuun if-lause, jolla nimien "." ja ".." käsittely jätetään väliin.
Nyt koodi ajetaan järkevässä ajassa loppuun, mutta tulos on silti väärä. Lisäksi tulee mm. tällainen varoitus:
PHP Warning: filemtime(): stat failed for koe.txt in /tmp/mib-koe/koe.php on line 11
Tiedän, että tiedosto "koe.txt" sijaitsee hakemistossa "alihakemisto". Selvästi siis filemtime-funktion kutsusta puuttuu se hakemiston nimi. Koodista voi päätellä, että se varmaan puuttuu muistakin vastaavista kohdista (is_dir ja haku).
Korjaus: vaihdetaan silmukassa tiedostonimeksi $tiedot-muuttujan sijaan "$hakemisto/$tiedot" kaikissa kolmessa kohdassa.
Hei, se toimii! Piti noinkin lyhyestä koodista korjata viisi asiaa, ja sitä ennen ruudulle tulostui tuhansia rivejä virheilmoituksia, joita koodin tekijä tai käyttäjä eivät ehkä olisi itse ymmärtänyt.
MIB: Kun et vielä osaa kovin hyvin koodata, testaa jokainen koodisi huolellisesti ennen lähettämistä. Avunpyytäjä ei voi tietää ohjelmointitaidoistasi ja luultavasti olettaa, että koodisi toimii, ja on aika ikävää, kun puolet koodista onkin päin honkia. Itse taas olisin aivan hyvin voinut korjata tuonkin koodin kokeilematta sitä kertaakaan – eikä siihen tarvita mitään laajempaa tietämystä, vaan pitää vain ymmärtää, miten koodin suoritus etenee ja mitä arvoja funktiot eri tilanteissa palauttavat. Se on sitä ohjelmointitaitoa, josta tuolla C++-alueellakin puhuttiin. Se ei tule lukemalla, kyselemällä ja kopioimalla vaan harjoituksen kautta.
Flatologi: Kun saat koodia henkilöltä, joka poistaa ensimmäisen vastauksensa kommentilla "oho ei se toiminutkaan", pidä varasi: koodi voi olla vaarallista (jumittaa palvelimen pitkäksi aikaa) tai toimia yllättävällä tavalla väärin. Testaa siis ainakin pari kertaa, että lopputulos on oikea. Esimerkiksi tässähän tuloksen pitäisi vaihtua, jos muokkaat jotain toista tiedostoa.
Tässä luettelemieni korjausten tekeminen MIBin viestin koodiin jääköön teille harjoitusta kaipaaville. Kyllä sen pitäisi noilla ohjeilla onnistua. Lisäksi otatte toivottavasti oppia pitkässä selostuksessa esitetyistä päättelytavoista, joissa ei sinänsä ole mitään ihmeellistä mutta joilla saa korjattua valtaosan perusvirheistä.
Metabolix: Aivan mahtavaa :-D
Itselle ei kylläkään tullut noita herjauksia, mutta päiväys on kylläkin väärin. Aikaisempi Antin laittama koodi tulostaa päiväyksen oikein, mutta jostain syystä se alkoi herjaamaan päiväyksen ohella, vaikka toimikin ensin täysin ok.
Täytyy perehtyä tuohon php-koodaukseen paremmin, tai siis opetella se, ei tästä muuten mitään tule. Toisaalta en sitä hirveästi tarvitse vielä, muttei siitä haittaakaan ole.
Metabolix: Kiitos huomioista.
Flatologi kirjoitti:
Itselle ei kylläkään tullut noita herjauksia, mutta päiväys on kylläkin väärin.
Tuo voi johtua siitä, että yleensä palvelimilla notice-tason herjat on laitettu täysin pois päältä ja varoituksetkin saattavat ohjautua lokitiedostoon. Tässähän vakavampia virheitä alkoi tulla vasta, kun tuon ensimmäisen virheen korjasi; aiemmin suurinta osaa koodista ei edes ajettu kertaakaan.
Mikä tarkalleen on Antin koodista tuleva ilmoitus?
Metabolix kirjoitti:
Mikä tarkalleen on Antin koodista tuleva ilmoitus?
Se on tuo ekassa viestissä oleva:
Warning: Invalid argument supplied for foreach() in /var/www/vhosts/oma.domain/httpdocs/
Tuo tulee kahdesti peräkkäin ja alimmaisena oikea päiväys.
Glob saattaa palauttaa tyhjästä hakemistosta arvon false. Lisää siis koodiin tarkistus tämän varalta:
eikös is_array() olisi loogisempi? sillä foreach syö vain taulukoita.
Samahan se tuossa on. Glob ei kuitenkaan palauta kuin taulukoita tai falsen, ja tyhjästä taulukosta ei ole foreachissa mitään iloa.
Tuo lisäys ei kylläkään muuttanut tilannetta.
Koodi toimi ennen, mutta se oli /testaus/ alihakemistossa. Nyt päähakemistossa se herjaa...
Metabolix kirjoitti:
Samahan se tuossa on. Glob ei kuitenkaan palauta kuin taulukoita tai falsen, ja tyhjästä taulukosta ei ole foreachissa mitään iloa.
käsittääkseni glob() ei koskaan palauta tyhjää taulukkoa
T.M. kirjoitti:
käsittääkseni glob() ei koskaan palauta tyhjää taulukkoa
Manuaali sanoo että voi palauttaa. Jos tiedät olevasi oikeassa, voit lähettää kommentin tuonne:
https://www.php.net/manual/en/function.glob.php
Taidat kuitenkin olla väärässä:
$ php -r 'print_r(glob("ihanjotainmuuta*"));' Array ( )
Edit: Ellet tarkoittanut aloitusviestin koodin tilannetta, jolloin voit olla oikeassa ajoympäristöstä riippuen. Windowsissa tyhjästä hakemistosta palautuisi tyhjä taulukko?
T.M. kirjoitti:
käsittääkseni glob() ei koskaan palauta tyhjää taulukkoa
Käsityksesi on manuaalin ja Chimanin esimerkin perusteella väärä.
Returns an array containing the matched files/directories, an empty array if no file matched or FALSE on error.
Note: On some systems it is impossible to distinguish between empty match and an error.
joo pieni ajatusvirhe tuli, tietysti se palauttaa tyhjän taulukon jos kansio on esim tyhjä.
pointtini oli se että foreach toimii kuten pitää, kun sinne ei päästä kuin taulukoita.
Aihe on jo aika vanha, joten et voi enää vastata siihen.