2016-04-27 3 views
0

Ich benutze ein Skript, das ich vor einiger Zeit auf Stack-Überlauf gefunden habe, um meine dynamische PHP-Seite zwischenzuspeichern, und ich bin ziemlich zufrieden mit der einfachen Lösung, da es einfach funktioniert und ich war kann es mit meinem rudimentären Wissen integrieren: D Es ist nur PHP-Code ohne die Verwendung von .htaccessEinfaches PHP-Caching erstellt zu viele Dateien - Unterordner erforderlich

Ein MD5-Hash der URL wird erstellt, um einen eindeutigen Namen für die Caching-Datei zu erstellen. Allerdings gibt es jetzt viele Dateien (ca. 300.000) in meinem Ordner, es ist nervig, beim Öffnen des Ordners per ftp auf die Ladezeiten zu warten. Um die Anzahl der Dateien in einem Ordner zu reduzieren, suche ich nach einer Lösung, um die ersten beiden Buchstaben als Namen von Unterordnern zu verwenden.

Wie es im Moment funktioniert:

  • URL: e72b0f58601e6d0c12f71a40b14101b7
  • Datei: cache/e72b0f58601e6d0c12f71a40b14101b7.html

Gewünschter Lösung:

  • URL: e72b0f58601e6d0c12f71a40b14101b7
  • Datei: cache/e7/e72b0f58601e6d0c12f71a40b14101b7.html

Die Unterverzeichnisse automatisch erstellt werden, wenn sie nicht existieren. Kann mir jemand mit dem Code helfen oder gibt es Bedenken gegen diese Lösung?

Dachte über die Verwendung der Substr-Befehl, aber meine "Experimente" hat nicht ganz gut funktioniert.

Vielen Dank im Voraus!

Update: Dank der Antworten konnte ich den Code erfolgreich bearbeiten. (: Stackflow/http://www.sanwebe.com/2013/09/php-cache-dynamic-pages-speed-up-load-times/ Quelle)

<?php 
//settings 
$cache_ext = '.html'; //file extension 
$cache_time  = 3600; //Cache file expires afere these seconds (1 hour = 3600 sec) 
$cache_folder = 'cache/'; //folder to store Cache files 
$ignore_pages = array('', ''); 

$dynamic_url = 'http://'.$_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . $_SERVER['QUERY_STRING']; // requested dynamic page (full url) 
$cache_file  = $cache_folder.md5($dynamic_url).$cache_ext; // construct a cache file 
$ignore = (in_array($dynamic_url,$ignore_pages))?true:false; //check if url is in ignore list 

if (!$ignore && file_exists($cache_file) && time() - $cache_time < filemtime($cache_file)) { //check Cache exist and it's not expired. 
    ob_start('ob_gzhandler'); //Turn on output buffering, "ob_gzhandler" for the compressed page with gzip. 
    readfile($cache_file); //read Cache file 
    echo '<!-- cached page - '.date('l jS \of F Y h:i:s A', filemtime($cache_file)).', Page : '.$dynamic_url.' -->'; 
    ob_end_flush(); //Flush and turn off output buffering 
    exit(); //no need to proceed further, exit the flow. 
} 
//Turn on output buffering with gzip compression. 
ob_start('ob_gzhandler'); 
######## Your Website Content Starts Below ######### 
?> 
<!DOCTYPE html> 
<html> 
    <head> 
     <title>Page to Cache</title> 
    </head> 
     <body> 
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer ut tellus libero. 
     </body> 
</html> 
<?php 
######## Your Website Content Ends here ######### 

if (!is_dir($cache_folder)) { //create a new folder if we need to 
    mkdir($cache_folder); 
} 
if(!$ignore){ 
    $fp = fopen($cache_file, 'w'); //open file for writing 
    fwrite($fp, ob_get_contents()); //write contents of the output buffer in Cache file 
    fclose($fp); //Close file pointer 
} 
ob_end_flush(); //Flush and turn off output buffering 

?> 

Wenn Sie in der Lösung interessiert sind, diese Zeilen aktualisiert werden müssen, die erforderlichen Änderungen können unter dem ursprünglichen Code

-Code Ich verwende für das Caching finden :

Original:

$cache_folder = 'cache/'; //folder to store Cache files 
$dynamic_url = 'http://'.$_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . $_SERVER['QUERY_STRING']; // requested dynamic page (full url) 

Aktualisiert (Dynamic URL ist die gleiche, aber wegen einer anderen Reihenfolge hier erwähnt wird):

$dynamic_url = 'http://'.$_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . $_SERVER['QUERY_STRING']; // requested dynamic page (full url) 
$cache_folder = 'cache/'.substr(md5($dynamic_url),0,2).'/'; //folder to store Cache files 

...

Original:

if (!is_dir($cache_folder)) { //create a new folder if we need to 
mkdir($cache_folder); 
} 

Aktualisiert:

if (!is_dir($cache_folder)) { //create a new folder if we need to 
mkdir($cache_folder, 0777, true); 
} 
+1

Die Aufteilung des MD5-Hash und das Erstellen der richtigen Verzeichnisse und Dateipfade scheint ziemlich einfach. Was hast du bisher versucht und wie funktioniert es nicht? – jeroen

Antwort

0

Statt

$cache_file = $cache_folder.md5($dynamic_url).$cache_ext; // construct a cache file 
... 
if (!is_dir($cache_folder)) { //create a new folder recuirsively if we need to 
    mkdir($cache_folder); 
} 

Verwenden

$cache_folder .= substr(md5($dynamic_url),0,2) . '/'; 
$cache_file = $cache_folder.md5($dynamic_url).$cache_ext; 
... 
if (!is_dir($cache_folder)) { //create a new folder if we need to 
     mkdir($cache_folder, 0777, true); 
} 

Dies wird die erste Zeichen des Dateinamens als einen neuen Unterordner hinzufügen und diesen Ordner rekursiv erstellen, wenn es nicht existiert.

+0

Vielen Dank, aber in Bezug auf den Ordner überprüft und erstellt nur die Hauptordner und nicht die Unterordner, oder? – Amsel

+0

Nur ein paar kleine Änderungen, aber mit Ihrem Ansatz funktioniert es. Danke vielmals! :) Ich werde meine Frage mit Ihrer Lösung zu aktualisieren – Amsel

