Iterazione array

MarcoGrazia

Utente Attivo
15 Dic 2009
852
20
28
63
Udine
www.stilisticamente.com
Ciao, ho un array multidimensionale a lunghezza variabile che definisce l'indice di un libro.
E' formato da tra Array: voce, dallaPagina, allaPagina e devo iterarlo.

l'Array:
Codice:
$target = [
  'Voce' => [
      1 => string 'Capitolo 1' (length=10)
      2 => string 'Capitolo 2' (length=10)
      3 => string 'Capitolo 3' (length=10)
  ],
  'DallaPagina' => [
      1 => string '1' (length=1)
      2 => string '99' (length=2)
      3 => string '151' (length=3)
  ],
  'AllaPagina' => [
      1 => string '98' (length=2)
      2 => string '150' (length=3)
      3 => string '160' (length=3)
   ]
]

Il tutto va iterato per inserirlo in un record di database ed avevo pensato di fare una cosa del genere:
PHP:
            $sql = 'INSERT INTO indici ';
            $sql .= '(libro_id, voce, dalla_pagina, alla_pagina) ';
            $sql .= 'VALUES (:idI, :v, :dp, :ap); --';
            $handle = $pdo->prepare($sql);
            $index = 1;
            $idFascicolo = 3;
            try {
                //    Inserimento selettivo delle voci
                $pdo->beginTransaction();
                foreach( $target as $t ) {

                    $handle->bindValue(':idI', $idFascicolo, PDO::PARAM_INT);
                    $handle->bindValue(':v', $t['Voce'][$index], PDO::PARAM_STR);
                    $handle->bindValue(':dp', $t['DallaPagina'][$index], PDO::PARAM_STR);
                    $handle->bindValue(':ap', $t['AllaPagina'][$index], PDO::PARAM_STR);
                    $handle->execute();
                    
                    $index++;
                }
                $pdo->commit();
                unset( $pdo, $handle, $sql, $target );
            }
            catch( PDOException $err ) {
                $pdo->rollback();
                throw $err;
            }
