Maison  >  Questions et réponses  >  le corps du texte

Tableaux en PHP : résultats surprenants lors de l'ajout de nouveaux éléments

J'écris donc du code qui me permet de collecter des images collectées par la bibliothèque python Instaloader et de les mettre dans une galerie sur mon site Web. J'ai réussi à les collecter et à les afficher sans aucun problème, mais j'ai maintenant commencé à implémenter des en-têtes pour chaque message et je rencontre des problèmes.

La façon dont la bibliothèque télécharge les photos est que s'il y a plus d'une photo dans la collection, elle ajoutera les suffixes _1, _2, etc. à la publication en fonction de la position de l'image dans la collection et fournira le fichier .txt comme un titre.

Exemple de contenu de dossier pour la collecte :

2022-12-26_14-14-01_UTC.txt
2022-12-26_14-14-01_UTC_1.jpg
2022-12-26_14-14-01_UTC_2.jpg
2022-12-26_14-14-01_UTC_3.jpg

Les publications uniques fonctionnent bien Exemple :

2022-12-31_18-13-43_UTC.txt
2022-12-31_18-13-43_UTC.jpg

Bloc de code principal :

$array = []; 
$account_name = "everton";
$file_directory = "images/instagram";
$count = 0;

$hasvideo = 0;
$hasCaption = 0;

$handle = opendir(dirname(realpath(__DIR__)).'/'.$file_directory.'/');
while($file = readdir($handle)){
    $date = substr($file, 0, strpos($file, "_UTC"));
    $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION)); // Using strtolower to overcome case sensitive
    if($ext === 'jpg'){
        $count++;

        $collectionSize = (int)str_replace("_", "", str_replace(".jpg", "", explode("UTC",$file)[1]));
        if(!is_numeric($collectionSize)){
            $collectionSize = 0;
        }

        $arrayKey = array_search($date, array_column($array, 'date'));

        if($arrayKey){
            $amount = intval($array[$arrayKey]['collection-size']);
            
            if($collectionSize > $amount){
                $array[$arrayKey]['collection-size'] = (int)$collectionSize;
            }
        }else{
            array_push($array, array ("date" => $date, "collection-size" => (int)$collectionSize, "has-video" => false));
        }
    }
    
    if ($ext === "txt"){
        $file_location = dirname(realpath(__DIR__)).'/'.$file_directory.'/'. $file;
        $myfile = fopen( $file_location, "r") or die("Unable to open file!");
        $caption = fread( $myfile, filesize($file_location));
        $arrayKey = array_search($date, array_column($array, 'date'));

        //$arrayKey returns false when there is a collection. 
        if($array[$arrayKey]){
            $array[$arrayKey]['caption'] = $caption;
        }else{
            array_push($array, array ("date" => $date, "caption" => $caption));
        }
        fclose($myfile);
    }
}

$arrayKey renvoie false lorsque la collection existe sur une seule publication régulière.

Je pense que cela a à voir avec l'ordre des fichiers dans lequel le script lit ces fichiers, car je suppose qu'il lit (date).txt avant de lire (date)_(collectionposition).jpg

Si l'entrée du tableau a déjà été créée, l'en-tête est généralement ajouté aux données du tableau, sinon (par exemple lorsque _1, _2, etc. sont présents), le tableau ne met rien à jour et aucune erreur n'est générée.

Modifier : Un dépannage plus approfondi montre que la façon dont je mets à jour/vérifie les clés du tableau en fonction de la valeur "date" est erronée, j'espère que la bonne façon de gérer ces opérations pourra être trouvée

Tout conseil sur ce que je peux corriger pour que cela fonctionne comme prévu serait apprécié, merci !

P粉893457026P粉893457026225 Il y a quelques jours491

