web-dev-qa-db-fra.com

Vérifier si les éléments d'un tableau existent dans la table et si non les insérer dans de nouveaux enregistrements?

J'ai un tableau de noms de fichiers d'image que je veux comparer à une table de ma base de données. Si le nom de fichier n'est pas présent, je veux l'insérer. J'ai commencé à travailler sur la déclaration insert, donc j'y reviendrai plus tard. Ce que je cherche, c’est de l’aide avec le code qui vérifie son existence, puis mène à la déclaration insert? Ci-dessous se trouve le code utilisé pour construire le tableau. Aurais-je intérêt à inclure le code à vérifier puis à insérer les données ici ou à créer une boucle foreach qui prend chaque élément du tableau et le vérifie?

//Create an array of all images that are Jpgs and start with 'n'
if ($dir = opendir($uploads))
{
  $images = array();

  foreach (glob($uploads."*.{jpg,jpeg,JPG,JPEG}", GLOB_BRACE) as $filename)
  {
    $f = str_replace($uploads, null, $filename);
    if (strtolower($f[0]) == 'n')
    {
      $images[] = $f;
    }
  }
}  

Nous vous remercions de votre soutien continu.

Donna

Edit: Merci @Lodder pour votre code. J'ai essayé de l'implémenter avec mon code existant, mais il semble échouer lors de l'affectation de la variable $ values. J'ai vérifié et je ne peux pas identifier une erreur de syntaxe particulière? Pouvez-vous repérer quelque chose? Voici mon code complet:

    <?php

    //display errors
    error_reporting(E_ALL);
    ini_set("display_errors", 1);

    //init Joomla Framework 
    define('_JEXEC', 1); 
    define('JPATH_BASE', dirname(__FILE__).'/');
    define('DS', DIRECTORY_SEPARATOR); 

    require_once (JPATH_BASE .DS. 'includes' .DS. 'defines.php'); 
    require_once (JPATH_BASE .DS. 'includes' .DS. 'framework.php');


    //Tell the code where the product images are
    //Use joomla API <-----------------------------------------------------------Needs looking at
    $uploads = '/home/#######/public_html/images/stories/virtuemart/product/';

    //Create an array of all image sthat are Jpgs and start with 'n'
    if ($dir = opendir($uploads))
    {
      $images = array();

      foreach (glob($uploads."*.{jpg,jpeg,JPG,JPEG}", GLOB_BRACE) as $filename)
      {
        $f = str_replace($uploads, null, $filename);
        if (strtolower($f[0]) == 'n')
        {
          $images[] = $f;
        }
      }
    } 

    //$images = array('image1.jpg', 'image2.jpg');

    //Start comparison
    $db = JFactory::getDbo();

    $query = $db->getQuery(true);
    $query->select($db->quoteName('file_url'))
          ->from($db->quoteName('#__virtuemart_medias'));
    $db->setQuery($query);

    $rows = $db->loadColumn();

    $differences = array_diff($rows, $images);

    foreach ($differences as $key => $val)
    {
        $query = $db->getQuery(true);
        $query->clear(); 
$filetitle = substr($f, 0, strrpos($f, '.'));   
    $filepath = "images/stories/virtuemart/product/".$f.;    

        $columns = array('virtuemart_vendor_id', 'file_title', 'file_description', 'file_mimetype', 'file_type', 'file_url','published');
        $values = array($db->quote('1'), $db->quote($filename), $db->quote($filetitle), $db->quote('images/jpeg'), $db->quote('Product'), $db->quote($filepath), db->quote('1'));

       $query->insert($db->quoteName('#__virtuemart_medias'))
              ->columns($db->quoteName($columns))
              ->values(implode(',', $values));

        $db->setQuery($query);
        echo $db->replacePrefix((string) $query);
        //$db->execute();
    }
    ?>

Merci.

1
Dtorr1981

Je vais essayer d'expliquer cela aussi facilement que possible:

