Soru PHP ile dizin içeriğinin değişip değişmediğini nasıl kontrol edebilirim?


PHP'de bir fotoğraf galerisi komut dosyası yazıyorum ve kullanıcının resimlerini depolayacağı tek bir dizine sahibim. Sayfayı önbelleğe almayı ayarlıyorum ve yalnızca dizinin içeriği değiştiyse önbellek yenilemeye çalışıyorum. Bunu, filemtime () işlevini kullanarak dizinin son değiştirilen zamanını önbelleğe alarak ve dizinin geçerli değiştirilen zamanıyla karşılaştırarak yapabileceğimi düşündüm. Ancak, fark ettiğim gibi, dizin değiştirilen zaman, dosyalar bu dizinden eklendiğinde veya kaldırıldığında (en azından Windows'da, henüz Linux makineleri hakkında emin olmadığından) değiştirilmez.

Sorularım, bir dizinin içeriğinin değiştirilip değiştirilmediğini kontrol etmenin en kolay yolu nedir?


23
2018-02-12 07:04


Menşei


Yanıtlar için teşekkürler, ancak yanıtlarınızın çoğu, pek çok farklı sistemdeki birçok son kullanıcının kullanacağı bir komut dosyası için geçerli değil. Bunu gerçekleştirdiğim şeyi daha iyi anlamak için, galeri sayfasına göz atın. code.web-geek.net/ck-gallery - PHLAK


Cevaplar:


Uh. Bir dizin listesinin md5'ini saklarım. İçerik değişirse, md5 (dizin-listeleme) değişecektir. Sen belki ara sıra md5 çatışması olsun, ama bu şansın yeterince küçük olduğunu düşünüyorum.
Alternatif olarak, "son değiştirilen" tarihi içeren bu dizine küçük bir dosya depolayabilirsiniz. Ama md5 ile giderdim.


PS. ikinci düşüncede, dizin listelemesini istemek ve birleştirmek için performansa (önbellekleme) nasıl baktığınızı görmek tamamen uygun olmayabilir.


6
2018-06-25 21:26





Başkaları tarafından daha önce de belirtildiği gibi, bu sorunu çözmenin daha iyi bir yolu, belirli olayların meydana geldiği, klasörün değiştirildiği bir işlevi tetiklemektir. Ancak, sunucunuz bir unix ise, kullanabilirsiniz inotifywait dizini izlemek ve sonra bir PHP betiğini çağırmak.

İşte basit bir örnek:

#!/bin/sh
inotifywait --recursive --monitor --quiet --event modify,create,delete,move --format '%f' /path/to/directory/to/watch |
  while read FILE ; do
    php /path/to/trigger.php $FILE
  done

Ayrıca bakınız: http://linux.die.net/man/1/inotifywait


21
2018-02-12 12:06



Bence çözüm PHP seviyesinde tutulmalıdır. Bu çözüm PHP uygulamasını temel işletim sistemi ile birleştirir ve taşınabilirliği kaybeder. - Mario
Bazı görevler OS seviyesinde daha iyi ele alınmaktadır. Örneğin, bir cronjob kurmak doğal olarak OS'ye özgüdür. Bunu PHP'de yapmanın bir yolu yoktur. - troelskn
Bu PHP ile bir HTML sayfası önbelleğe almakla ilgili, PHP ile ilgisi var. İşletim Sisteminin buna dahil olması, hiçbir şey için meseleleri zorlaştırır. Gizli çözümden bahsetmemekle birlikte bu çözüm saklamak programcıları karıştırıyor olabilir. - Mario
Bu yüzden diyorsun. Bu çözüm için durumlar olabilir. Örneğin, PHP uygulaması resimlerin yüklenebilmesinin tek yolu değilse. Buna katılıyorum muhtemelen PHP'de çözmek daha iyi, ancak bağlam olmadan, emin olamıyorum, yapabilir miyim? - troelskn
Posterin sorusuna göre gidiyorum. Sonsuza kadar oyun oynayabilirdik ... - Mario


Ne dersin dokunma Bir kullanıcı resmini gönderdikten sonra dizini? Changelog diyor ki: windows çalışmak için php 5.3 gerektirir, ancak diğer tüm ortamlarda çalışması gerektiğini düşünüyorum


8
2018-02-12 10:25



+1, Basit, güzel ve hızlı! - Alix Axel


php içinde inotifywait ile

$watchedDir = 'watch';

$in = popen("inotifywait --monitor --quiet --format '%e %f' --event create,moved_to '$watchedDir'", 'r');
if ($in === false)
    throw new Exception ('fail start notify');

while (($line = fgets($in)) !== false) 
{
    list($event, $file) = explode(' ', rtrim($line, PHP_EOL), 2);
    echo "$event $file\n";
}

6
2017-07-20 20:12