répondre à tous(1)je répondrai

  • P粉739942405

    P粉7399424052024-04-01 00:29:12

    Étudions d’abord votre code. La question que vous avez mentionnée, c'est-à-dire. Les lignes suivantes :

    $arrayKey = array_search($date, array_column($array, 'date'));

    ...Retour false,因为处理 .txt 文件时尚未创建带有日期的 $array 条目。 (使用 array_push La logique de création des membres du tableau se trouve sous le code. )

    Correction simple pour continuer à passer à la partie pertinente de la if/elselogique pas encore définie :

    if($arrayKey !== false && $array[$arrayKey]){
    ...

    Autrement dit, si $arrayKey不是false, continuez à ajouter la valeur au membre du tableau existant. Sinon, créez un membre du tableau.

    De plus, il y a un problème lors du traitement des images, qui génère un avertissement la première fois que cela se produit :

    $amount = intval($array[$arrayKey]['collection-size']);

    Cela échouera avec clé de tableau non définie 'collection-size' car la clé collection-size n'existe pas encore. Corrigez par exemple l'utilisation de l'opérateur de fusion nul pour définir "zéro par défaut" avant d'essayer d'opérer sur les clés du tableau :

    $array[$arrayKey]['collection-size'] ??= 0;

    Ces commentaires corrigent le bug, mais il serait préférable de séparer la "création d'entrée" dans la première instance de txt ou jpg - utilisez un membre de tableau vide avec la clé attendue, avant d'effectuer toute logique spécifique txt/jpg. J'utiliserai simplement $date 本身作为分组,这样您也可以摆脱 array_search. Par exemple, après avoir extrait la date, utilisez :

    $array[$date] ??= [
        'date' => $date,
        'caption' => '',
        'collection-size' => 0,
        'has-video' => false,
    ];

    Modifiez ensuite le reste du code pour qu'il corresponde. Votre code ne doit pas dépendre de l'ordre dans lequel les fichiers sont lus. La commande n'est pas garantie. Sinon, vous pouvez toujours lire d'abord la liste des fichiers dans un tableau normal, puis les trier et réitérer lors de l'application d'une logique spécifique.

    Code simplifié

    La quantité réelle de code requise est bien inférieure à celle dont vous disposez. Je l'ai coupé pour vous ici. Je n'ai pas votre fichier, alors voici quelques données factices :

    $files = <<
    

    Vous pouvez également mettre glob fichiers dans un tableau (= liste des chemins de fichiers) :

    $file_directory = "images/instagram";
    $files = glob(dirname(realpath(__DIR__)).'/'.$file_directory.'/*');

    Puis répétez comme suit :

    foreach($files as $filepath) {
        $filename = basename($filepath);
        $date = strstr($filename, '_UTC', true);
        
        $array[$date] ??= [
            'date' => $date,
            'caption' => '',
            'collection-size' => 0,
            'has-video' => false,
        ];
        
        $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
        
        if($ext === 'jpg'){
            // Each JPG increments collection size:
            $array[$date]['collection-size']++;
        }
        
        elseif ($ext === "txt"){
            // We use a dummy here:
            $caption = '---';
            // $caption = file_get_contents($filepath);
    
            $array[$date]['caption'] = $caption;
        }
    }

    Remarquez à quel point il rétrécit. ce qui s'est passé?

    • Nous utilisons $date 作为数组的分组索引。不再有 array_search !
    • Nous initialisons une entrée par défaut pour chaque date. Aucune autre inspection ou condition requise !
    • Nous ignorons le _3 dans le nom du fichier et ainsi de suite pour la « taille de la collection » : ajoutez simplement +1 à chaque JPG.
    • Nous utilisons nglobfile_get_contents 而不是 readdirfopen.
    • L'ordre des fichiers n'a pas d'importance. (N'hésitez pas à tester et shuffle($files) !)

    Résultat :

    array(3) {
        ["2022-12-26_14-14-01"] · array(4) {
            ["date"] · string(19) "2022-12-26_14-14-01"
            ["caption"] · string(3) "---"
            ["collection-size"] · int(3)
            ["has-video"] · bool(false)
        }
        ["2022-12-27_14-14-01"] · array(4) {
            ["date"] · string(19) "2022-12-27_14-14-01"
            ["caption"] · string(3) "---"
            ["collection-size"] · int(2)
            ["has-video"] · bool(false)
        }
        ["2022-12-31_18-13-43"] · array(4) {
            ["date"] · string(19) "2022-12-31_18-13-43"
            ["caption"] · string(3) "---"
            ["collection-size"] · int(1)
            ["has-video"] · bool(false)
        }
    }

    répondre
    0
  • Annulerrépondre