$images = array('image1.jpg', 'image2.jpg');

$db = JFactory::getDbo();

$query = $db->getQuery(true);
$query->select($db->quoteName('COLUMN_NAME'))
      ->from($db->quoteName('#__tablename'));
$db->setQuery($query);

$rows = $db->loadColumn();

$differences = array_diff($rows, $images);

foreach ($differences as $key => $val)
{
    $query = $db->getQuery(true);
    $query->clear();

    $columns = array('COLUMN_NAME');
    $values = array($db->quote($val));

    $query->insert($db->quoteName('#__tablename'))
          ->columns($db->quoteName($columns))
          ->values(implode(',', $values));

    $db->setQuery($query);
    $db->execute();
}

Donc, à des fins de test, disons que $images Est votre tableau de noms d'images.

Vous devrez d’abord exécuter une requête select sur votre table contenant les images. Donc changez COLUMN_NAME Dans le code ci-dessus pour quel que soit le nom de votre colonne.


$rows = $db->loadColumn(); est maintenant votre tableau de tous les résultats de votre colonne.


$differences = array_diff($rows, $images); compare ensuite le tableau de votre base de données au tableau d'images défini dans la toute première ligne de code. Les résultats sont un tableau de valeurs qui ne pas correspondent.


Vous pouvez ensuite exécuter une requête insert dans une boucle foreach, qui parcourt le tableau $differences.


J'espère que cela t'aides

1
Lodder

Votre tentative de codage comportait quelques points.

  • Le chemin $upload Et le chemin file_url Ne correspondront jamais. J'ai donc repensé le processus d'appel de glob() et d'interrogation de la table de base de données afin que les valeurs soient comparables. comme "pomme à pomme" avant d'appeler array_diff().
  • Vous utilisez $f Dans votre deuxième boucle, mais cette variable ne portera que la valeur d'itération finale de la première boucle. Je pense que vous voulez probablement utiliser $val Dans la deuxième boucle (et $key N'est pas utilisé, il n'est donc pas nécessaire de le déclarer).
  • Je ne suis pas tout à fait sûr que vos assignations de colonne-> valeur étaient logiquement alignées dans votre extrait. J'ai fait quelques ajustements en fonction de ma propre pensée, mais s'ils ne sont pas ce que vous voulez, mes appels de diagnostic enqueueMessage() devraient vous aider à comprendre ce qui se passe.
  • Selon les meilleures pratiques de codage, vous devez minimiser le nombre total d’accès à la base de données. J'ai écrit mon code pour n'exécuter qu'une seule requête INSERT peu importe le nombre de lignes de données à sauvegarder.

Je l'ai couru sur mon localhost pour réussir. J'ai emballé autant de commentaires et de enqueueMessage() points de contrôle que possible afin de vous aider à voir ce qui est généré tout au long du processus. Cela fait paraître mon extrait plutôt "salissant". Ainsi, lorsque tout fonctionne comme vous le souhaitez, supprimez/commentez toutes mes lignes de diagnostic. Si vous rencontrez des problèmes avec mon extrait, merci de me le faire savoir afin que je puisse ajuster ma solution au profit des futurs chercheurs.

<?php    
//display errors
error_reporting(E_ALL);
ini_set("display_errors", 1);

//init Joomla Framework 
define('_JEXEC', 1); 
define('JPATH_BASE', dirname(__FILE__) . '/');
define('DS', DIRECTORY_SEPARATOR); 

