Domanda di ordinamento PHP

2

Ho un sistema di sicurezza basato su telecamere che carica tutte le sue immagini via FTP in una cartella in uno dei miei account di hosting. (FYI, lo uso per guardare i miei gatti quando sono in viaggio). Così ho creato un file PHP per visualizzare semplicemente tutte le immagini insieme ai loro nomi e timestamp. Sfortunatamente il software della fotocamera crea cartelle separate per ogni telecamera e un'altra per ogni giorno. Così ho usato la classe RecursiveDirectoryIterator, che rende facile costruire array contenenti solo i file di immagine, il che rende la visualizzazione abbastanza facile. Ma ora mi rendo conto che sarebbe molto più utile se mostrasse tutti i file in ordine di data e ora.

Nel seguito, puoi vedere dove ho costruito gli array per tutti i timestamp, i nomi di file e fullpath in modo da poterli visualizzare nel ciclo for () in basso. Penso che quello che devo fare ora è creare una serie di indici $ che sono basati su una sorta di data / ora. quindi nel ciclo di visualizzazione, potrei sostituire $ indexes [$ i] ovunque sia usato il semplice indice $ i ora. Ma non sono sicuro di come farlo. Grazie per l'aiuto.

Modifica: mi rendo conto che dovrò aggiungere una riga per salvare gli interi rawtimestamp in un array, per il modo in cui lo ordino.

<?php
$dir_path = "private/cats/";
$extensions_array = array('jpg','png','jpeg','JPG','PNG','JPEG');
$total = 0;

$objects = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir_path),

RecursiveIteratorIterator::LEAVES_ONLY);
  foreach($objects as $filepath => $object)
  {
   $fileinfo = pathinfo($filepath);
   // skip if no extension, or extension not in my allowed list
   if (!isset($fileinfo['extension'])) continue;
   if (!in_array($fileinfo['extension'], $extensions_array)) continue;

   $timestamps[$total] = date("F d Y H:i:s", filemtime($filepath));
   $filenames[$total] = $fileinfo['filename'] . "." .  $fileinfo['extension'];
   $filepaths[$total] = $filepath;

   $total++;

  }

echo "<h1>$total Image Files</h1>";
for ($i=0; $i < $total; $i++)
  {
   echo "<br><hr><h1>$filenames[$i] &nbsp;&nbsp; $timestamps[$i] <br></h1>";
   echo "<img src='$filepaths[$i]' style='width:100%;height:auto;'><br>";
  }
?>
    
posta Randy 18.11.2018 - 19:54
fonte

2 risposte

0

Mantenere 3 array diversi sincronizzati durante l'ordinamento sarà un compito difficile.

Vorrei invece utilizzare un array associativo multidimensionale OPPURE un tipo / struttura di tipo di struttura dati di base per contenere tutti e 3 gli elementi di dati su ciascun file come un'unica unità. Dato che sono pigro e la domanda è probabile che venga bloccata, array associativo:

  foreach($objects as $filepath => $object)
  {
   $fileinfo = pathinfo($filepath);
   // skip if no extension, or extension not in my allowed list
   if (!isset($fileinfo['extension'])) continue;
   if (!in_array($fileinfo['extension'], $extensions_array)) continue;
   /*
   $timestamps[$total] = date("F d Y H:i:s", filemtime($filepath));
   $filenames[$total] = $fileinfo['filename'] . "." .  $fileinfo['extension'];
   $filepaths[$total] = $filepath;
   */
   $files[]=array("timestamp"=>filemtime($filepath),
                  "filename"=>$fileinfo['filename'].".".$fileinfo['extension'],
                  "filepath"=>$filepath);

  }

Ora puoi scrivere la tua funzione di ordinamento in base al timestamp (memorizzato in unix time ancora, format on display ma pure int è più facile da ordinare) e chiamalo con usort() . Una volta ordinato, esegui il ciclo, ovvero $files[42]['timestamp'] etc

    
risposta data 18.11.2018 - 20:14
fonte
0

OK, concederò che ci sono molti costrutti PHP che non capisco, e ho la tendenza ad usare metodi più semplici di stile "C" della vecchia scuola. Ma il primo obiettivo è quello di far funzionare il codice come desiderato, e quindi migliorarlo. Con questo in mente, un'ulteriore complicazione che ho scoperto è che, per qualche ragione, il mio software di sicurezza della videocamera carica occasionalmente file duplicati (stesso contenuto, stesso nome e timestamp) nelle diverse directory. Quindi ecco la mia soluzione globale per visualizzare le immagini in ordine, eliminando i duplicati. Quest'ultima parte non è ancora perfetta, perché finora sto solo ipotizzando che i timestamp duplicati significano file duplicati. Ma ho mostrato un modo di mantenere più file con data / ora dup nei commenti.

