Ankündigung

Einklappen
Keine Ankündigung bisher.

Mehrere Einträge in mehreren Dateien speichern

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Mehrere Einträge in mehreren Dateien speichern

    Hey liebe Gemeinde,
    Zu Beginn erstmal folgender Code (das Nötigste):
    PHP-Code:
    <?php
    /**
    * class w_statistics
    *
    * classifies all statistics of DokuWiki
    */
    class w_statistics
    {
      private 
    $all_changes = array();

      
    /**
      * constructor
      *
      * defines var all_changes
      */
      
    public function w_statistics($fromcache=true)
      {
        if(
    $fromcache)
        {
          return 
    $this->get_cache();
        }
        else
        {
          return 
    $this->parse_changes();
        }
      }

      
    /**
      * get_cache
      *
      * gets data from cache
      */
      
    private function get_cache()
      {
        global 
    $conf;
        
        
    $check true;
        
    $cache_dir  $conf['cachedir'] . '/w_statistics/';
        
    $cache_file $cache_dir 'all_cached.changes.php';
        
        if(!@
    file_exists($cache_file) || !is_dir($cache_dir))
        {
          
    $check $this->write_cache($cache_dir$cache_file);
        }
            
        
    $last_update = @filectime($cache_file);
        if(
    time() > $last_update 60)
        {
          
    $check $this->write_cache($cache_dir$cache_file);
        }
        
        if(!
    $check)
        {
          return 
    false;
        }
        
        include_once(
    $cache_file);
            
        return 
    true;
      }
      
      
    /**
      * write_cache
      *
      * writes data in cache
      */
      
    private function write_cache($cache_dir$cache_file)
      {
        if(!
    $cache_dir || !$cache_file)
        {
          return 
    false;
        }
        
          if (!
    is_dir($cache_dir))
          {
              
    io_mkdir_p($cache_dir);  // DokuWiki framework
          
    }
        @
    unlink($cache_file);
        unset(
    $this->all_changes);
            
        
    $this->parse_changes();

        
    $fp       = @fopen($cache_file'w');
        
    $check_fw = @fwrite($fp"<?php
            if(!defined('DOKU_INC')) die('meh.');"
    );
        
    $i 0;
        foreach (
    $this->all_changes as $change)
            {
            @
    fwrite($fp'
                $this->all_changes['
    .$i.'] = array(
                  \'date\' => ' 
    $change['date'] . ',
                    \'ip\' => \'' 
    $change['ip'] . '\',
                    \'type\' => \'' 
    $change['type'] . '\',
                    \'id\' => \'' 
    $change['id'] . '\',
                    \'user\' => \'' 
    $change['user'] . '\',
                    \'sum\' => \'' 
    htmlspecialchars($change['sum'], ENT_QUOTES) . '\',
                    \'extra\' => \'' 
    $change['extra'] . '\',
                  );'
    );
              
    $i++;
          }
          @
    fclose($fp);
            
        
    // if anything false return false
        
    if(!$fp || !$check_fw)
        {
          return 
    false;
        }
        
        return 
    true;
      }
    /*...*/
    Wie zu erkennen ist, wird mit der Funktion parse_changes() die Variable $all_changes definiert (für mein Problem unbedeutend). Nun möchte ich, dass alle beispielsweise 20 Einträge eine neue Datei (z.b. all_cached.changes.1.php oder all_cached.changes.2.php) kreiert wird. Also quasi für jede 20 Einträge eine neue Seite.
    Hat jemand eine Idee, wie man das machen könnte?

    Gruß farady


  • #2
    Hat jemand eine Idee, wie man das machen könnte?
    Zähl-Variable und Datei-Namen nach einem Switch (Modulo-Operator!) ändern. Aber ganz ehrlich: das ist keine Frage für ein Fortgeschrittenen Forum.
    Viele Grüße,
    Dr.E.

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1. Think about software design before you start to write code!
    2. Discuss and review it together with experts!
    3. Choose good tools (-> Adventure PHP Framework (APF))!
    4. Write clean and reusable software only!
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Kommentar


    • #3
      Einfach einen Zähler mitlaufen lassen, und abfragen ...?


      Wie zu erkennen ist, [...]
      M.E. viel zu viel Code für solch eine simple Fragestellung.

      Kommentar


      • #4
        Zitat von ChrisB Beitrag anzeigen
        Einfach einen Zähler mitlaufen lassen, und abfragen ...?
        Ja dann schreib mir mal auf, wie du das in meinen Code implementieren willst, wenn das so einfach ist. =)
        Das hieße ja, ich üsste den Zähler laufen lassen, bevor ich die Datei zum schreiben öffne und die Daten auslese. Allerdings bauch ich den Zähler für die Daten selbst, die ich dann ja erst schreibe, wenn ich die Datei zum Schreiben geöffnet habe...

        Außerdem muss ich den Ordner doch beim includen auf Dateien ALLE Dateien untersuchen, die Changes beinhalten.

        Ganz so einfach ist das nämlich nicht. Wenns so einfach wäre, hätte ich's schon längst lösen können. Oder ich bin einfach strohdoof.

        Kommentar


        • #5
          Zitat von faraday Beitrag anzeigen
          Ja dann schreib mir mal auf, wie du das in meinen Code implementieren willst. =)
          Ich will es gar nicht implementieren, sondern du.

          Und dass ich mich in unkommentierten, fremden Quellcode gratis reindenke, nimmst du doch wohl nicht ernsthaft an.

          Außerdem muss ich den Ordner doch beim includen auf Dateien ALLE Dateien untersuchen, die Changes beinhalten.
          Die Vorgänge, die du jetzt hier erwähnst, fehlen in deiner bisherigen (verbalen) Problembeschreibung komplett.

          Kommentar


          • #6
            Zitat von ChrisB Beitrag anzeigen
            IchDie Vorgänge, die du jetzt hier erwähnst, fehlen in deiner bisherigen (verbalen) Problembeschreibung komplett.
            Tut mir Leid, dass es logisch ist, dass das dazugehört. O.o
            Eine normale "Seitenzahl" krieg ich wohl gerade so noch hin. Aber halt das ganze Zusammenspiel hier fällt mir etwas schwierig.

            Zitat von ChrisB Beitrag anzeigen
            Ich will es gar nicht implementieren, sondern du.

            Und dass ich mich in unkommentierten, fremden Quellcode gratis reindenke, nimmst du doch wohl nicht ernsthaft an.
            Das war eine sarkastische Bemerkung. Wenn du mir sagst, dass das alles so einfach sei, obwohl ich mir da die Zähne ausbeiße...

            P.S. Tut mir Leid, wenn das etwas unhöflich wirkt, das ist nicht meine Absicht.

            Kommentar


            • #7
              Ich wollte mich nochmal für mein eher unhöfliches Verhalten entschuldigen. Ich brauche allerdings noch einmal kurz Hilfe. Und zwar hab ich das Ganze jetzt mit zwei ineinanderliegenden for-Schleifen gelöst:
              PHP-Code:
              <?php
                  
              // open cache file and write it
                  
              $epf         200;  // int value (edits per file)
                  
              $num_entries count($this->all_changes);
                  
              $num_files   ceil($num_entries/$epf);
                  
                  for(
              $f=0$f<$num_files$f++)
                  {
                    
              $fp         = @fopen($_cache_file.'.part'.$f'w');
                    
              $check_fw   = @fwrite($fp"<?php
                        if(!defined('DOKU_INC')) die('meh.');"
              );
                    
                    for(
              $i=0$i<$epf$i++)
                    {
                      
              $tmpi $f*$epf+$i;
                            @
              fwrite($fp'
                            $this->all_changes['
              .$tmpi.'] = array(
                              \'date\' => ' 
              $this->all_changes[$tmpi]['date'] . ',
                                \'ip\' => \'' 
              $this->all_changes[$tmpi]['ip'] . '\',
                                \'type\' => \'' 
              $this->all_changes[$tmpi]['type'] . '\',
                                \'id\' => \'' 
              $this->all_changes[$tmpi]['id'] . '\',
                                \'user\' => \'' 
              $this->all_changes[$tmpi]['user'] . '\',
                                \'sum\' => \'' 
              htmlspecialchars($this->all_changes[$tmpi]['sum'], ENT_QUOTES) . '\',
                                \'extra\' => \'' 
              $this->all_changes[$tmpi]['extra'] . '\',
                              );'
              );
                    }
                    @
              fclose($fp);

                    
              // if anything false check is false
                    
              if(!$fp || !$check_fw)
                    {
                      
              $check false;
                    }
                  }
              Allerdings hat jede Datei jetzt 200 Einträge, obwohl beispielsweise nur 100 vorhanden sind (die letzten 100 sind dann leer). Ich habe schon überlegt das ganze mit einem statischen Zähler zu lösen, aber iwi liegt es mir auf der Zunge und ich komm' nicht drauf. Hat jemand eine gescheite Lösung parat? Oder lässt sich sogar umgehen, indem man etwas anderes als for-Schleifen verwendet.

              Dankesehr und Grüße

              Kommentar


              • #8
                Also, wenn ich Dein Problem richtig verstanden haben, hast Du ein array mit Daten und willst Daten aus diesem Array in verschiedene Dateien verteilen.

                Das wäre ja dann sowas:

                PHP-Code:
                $c = array(1,2,3,4,5,6,7,8,8,10);
                $start 0;
                $length 3;
                $file_counter 1;

                while(
                42){
                    
                $to_write array_slice($c,$start,$length);
                    
                $start $start+$length;
                    
                    if(empty(
                $to_write)){
                        break;
                    }else{
                        
                print_r($to_write);
                        
                //file_put_contents('my_file_'.$file_counter.'.txt',serialize($to_write));
                        
                $file_counter++;
                    }

                AFFE ist nur im Dezimalsystem ein Palindrom.

                Kommentar


                • #9
                  Zitat von agundur Beitrag anzeigen
                  Also, wenn ich Dein Problem richtig verstanden haben, hast Du ein array mit Daten und willst Daten aus diesem Array in verschiedene Dateien verteilen.

                  Das wäre ja dann sowas:

                  PHP-Code:
                  $c = array(1,2,3,4,5,6,7,8,8,10);
                  $start 0;
                  $length 3;
                  $file_counter 1;

                  while(
                  42){
                      
                  $to_write array_slice($c,$start,$length);
                      
                  $start $start+$length;
                      
                      if(empty(
                  $to_write)){
                          break;
                      }else{
                          
                  print_r($to_write);
                          
                  //file_put_contents('my_file_'.$file_counter.'.txt',serialize($to_write));
                          
                  $file_counter++;
                      }

                  Das ist ja cool. Viel einfacher als mein komplexes...Ding. Naja gut okay. Und mit unserialize kann ich die daten wieder auslesen, korrekt? Wie genau speicher ich das ganze dann in einem Array?

                  Dann wäre da nur noch eines: Ich muss ja noch die Dateien nacheinander auslesen. Also quasi den Ordner durchsuchen und dann schauen welche Dateien oder wieviele vorhanden sind von den Parts.

                  Danke bis hierher =)

                  Kommentar


                  • #10
                    Und mit unserialize kann ich die daten wieder auslesen, korrekt?
                    ja

                    Wie genau speicher ich das ganze dann in einem Array
                    array_push
                    AFFE ist nur im Dezimalsystem ein Palindrom.

                    Kommentar


                    • #11
                      Zitat von agundur Beitrag anzeigen
                      Super, danke. =)

                      Kommentar


                      • #12
                        Ich hab das Ganze jetzt so gemacht zum einbetten der Cache:
                        PHP-Code:
                        <?php
                        $cache_filename  
                        'all_changes.%d.txt';  // cache-filename
                        $_cache_file     $cache_dir $cache_filename;  // cachefile path

                        // get number of cache-files
                        $num_all_files   count(glob($cache_dir.'*'));
                        $num_cache_files 0;
                                
                        // count cache files
                        for($a=1$a<=$num_all_files$a++)
                        {
                              if(@
                        file_exists(sprintf($_cache_file,$a)))
                              {
                                
                        $num_cache_files++;
                              }
                        }

                        // get cache
                        for($i=1$i<=$num_cache_files$i++)
                        {
                              
                        $content = @unserialize(file_get_contents(sprintf($_cache_file,$i)));
                              
                              if(!
                        $content || !is_array($content))
                              {
                                continue;
                              }
                              
                              foreach(
                        $content as $entry)
                              {
                                
                        $this->all_changes[] = $entry;
                              }
                        }
                        ...und so zum Schreiben der Cache:
                        PHP-Code:
                        <?php
                        // create lock file
                        $lock_cache_file sprintf($_cache_file,0);
                        $lock = @fopen($lock_cache_file'w');
                        @
                        fclose($lock);

                        // delete cache-files and datas
                        unset($this->all_changes);
                        for(
                        $i=1$i<=$num_cache_files$i++)
                        {
                              @
                        unlink(sprintf($_cache_file,$i));
                        }
                                
                        // parse changes (defines all_changes)
                        $this->parse_changes();
                            
                        // save all_changes as txt
                        $start 0;
                        $length 500;  // number of entries per file
                        $file_counter 1;

                        // start loop
                        while(!empty($this->all_changes))
                        {
                              
                        $to_write array_slice($this->all_changes,$start,$length);  // devide array into parts
                              
                        $start $start+$length;  // redefine next start point

                              // if there's nothing to write break loop
                              
                        if(empty($to_write))
                              {
                                break;
                              }
                              else
                              {
                                
                        // put content into file and increase counter
                                
                        $file        sprintf($_cache_file,$file_counter);
                                
                        $put_content file_put_contents($file,serialize($to_write));
                                
                        $file_counter++;
                                
                                
                        // in case something goes wrong...
                                
                        if(!$put_content)
                                {
                                  
                        $check false;
                                }
                              }
                        }

                        // delete lock-file
                        @unlink($lock_cache_file);
                        Ich habe auch noch eine Lock-Datei programmiert. Hielt ich für sinnvoll, falls der Prozess etwas länger dauert oder noch nicht alle Cache-Dateien beschrieben wurden und parallel zum Write-Prozess auf die Cache zugegriffen wird.
                        An dieser Stelle nochmal vielen Dank. =)

                        Kommentar


                        • #13
                          Also, ich denke den einen oder anderen Loop könntest Du Dir sparen - beim Lesen -.
                          Du musst ja nicht erst alle Dateien zum zählen anfassen und dann nochmal zum lesen ... das geht auch in einem Rutsch ...

                          PHP-Code:
                          $cache_dir './';
                          foreach (new 
                          DirectoryIterator($cache_dir) as $fileInfo) {
                              if(
                          $fileInfo->isDot()) continue;
                              
                               
                          $content unserialize(file_get_contents($fileInfo->getPathname()));
                               
                               if(
                          $content)
                                   
                          array_push($this->all_changes,$content);

                          Das mit dem Lock kannst Du Dir wohl auch sparen wenn Du das einfach "file_put_contents" überlässt in dem Du ihm ein "LOCK_EX" mit gibst.
                          (Macht nur Sinn, wenn sich Daten in einzelnen Dateien zwischenzeitlich ändern dürfen)
                          AFFE ist nur im Dezimalsystem ein Palindrom.

                          Kommentar


                          • #14
                            Zitat von agundur Beitrag anzeigen
                            Also, ich denke den einen oder anderen Loop könntest Du Dir sparen - beim Lesen -.
                            Du musst ja nicht erst alle Dateien zum zählen anfassen und dann nochmal zum lesen ... das geht auch in einem Rutsch ...

                            PHP-Code:
                            $cache_dir './';
                            foreach (new 
                            DirectoryIterator($cache_dir) as $fileInfo) {
                                if(
                            $fileInfo->isDot()) continue;
                                
                                 
                            $content unserialize(file_get_contents($fileInfo->getPathname()));
                                 
                                 if(
                            $content)
                                     
                            array_push($this->all_changes,$content);

                            Das mit dem Lock kannst Du Dir wohl auch sparen wenn Du das einfach "file_put_contents" überlässt in dem Du ihm ein "LOCK_EX" mit gibst.
                            (Macht nur Sinn, wenn sich Daten in einzelnen Dateien zwischenzeitlich ändern dürfen)
                            Wenn ich das richtig sehe, liest dieser Code-Abschnitt ALLE Dateien des Cache Ordners? Eigentlich möchte ich den Ordner evtl. noch für weitere Cache-Dateien verwenden, von daher muss der Dateiname schon irgendwie rausgefiltert werden, oder seh ich da jetzt was falsch? :-/
                            Außerdem muss ich die Cache-Dateien noch löschen.

                            Könntest du mir das bitte mit "LOCK_EX" erklären? =)

                            Gruß faraday

                            Kommentar


                            • #15
                              Wenn ich das richtig sehe, liest dieser Code-Abschnitt ALLE Dateien des Cache Ordners?
                              Das ist richtig. Ändert aber nichts daran, das Du Die Dateien nicht erst zählen musst.
                              Wenn Du noch andere Dateien darin liegen hast kannst Du dem DirectoryIterator aber auch noch einen "FilterIterator" mitgeben, der dann nach bestimmten Kriterien ( z.B. Pre/Postfix) sucht.

                              Außerdem muss ich die Cache-Dateien noch löschen.
                              Naja, wenn Du Sie direkt nach dem lesen löschen wolltest, würde Dir ja nur noch ein "unlink" in dem DirectoryIterator -loop fehlen. Was aber bei einem Cache keinen Sinn ergeben würde ... nach jedem lesen neu aufbauen.

                              Wenn das Löschen in einen anderen Methode stattfindet kannst Du genau den gleichen code benutzen nur halt anstatt zu "lesen" halt dann löschen.

                              Könntest du mir das bitte mit "LOCK_EX" erklären?
                              Was genau ? Ich hab dazu auch noch ein "Edit" meines letzten Posts gemacht.
                              AFFE ist nur im Dezimalsystem ein Palindrom.

                              Kommentar

                              Lädt...
                              X