Потеря данных в цикле foreach

Борьба с этим проектом — у меня есть многомерный ассоциативный массив, который анализируется, чтобы вытащить имена таблиц, имена полей и данные для вставки в базу данных mysql. В функции array2query, если key: value является парой верхнего уровня, то $tablename имеет значение ‘project’, в противном случае $tablename=array name (отбрасывание array[0] array name). Данные не поступают пользователям, они поступают от вызова API в файле json. Реализация будет использовать PDO для записи в MySQL db.

Я получаю необъявленное уведомление о переменной на $sql. Если я объявляю его внутри функции, он сбрасывается в пустое состояние во время цикла foreach, и я теряю часть построенной строки $sql (все данные tablename ‘project’).

Мне также нужно отбросить данные, где $element равен null или пуст, но не 0 или ‘false’, что я не могу найти способ сделать чисто.

Как правильно обработать уведомление без потери существующей строки?

<?php

error_reporting(E_ALL);

//read the json file contents
$data = file_get_contents('c:wamp64wwwjsontest.json');
$data1 = preg_replace('/("w+"):(-?d+(.d+)?)/', '1:"2"', $data);
$array1 = json_decode($data1, true);

function array2query(array $array1, $tableName = ''){
       $sql="";  // not declaring variable results in NOTICE; declaring results in $sql being reset to "" during foreach loop
       foreach ($array1 as $key => $element) {
            if (is_array($element)) {
            // if key is integer then skip - it is the first level of array, keep the $tablename    
                $key = is_int($key) ? $tableName : $key;
                array2query($element, $key);
            } else {
                if ($tableName === '') {
                $tableName = 'project';
                }
            $sql .= 'INSERT INTO ' . $tableName . ' (' . rtrim($key, ',') . ') VALUES (' . rtrim($element, ',') . ');';
            //    }        
            } 
       }    
       echo $sql;  //dump to screen; missing non-nested values from tablename 'project' 
       return $sql;
    }

$array_query=array2query($array1);

Спасибо, что посмотрели на это. Тестовые данные на http://pastebin.com/iSvqCMxb

РЕДАКТИРОВАТЬ:
Дамп экрана от echo:

INSERT INTO Contacts (ContactType) VALUES (Sales);
INSERT INTO Contacts (ContactAddressId) VALUES (ec4539c0-9012-4b4f-a590-bee11cc91109);
INSERT INTO Contacts (ExportId) VALUES ();
INSERT INTO Vendors (VendorId) VALUES (c3abfde4-4390-4e09-aa5f-60284613c8c5);
INSERT INTO Vendors (Name) VALUES (Fabrication Specialists);
INSERT INTO Vendors (ShortName) VALUES (Fabspec);

Это отсутствует все » INSERT INTO (project)… » заявления.

4 ответа

  1. Если вы хотите создать строку рекурсивным вызовом функции, необходимо вернуть значение через параметр, используя ссылку, а не оператор return.

    Изменение подписи функции:

    function array2query(array $array1, &$sql, $tableName = '')
    

    Затем вызовите функцию с переменной, которая будет собирать инструкции SQL:

    $sql = '';
    $array_query=array2query($array1, $sql);
    

    Не забудьте также изменить рекурсивный вызов:

    if (is_array($element)) {
        $key = is_int($key) ? $tableName : $key;
        array2query($element, $sql, $key);
    }
    

    Надеюсь, это поможет,я не могу проверить это сейчас.

  2. из информации, сброшенной из вашего echo, кажется, что в генерируемом массиве отсутствует информация (выводится из эхо-строки кода: INSERT INTO Contacts (ExportId) VALUES ();).

    Кроме того, я считаю, что вам не хватает апострофов вокруг строковых значений, вставляемых в вашу инструкцию sql, например, эта строка кода:

    INSERT INTO Vendors (ShortName) VALUES (Fabspec);
    

    должна быть эта строка кода:

    INSERT INTO Vendors (ShortName) VALUES ('Fabspec');
    

    ПРЕДЛАГАЕМОЕ РЕШЕНИЕ:

    Так как у меня нет возможности изменить формат информации в файле 'c:\wamp64\www\json\test.json', я могу только сделать обходной путь, чтобы код работал в случаях, когда нет данных, доступных в элементе массива.

    Сначала я решил бы проблему apostophe, заменив эту строку кода:

    $sql .= 'INSERT INTO ' . $tableName . ' (' . rtrim($key, ',') . ') VALUES (' . rtrim($element, ',') . ');';
    

    с этим кодом:

    $column = rtrim($key, ',');
    $value_inserted = rtrim($element, ',');
    $ap = ""
    switch ($column)
    {
        case ('Name')
            $ap = "'";
        break;
        case ('ShortName')
            $ap = "'";
        break;
        //create a case for all the situations where 
        //the specific column stores string values
    
        default:
        {
            if ($value_inserted == "")
            {
               $value_inserted = 0;
            }
        }
    }
    
    $sql .= 'INSERT INTO ' . $tableName . ' ($column) VALUES ('$ap.$value_inserted.$ap');';
    

    Предыдущий код вставит Апостроф с обоих концов вставленного значения в инструкцию sql, если для рассматриваемого столбца требуется строка.

    Часть switch по умолчанию выполняется только тогда, когда строка не является типом данных рассматриваемого столбца, поэтому я воспользовался этой частью кода, чтобы проверить, было ли значение внутри $inserted_valueпусто (что должно быть причиной вашей ошибки). В этих случаях я поставил ноль, однако вы можете разместить любое значение, которое вы связываете.

    Дайте мне знать, если это сработает для вас.

  3. @Mad Dog прав, в этом ваша проблема (по крайней мере, рекурсивная).

    Этот блок кода отлично работает, используя небольшую часть вашего массива данных:

    $sql="";
    function array2query(array $array1, $tableName = '', &$sql){
       //$sql="";  // not declaring variable results in NOTICE; declaring results in $sql being reset to "" during foreach loop
       foreach ($array1 as $key => $element) {
            if (is_array($element)) {
            // if key is integer then skip - it is the first level of array, keep the $tablename    
                $key = is_int($key) ? $tableName : $key;
                array2query($element, $key, $sql);
            } else {
                if ($tableName === '') {
                $tableName = 'project';
                }
            $sql .= 'INSERT INTO ' . $tableName . ' (' . rtrim($key, ',') . ') VALUES (' . rtrim($element, ',') . ');' . "\r\n";
            } 
       }    
       //echo $sql;  //dump to screen; missing non-nested values from tablename 'project' 
       return $sql;
    }
    $rez = $array_query=array2query($array1, '', $sql);
    echo '<pre>';
    print_r($rez);
    echo '</pre>';
    

    Затем вам также нужно указать свои значения SQL, как уже указывалось @Webeng.