İşte deneyebilirsiniz. Tüm resimleri tek bir dizinde (veya /username İşleri hızlandırmak ve FS'deki stresi azaltmak için içindeki alt dizinler ve Apache'yi (veya kullandığınız whaterver'i), bunları 100 yıl sonra "sona ermiş" olan statik içerik olarak sunmak için kurdunuz. Dosya adları bazı benzersiz önek veya sonek (zaman damgası, dosya içeriğinin SHA1 karması, vb.) İçermelidir. Bu nedenle, dosya kullanıldığında dosyanın adı değişir ve Apache, yol boyunca önbelleğe alınacak yeni bir sürüm sunacaktır.


3
2018-02-12 07:28



Bu ayrıca, tarayıcı dizesi parametrelerini ve benzerlerini (Safari, iirc) nedeniyle tarayıcıları bir şeyler önbelleğe almayı engeller. - Richard Levasseur
Tüm sayfa önbellekleme nereden geliyor? - Mario
Resim adlarını değiştirmek, yer imlerini öldürür. - Mario
Genelde görüntülerin kendilerine değil, içerdiği resimlere yer işareti koyarsınız. - Anton Gogolev
Bunu ortalama kullanıcılarına söyle. - Mario


Yanlış yolu düşünüyorsun.

Birisi yeni bir dosya yüklediğinde ve hedef konuma taşındığında dizin dizinleyici komut dosyanızı çalıştırmalısınız.


3
2018-02-12 08:10



İlk başta iyi bir çözüm gibi görünüyor, ama bir GOTCHA var. Sayfasının şablonunu değiştirmek istiyorsa, önbelleğe alınmış öğeleri yenilemelerini silmediğiniz için çözümünüz başarısız olur. Her şeyi yeniden inşa etmek için başka bir senaryo gerektirir. - Mario
Önbelleğe alınmış öğeleri neden silmeniz gerekmiyor? Chmod'u duymadın mı? - SchizoDuckie
Önerebileceğim tek şey, bu soruyu, cevabınızı, alt kısımdaki cevabımı ve buradaki yorumumu dikkatle tekrar okumaktır. Bu durumda önbellek önbelleği arızalı. - Mario
gerçekten düşünüyorum sen soru sormuyorlar. Fotoğraflarını yerleştirdikleri dizine yüklenen yeni bir dosya varsa önbelleğin yenilenmesini ister. Benim çözümüm o tetiği beklemek ve ardından önbelleği silmek. Sorun ne? - SchizoDuckie
Cevabını tekrar okuduğumda, benim yaptığımın aynısı olan çözümü kastediyorsun. - SchizoDuckie


IMO edubem cevabı gitmek için yol, ancak böyle bir şey yapabilirsiniz:

if (sha1(serialize(Map('/path/to/directory/', true))) != /* previous stored hash */)
{
    // directory contents has changed
}

Ya da daha zayıf / daha hızlı bir versiyon:

if (Size('/path/to/directory/', true) != /* previous stored size */)
{
    // directory contents has changed
}

İşte kullanılan fonksiyonlar:

function Map($path, $recursive = false)
{
    $result = array();

    if (is_dir($path) === true)
    {
        $path = Path($path);
        $files = array_diff(scandir($path), array('.', '..'));

        foreach ($files as $file)
        {
            if (is_dir($path . $file) === true)
            {
                $result[$file] = ($recursive === true) ? Map($path . $file, $recursive) : $this->Size($path . $file, true);
            }

            else if (is_file($path . $file) === true)
            {
                $result[$file] = Size($path . $file);
            }
        }
    }

    else if (is_file($path) === true)
    {
        $result[basename($path)] = Size($path);
    }

    return $result;
}

function Size($path, $recursive = true)
{
    $result = 0;

    if (is_dir($path) === true)
    {
        $path = Path($path);
        $files = array_diff(scandir($path), array('.', '..'));

        foreach ($files as $file)
        {
            if (is_dir($path . $file) === true)
            {
                $result += ($recursive === true) ? Size($path . $file, $recursive) : 0;
            }

            else if (is_file() === true)
            {
                $result += sprintf('%u', filesize($path . $file));
            }
        }
    }

    else if (is_file($path) === true)
    {
        $result += sprintf('%u', filesize($path));
    }

    return $result;
}

function Path($path)
{
    if (file_exists($path) === true)
    {
        $path = rtrim(str_replace('\\', '/', realpath($path)), '/');

        if (is_dir($path) === true)
        {
            $path .= '/';
        }

        return $path;
    }

    return false;
}

2
2017-12-13 10:13





Bir kullanıcı dizine bir dosya yüklediğinde önbelleğe alınmış sürümü silmeyi deneyin.

Birisi galeriyi görüntülemeye çalıştığında, önce önbelleğe alınmış bir sürüm olup olmadığına bakın. Önbelleğe alınmış bir sürüm varsa, yükleyin, aksi takdirde sayfayı oluşturun, önbelleğe alın, tamamlayın.


1
2018-02-12 11:50



Bu mantıklı, ancak yüklenen bir dosyayı nasıl izlerim? Komut dosyası yalnızca bir kullanıcı sayfayı ziyaret ettiğinde yürütür, bir dizini aktif olarak izleyemiyorum, bu yüzden dir değiştirilen tarihi kontrol etmeye çalıştım. - PHLAK