require_once (implode(DS, [JPATH_BASE, 'includes', 'defines.php'])); 
require_once (implode(DS, [JPATH_BASE, 'includes', 'framework.php'));

//Tell the code where the product images are
$product_path_dirs = ['images', 'stories', 'virtuemart', 'product'];
$product_path = implode('/', $product_path_dirs);
$uploads = JPATH_BASE . DS . implode(DS, $product_path_dirs) . DS;
// $uploads = '/home/#######/public_html/images/stories/virtuemart/product/';
JFactory::getApplication()->enqueueMessage("<div>\$uploads = <br><b>{$uploads}</b></div>", 'notice');

//Create an array of all images that are jpgs and start with 'n'
JFactory::getApplication()->enqueueMessage("<div>Original Working Directory = <br><b>" . getcwd() . "</b></div>", 'notice');
chdir($uploads); // this eliminates the path from the glob() array values
JFactory::getApplication()->enqueueMessage("<div>New Working Directory = <br><b>" . getcwd() . "</b></div>", 'notice');

$server_filenames = glob("n*.{jpg,jpeg,JPG,JPEG}", GLOB_BRACE);
                    //       ^^^^^^^^^^^^^^^^^^^- whitelist of case-insensitive file extensions
                    //      ^- literal dot
                    //     ^- zero or more of any character
                    //    ^- starts with n

// apply url path to filenames
$server_filenames = array_map(function ($v) use ($product_path) {
    return "{$product_path}/{$v}";
}, $server_filenames);
JFactory::getApplication()->enqueueMessage("<div>\$server_filenames (as json) = <br><b>" . json_encode($server_filenames) . "</b></div>", 'notice');

// Retrieve existing image filenames from db
$db = JFactory::getDbo();
$select_query = $db->getQuery(true)
                   ->select("file_url")
                   ->from("#__virtuemart_medias")
                   ->where("file_url LIKE '{$product_path}/n%g'");  // some general filtering is applied here (this could be further refined)
                                                                    // assuming case-insensitive COLLATION utf8_general_ci
$db->setQuery($select_query);
JFactory::getApplication()->enqueueMessage("<div>Rendered Select Query<br><b>" . $select_query->dump() . "</b></div>", 'notice');
try
{
    $db_filenames = $db->loadColumn();
}
catch (Exception $e)
{
    JFactory::getApplication()->enqueueMessage("Select Query Syntax Error " . $e->getMessage(), 'error');
    // use $e->getMessage() only while debug and page is not viewable by public
    exit('script halted');
}

if (!$difference = array_diff($server_filenames, $db_filenames)) {  // declare $difference and check if empty
    JFactory::getApplication()->enqueueMessage("<div>No New Qualifying Image Files Found</div>", 'notice');
}
else
{
    JFactory::getApplication()->enqueueMessage("<div>\$db_filenames (as json) = <br><b>" . json_encode($db_filenames) . "</b></div>", 'notice');
    JFactory::getApplication()->enqueueMessage("<div>\$difference (as json) = <br><b>" . json_encode($difference) . "</b></div>", 'notice');
    // build query with all static parts
    $insert_query = $db->getQuery(true)
                       ->insert("#__virtuemart_medias")
                       ->columns("virtuemart_vendor_id, file_title, file_description, file_mimetype, file_type, file_url, published");

    // iterate new, unique filenames and write separate rows for insertion
    foreach ($difference as $new_filename) {
        $path_parts = pathinfo($new_filename);
        $values = [
            1,                               // virtuemart_vendor_id
            $db->q($path_parts['filename']), // file_title
            $db->q($path_parts['basename']), // file_description
            $db->q('images/jpeg'),           // file_mimetype
            $db->q('Product'),               // file_type
            $db->q($new_filename),           // file_url
            1                                // published
        ];
        $insert_query->values(implode(',', $values));
    }
    JFactory::getApplication()->enqueueMessage("<div>Rendered Insert Query<br><b>" . $insert_query->dump() . "</b></div>", 'notice');
    $db->setQuery($insert_query);
    try {
        $db->execute();
        JFactory::getApplication()->enqueueMessage("<div>" . $db->getAffectedRows() . " Rows Of Data Inserted", 'success');
    } catch (Exception $e) {
        JFactory::getApplication()->enqueueMessage("Insert Query Syntax Error: " . $e->getMessage(), 'error');
        // use $e->getMessage() only while debug and page is not viewable by public
    }
}
0
mickmackusa