+0

Gern geschehen. Wenn diese Antwort Ihnen geholfen hat, Ihr Problem zu lösen, dann überlegen Sie, die Antwort als "Lösung" zu markieren oder die Antwort zu verbessern. – maxhb

-1

Betrachten anderen Caching-Mechanismus anstatt Dateicache.

Sie sollten Redis oder Memcache als Cache-Speicher verwenden. Für den vollständigen Seitencache entscheiden Sie sich für eine CDN-Lösung.Es gibt kostenlose CDN wie Cloudfront.

+2

Dies ist nicht wirklich eine Antwort, mehr ein Kommentar. – jeroen

+0

Ja, ich werde irgendwann eine andere Technik in der Zukunft verwenden, aber im Moment ist es nicht möglich :() – Amsel

0

seine ärgerlich warten, wenn Sie den Ordner per FTP in Bezug auf die Ladezeiten

Ich bin mir nicht bewusst ein „Öffnen Sie den Ordner“ -Betrieb in FTP zu öffnen. Sicherlich, wenn Sie eine Auflistung des Ordners bekommen, wird es einige Zeit dauern, die Daten zu übertragen und auf Ihrem Client zu rendern. Es wirft die Frage auf, was Sie gewinnen, wenn Sie in den Ordner schauen.

Was eher ein Problem ist, ist die Zeit, die es dauert, ein einzelnes Objekt im Cache zu finden und Kandidaten für die Räumung zu identifizieren - aber das hängt vollständig vom Dateisystem ab, in dem sich die Daten befinden - und Sie haben nein angegeben Details davon, noch die Timings für diese Prozesse.

300.000 ist eine Menge Dateien - es könnte die richtige Zahl sein - wieder haben Sie keinen Hinweis darauf, ob dies erwartet wird. OTOH könnte auf ein Problem mit der Methode zum Generieren von Cache-Schlüsseln hinweisen und ob es für Ihre Anwendung geeignet ist.

Um Unterordner zu verwenden, einfach ändern:

$cache_file = $cache_folder.md5($dynamic_url).$cache_ext; 

zu

$cache_file = $cache_folder.mk_hash_path($dynamic_url,$cache_folder).$cache_ext; 
... 

function mk_hash_path($dynamic_url,$cache_folder) 
{ 
    md5($dynamic_url); 
    $subfolders=4; 
    while ($subfolders--) { 
    $hash=substr($hash, -$subfolders, 1) . '/' . $hash; 
    } 
    if (!is_dir(dirname($cache_folder . $hash))) { 
     mkdir(dirname($cache_folder . $hash,0777, true)) 
    } 
    return $hash; 
} 

Aber eine viel netten Idee, eine Caching-Reverse-Proxy zu verwenden wäre.

+0

Danke auch! In meinem Fall ist die Anzahl der Dateien richtig/beabsichtigt;) Das Skript verwendet viele APIs, daher war es die einfachste Lösung, die Ladegeschwindigkeit und die Anzahl der Anfragen an die API-Server zu reduzieren. Allerdings stimme ich zu, dass ich in Zukunft eine andere Lösung verwenden sollte (Memcache, Lack etc.) - aber ich muss auf einem dateibasierten Cache bleiben =) Bin ich richtig, dass ich die Funktion kopieren muss (mk_hash_path) über der Variablendeklaration von cache_file seit, um richtig zu laufen oder spielt es keine Rolle? – Amsel

+0

Sie benötigen die Funktion sowie die Änderung der Namensgenerierung. – symcbean

+0

Nein, es tut mir leid - ich bin kein Muttersprachler, ich meinte die chronologische Reihenfolge Ihres Codes, da sich die erste Zeile Ihres Codes auf die Funktion bezieht, die später in Ihrem Code kommt.Ich habe versucht, es zu implementieren, aber es ist auf diese Weise gescheitert. Allerdings war ich mit max 'approach :) trotzdem dankeschön – Amsel

Verwandte Themen