Quindi, per prima cosa, ho modificato il blocco di codice originale per registrare anche i rawtimestamp $, insieme ai nomi dei file, ai timestamp formattati e ai percorsi completi. Come qualcuno ha già indicato in un'altra risposta, gli interi grezzi di data e ora saranno certamente più facili da ordinare.

    <?php
$dir_path = "private/cats/";
$extensions_array = array('jpg','png','jpeg','JPG','PNG','JPEG');
$total = 0;

$objects = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir_path), RecursiveIteratorIterator::LEAVES_ONLY);
foreach($objects as $filepath => $object)
  {
   $fileinfo = pathinfo($filepath);
   // skip if no extension, or extension not in my allowed list
   if (!isset($fileinfo['extension'])) continue;
   if (!in_array($fileinfo['extension'], $extensions_array)) continue;

   $rawTimestamps[$total] = filemtime($filepath); // <- new addition.
   $timestamps[$total] = date("F d Y H:i:s", filemtime($filepath));
   $filenames[$total] = $fileinfo['filename'] . "." .  $fileinfo['extension'];
   $filepaths[$total] = $filepath;

   $total++;

  }

Poi ho inventato questo loop di forza bruta per creare un nuovo array chiamato $ indexes. Servirà come una tabella di mappatura, tenendo gli indici a timestamp progressivamente più alti negli array originali.

 $max = max($rawTimestamps);
 $newtotal=0;

 for ($i=0; $i < $total; $i++)
  {
   $lowest = min($rawTimestamps);
   if ($lowest > $max) break;  // stop when no more.

   for ($j= 0; $j < $total; $j++)
     {
      if ($rawTimestamps[$j] != $lowest) continue;
      $indexes[$newtotal] = $j;    // keep index. overwrite duplicates
      $rawTimestamps[$j] = $max+1; // ensure never counted again.
     }
  $newtotal++;   // ** this is the new real total

  }

Quello che sta accadendo qui è che ho usato la funzione max () per registrare il valore più alto nella matrice $ rawtimestamp. Quindi nel ciclo esterno registro il valore minimo di $ nell'array timestamp non elaborato, uscendo quando il numero più basso rilevato è maggiore del valore massimo trovato originariamente. Questo sarà jmake in un attimo. Nel ciclo interno cerco il timestamp "più basso" e quando lo trovo, inserisco l'indice ($ j) nel punto in cui è stato trovato nel mio nuovo array $ indexes. Quindi sostituisco il timestamp non elaborato con un numero maggiore del valore massimo originariamente trovato. In questo modo non verrà più trovato dal loop interno. Questo distrugge $ rawtimeatamps mentre il processo continua, ma non ne avrò più bisogno. Quando il timestamp più basso trovato è uguale al valore massimo originariamente determinato, significa che tutti i $ rawtimestamps sono stati sostituiti e il loop esiste con un'interruzione;

Si noti che $ newTotal viene conteggiato e utilizzato per fare riferimento a dove sono memorizzati gli indici $ successivi. Se vengono rilevati timestamp duplicati, vengono sovrascritti, poiché il $ newtotal non viene incrementato fino all'uscita dal ciclo interno. Se volessi conservare più file con lo stesso timestamp, commenta dove viene incrementato $ newtotal e modifica questa riga in modo tale che gli incrementi totali ogni volta che viene inserito un valore in $ indici ...

$indexes[$newtotal++] = $j;    // keep index and do NOT overwrite duplicates

Quindi ora tutto ciò che dovevo fare era modificare il mio loop di visualizzazione. Invece di indicizzare direttamente i miei nomi di file, uso la mia "mappa" $ index per "cercare" i dati del file in base a timestamp progressivamente più alti, come li visualizzo.

  echo "<h1>$newtotal Image Files</h1>";
  for ($i=0; $i < $newtotal; $i++)
    {
    $ix= $indexes[$i]; // get index to progressively older files 
    echo "<br><hr><h1>$filenames[$ix] &nbsp;&nbsp; $timestamps[$ix] <br></h1>";
    echo "<img src='$filepaths[$ix]' style='width:100%;height:auto;'><br>";
    }

Ancora una volta, sono sicuro che questa non è una soluzione eloquente, ma funziona. Se qualcuno desidera offrire un modo migliore di fare ciò che ho fatto qui, sono felice di imparare.

    
risposta data 18.11.2018 - 23:24
fonte

Leggi altre domande sui tag