ma il sistema mi da errori: Notice: Trying to access array offset on value of type int in C:\Apache\users\marco\moduli-2\putVoci.php on line 105 dove la riga 105 nel mio listato corrisponde all'istruzione: $handle->bindValue(':v', $t['cellaVoce'][$index], PDO::PARAM_STR); e così via per le altre due chiavi dell'array $target, ovvero le due righe seguenti del Binding sempre lo stesso errore.
Quindi infine: Fatal error: Uncaught PDOException: SQLSTATE[23000]: Integrity constraint violation: 1048 La colonna 'voce' non puo` essere nulla in C:\Apache\users\marco\moduli-2\putVoci.php on line 108 dove la riga 108 corrisponde a $handle->execute();
Che appunto mi fa capire che non ho iterato un bel nulla.
 
Ciao, mi pare ci sia un problema di logica.

In quel foreach stai iterando proprio la prima dimensione del vettore $target, per cui il ciclo è eseguito esattamente per quei tre elementi ('Voce', 'DallaPagina' e 'AllaPagina'). La variabile $t, ad ogni iterazione, assume rispettivamente il riferimento a $target['Voce'], $target['DallaPagina'] e $target['AllaPagina'], però tu stai già riferendoti specificatamente (e in modo statico) a quegli elementi nel codice dentro il ciclo.

In sostanza, con questo tuo codice:
PHP:
$handle->bindValue(':v', $t['Voce'][$index], PDO::PARAM_STR);
$handle->bindValue(':dp', $t['DallaPagina'][$index], PDO::PARAM_STR);
$handle->bindValue(':ap', $t['AllaPagina'][$index], PDO::PARAM_STR);

alla prima iterazione del ciclo foreach, ottieni un risultato equivalente a questo codice:
PHP:
$handle->bindValue(':v', $target['Voce']['Voce'][1], PDO::PARAM_STR);
$handle->bindValue(':dp', $target['Voce']['DallaPagina'][1], PDO::PARAM_STR);
$handle->bindValue(':ap', $target['Voce']['AllaPagina'][1], PDO::PARAM_STR);

alla seconda iterazione, ottieni questo:
PHP:
$handle->bindValue(':v', $target['DallaPagina']['Voce'][2], PDO::PARAM_STR);
$handle->bindValue(':dp', $target['DallaPagina']['DallaPagina'][2], PDO::PARAM_STR);
$handle->bindValue(':ap', $target['DallaPagina']['AllaPagina'][2], PDO::PARAM_STR);

e così via.

Puoi capire che l'impostazione è sbagliata a livello logico.

Se conosci già a priori la prima dimensione (dal momento che le stesse chiavi le usi staticamente dentro il ciclo), e se la seconda dimensione ha una lunghezza uguale per tutti gli elementi della prima dimensione, puoi iterare solo la seconda dimensione (cioè l'indice) con un semplice for, dove &index parte da 1 e arriva alla lunghezza X (valore che puoi recuperare contando la lunghezza di un qualsiasi elemento della prima dimensione).

Potrebbe essere quindi una cosa del genere:
PHP:
$target = [
  'Voce' => [
      1 =>  'Capitolo 1',
      2 =>  'Capitolo 2',
      3 =>  'Capitolo 3'
  ],
  'DallaPagina' => [
      1 => '1',
      2 => '99',
      3 => '151'
  ],
  'AllaPagina' => [
      1 => '98' ,
      2 => '150',
      3 => '160'
   ]
];

for ($index = 1; $index <= count($target['Voce']); $index++) {

    $handle->bindValue(':idI', $idFascicolo, PDO::PARAM_INT);
    $handle->bindValue(':v', $target['Voce'][$index], PDO::PARAM_STR);
    $handle->bindValue(':dp', $target['DallaPagina'][$index], PDO::PARAM_STR);
    $handle->bindValue(':ap', $target['AllaPagina'][$index], PDO::PARAM_STR);
    $handle->execute();

}

A prescindere dal metodo usato, è essenziale che si riesca a comprendere la logica per ottenere il risultato voluto.

Fai sapere :)
 
Allora @WmbertSea :

utilizzando un ciclo for in luogo di quello foreach funziona, in effetti ho compreso il motivo per cui non poteva andare nel mio modo, ora però mi si è presentato un altro problema.

Mi registra solo le voci dispari.

Ecco un pezzetto del codice originale dopo le correzioni da te suggerite
PHP:
            $len = count($target['cellaVoce']); echo $len . '<br>';
            try {
                //    Inserimento selettivo delle voci
                $pdo->beginTransaction();
                echo 'Riporto ciclo for:<br>';
                for ( $index = 1; $index <= $len; $index++ ) {
                   
                    $handle->bindValue(':idF', $idFascicolo, PDO::PARAM_INT);
                    $handle->bindValue(':v', $target['cellaVoce'][$index], PDO::PARAM_STR);
                    $handle->bindValue(':dp', $target['cellaDalla'][$index], PDO::PARAM_STR);
                    $handle->bindValue(':ap', $target['cellaAlla'][$index], PDO::PARAM_STR);
                    $handle->execute();
                   
                    echo $index . ') ' . $target['cellaVoce'][$index] . '<br>';
                    $index++;
                }
                $pdo->commit();
                unset( $pdo, $handle, $sql, $target );
            }
            catch( Exception $err ) {
                $pdo->rollback();
                throw $err;
            }

le echo le ho messe per evidenziare le righe effettivamente processate, qui sotto metto il risultato così come viene riportato dall'analizzatore, dati riportati sono ovviamente fittizi anche se è una simulazione reale.
I dati sono passati tramite Ajax al file putVoci.php e qui processati e memorizzati nel database, quello riportato è il var_dump() dell'array $target dopo il filtraggio dei dati.
Come si vede ci sono tutti, ma solo i dispari vengono registrati come riportato in fondo

Codice:
C:\Apache\users\marco\moduli-2\putVoci.php:71:
array (size=7)
  'docElettronica' => null
  'ufficio' => int 1
  'numero' => int 1
  'anno' => int 2022
  'cellaVoce' =>
    array (size=4)
      1 => string 'Nota di iscrizione a ruolo' (length=26)
      2 => string 'Accordo di Negoziazione tra le parti ex lege 162/2014 art. 6' (length=60)
      3 => string 'Provvedimento del PM' (length=20)
      4 => string 'Allegati non catalogabili' (length=25)
  'cellaDalla' =>
    array (size=4)
      1 => string '1' (length=1)
      2 => string '2' (length=1)
      3 => string '9' (length=1)
      4 => string '10' (length=2)
  'cellaAlla' =>
    array (size=4)
      1 => string '*' (length=1)
      2 => string '8' (length=1)
      3 => string '*' (length=1)
      4 => string '*' (length=1)

4
Riporto cicolo for:
1) Nota di iscrizione a ruolo
3) Provvedimento del PM
 
Ultima modifica:
Fai attenzione, la variabile $index (che è il cosiddetto contatore del ciclo for) viene incrementata già nella inizializzazione del ciclo, per ogni iterazione che sarà eseguita. Non hai quindi bisogno di incrementarla nuovamente tra le istruzioni interne del ciclo.

RTF (BB code):
for ( $index = 1; $index <= $len; $index++ ) // Il contatore viene già incrementato qui
{
    [...]
    $index++; // Questo va rimosso
}
 
Fai attenzione, la variabile $index (che è il cosiddetto contatore del ciclo for) viene incrementata già nella inizializzazione del ciclo, per ogni iterazione che sarà eseguita. Non hai quindi bisogno di incrementarla nuovamente tra le istruzioni interne del ciclo.

RTF (BB code):
for ( $index = 1; $index <= $len; $index++ ) // Il contatore viene già incrementato qui
{
    [...]
    $index++; // Questo va rimosso
}
Uh porc.... che resti tra noi :D
era un ciclo creato prima con foreach... va bè capita. o_O
 

Discussioni simili