После большого тестирования, вот мой ответ - я надеюсь, что кто-то еще найдет это полезным (я использую структуру Yii2).
Класс преобразует массив так:
Array
(
[per_page] => 100
[total] => 69
[data] => Array
(
[0] => Array
(
[total_time] => 374
[href] => https://api.surveymonkey.net/v3/surveys/######
[custom_variables] => Array
(
[ref] => 38i7zw
)
[ip_address] => 198.x.x.x
[id] => 4917
[logic_path] => Array
(
)
[date_modified] => 2016-08-18T10:04:26+00:00
[response_status] => completed
[custom_value] =>
[pages] => Array
(
[0] => Array
(
[id] => 249
[questions] => Array
(
)
В то вроде этого:
Array
(
[0] => Array
(
[answer_id] => 10375872133
[question_id] => 985997023
[question_text] => Who was the contact?
)
[1] => Array
(
[answer_id] => 10375872147
[question_id] => 985997023
[question_text] => Which group did you use?
)
Красота этого решения заключается в том, что это не имеет значения, насколько глубоко массив или если столбцы не существуют во всех вложенных массивах - класс будет последовательно возвращать данные в том же формате.
Вот как его использовать:
1) экземпляр класса и передать массив к нему:
$obj = new ArrayToolkit($array)
2) Вывести список элементов, которые существуют в массиве. Элементы возвращаются в формате «разделенные точкой» и действуют как система индексирования.
$list = $obj->getListOfKeys();
echo "<pre>" . print_r($list, 1) . "</pre>";
список будет выглядеть примерно так (номер по праву является число появлений этого элемента в массиве вы прошли к классу):
Array
(
[data.total_time] => 69
[data.href] => 69
[data.custom_variables.ref] => 69
[data.ip_address] => 69
[data.id] => 69
[data.date_modified] => 69
[data.response_status] => 69
[data.custom_value] => 69
[data.analyze_url] => 69
[data.pages.id] => 1311
2) определить и переименовать элементы, которые вы хотите вернулись:
$obj->keysToFind([
'answer_id'=>'data.pages.questions.answers.choice_id',
'question_id'=>'data.pages.questions.id',
'question_text' => 'placeholder'
]);
В приведенном выше примере, класс будет возвращать три элемента: answer_id, question_id, question_text
пара интересных моментов об этой функции:
- Это будет переименовывать элемент в нечто более подходящее для вас
- Вы можете вставить заполнители, даже если вы знаете, что данные не существуют в массиве
- Вы можете выбрать, какие элементы вы хотите вернуть, он будет не возвращать все элементы, если они вам не нужны.
- Выход соответствует, даже если один суб-массив не все элементы
4) Получить данные обратно:
$arr = $obj->target([
'answer_id'=>'data.pages.questions.answers.choice_id',
]);
«целевой» Важно: Это ключ/ценность пара вы больше всего заботитесь. Функция ищет массив, чтобы найти этот ключ. Как только он найдет ключ, он возвращает значение, а затем все остальные запрошенные вами данные (т. Е. Нужные вам родительские элементы).
Примечание. Он не возвращает дочерние элементы, только родительские элементы, но если у вас есть дочерний элемент в «ключах для поиска», он будет равен нулю. По этой причине цель должна быть самым глубоким дочерним элементом, но не обязательно. Вы можете задаться вопросом, почему я бы его проектировал так, но я сделал это, потому что функция позволяет вам добавить другую цель.
Например, если вы сейчас гласил:
$arr = $obj->target([
'question_id'=>'data.pages.questions.id',
]);
Результаты будут добавлены к существующей продукции. Это очень важно для плохо сконструированных массивов (как в случае с массивом, с которым я работаю).
В конце концов, вы получаете хороший чистый массив для пакетных вставок!
Надеюсь, это поможет. Вот код
PS: ссылка на Toolkit :: PrintObj() эквивалентно
echo "<pre>" . print_r($var, 1) . "</pre>";
<?php
namespace app\models;
use Yii;
use yii\helpers\ArrayHelper;
/**
* Class ArrayToolkit
* @package app\models
*/
class ArrayToolkit extends \yii
{
// This holds the data for this class
public $model = array();
/**
* model constructor.
* @param $array
*/
function __construct($array)
{
$this->getArrayIndex($array);
}
/**
* @return array
*/
public function getListOfKeys()
{
//Toolkit::printObject($this->model['list_of_keys']);
return $this->model['list_of_keys'];
}
/**
* @return mixed
*/
public function getIndex()
{
return $this->model['index'];
}
// This is the heart of the function. "KeysToFind" is the list of keys it will search for
// These keys will allways be in the same order and will exist even if a particular key is empty
// This is needed for batch inserts into mysql
public function keysToFind($arr)
{
$this->model['keys_to_find']['all'] = $arr;
foreach ($arr as $key => $value) {
$this->model['keys_to_find']['temp'][$key] = null;
}
}
// this function is the function which kicks off the search to populate the data
// this function is additive! ie new results are added to old results. To clear the cache,
// you need to clear $this->model['mysql_array']
public function target($target)
{
$this->model['keys_to_find']['target']['name'] = key($target);
$this->model['keys_to_find']['target']['key'] = array_values($target)[0];
$this->buildMysqlArray();
return $this->model['mysql_array'];
}
/**
* This function will create an array of elements suitable for mysql insert
* User simply loops over the array and inserts into table
*/
private function buildMysqlArray()
{
// name = the new name assigned by user
// key = string eg pages.questions.answers.id
// index is the indexing id eg [0.12] or [0.1.2.3]
// levelCount is the number of levels within the index
// For example [0] = 1 level, [0.0] = 2 levels, [0.0.0] = 3 levels
// Target is the value the user is looking for
// For example: The answer ID
$target_key = $this->model['keys_to_find']['target']['key'];
$target_name = $this->model['keys_to_find']['target']['name'];
$target_levelCount = $this->model['index'][$target_key]['index_levelCount'];
$target_array = $this->model['index'][$target_key]['members'];
// Other is all the other supporting values (typically foreign keys)
// For example: Survey ID, Question ID etc
$other = $this->model['keys_to_find']['all'];
// Toolkit::printObject($this->model);
// loop through the target array eg pages.questions.answers.id
foreach ($target_array as $target_index => $target_value) {
$temp = $this->model['keys_to_find']['temp']; // this ensures that all keys are present in the output
// for each answer, assign the value
$temp[$target_name] = $target_value;
// now loop through all the other keys the users wants
if ($other !== null) {
foreach ($other as $other_name => $other_key) {
if (isset($this->model['index'][$other_key]['members']) && $other_key != $target_key) {
// "members" is the array of answers or pages etc
$other_array = $this->model['index'][$other_key]['members'];
$other_levelCount = $this->model['index'][$other_key]['index_levelCount'];
// if the question_id is 1.2.3.4 then it has 4 levels.
// however a page might be on 1.2.3 (ie 3 levels)
// To find the page for our question, we simply shorten the question index to the same number of levels
// ie 1.2.3.4 becomes 1.2.3
// and now we can easily find the page by using the key: page['1.2.3']
if ($other_levelCount < $target_levelCount) {
$indexToFind = substr($target_index, 0, $this->strposX($target_index, ".", $other_levelCount));
} else {
$indexToFind = $target_index;
}
if (isset($other_array[$indexToFind])) {
$temp[$other_name] = $other_array[$indexToFind];
}
}
}
}
$this->model['mysql_array'][] = $temp;
$temp = null;
}
}
/**
* @param $array
* @param string $prefix
* @param bool $recursive
* @return array
*/
private function getArrayIndex($array, $prefix = '', $recursive = false)
{
$result = array();
foreach ($array as $key => $value) {
if (is_array($value)) { // $value is another array - we will need to do a recursive loop
if (is_int($key)) { // incremental key eg [0] or [1] etc
// The format is as follows:
// pages[0]['questions'][1]['id'][2] becomes...
// 0.1.2-pages.questions.id
// With each loop of this function, I explode the string on "-" and then add the new index
// 0.1.2- becomes 0.1.2.3-
if (strpos($prefix, "-")) {
$arr = explode("-", $prefix);
$result = $result + $this->getArrayIndex($value, $arr[0] . "." . $key . '-' . $arr[1], true);
} else {
$result = $result + $this->getArrayIndex($value, $key . '-' . $prefix, true);
}
} else {// key is not an integer. It is a string eg "questions". Append it to the $prefix
$result = $result + $this->getArrayIndex($value, $prefix . $key . '.', true);
}
} else { // $value is not an array, it is the actual value
if (strpos($prefix, "-")) {
$temp = explode("-", $prefix);
$this->model['index'][$temp[1] . $key]['index_levelCount'] = substr_count($temp[0], ".") + 1;
$this->model['index'][$temp[1] . $key]['members'][$temp[0]] = $value;
}
$result[$prefix . $key] = $value;
}
}
// CLEANUP:
// We don't want to process every recursive loop, only the final array being returned.
if ($recursive === false) { // This is the final return
$list_of_keys = array();
foreach ($result as $str => $val) {
if (strpos($str, "-")) {
$temp = explode("-", $str);
if (isset($list_of_keys[$temp[1]])) {
$list_of_keys[$temp[1]] = $list_of_keys[$temp[1]] + 1;
} else {
$list_of_keys[$temp[1]] = 1;
}
}
}
$this->model['list_of_keys'] = $list_of_keys;
}
return $result;
}
/**
* @param $haystack
* @param $needle
* @param $number
* @return bool|int
* This function will get the n'th occurrence of the needle
*/
private function strposX($haystack, $needle, $number)
{
if ($number == '1') {
return strpos($haystack, $needle);
} elseif ($number > '1') {
return strpos($haystack, $needle, $this->strposX($haystack, $needle, $number - 1) + strlen($needle));
} else {
$this->model['ERR'][] = ['strposX' => 'Value for parameter $number is out of range'];
return false;
}
}
}
Попробуйте что-то вроде этого Еогеасп ($ массив как $ ключ => $ значение) {если ( is_array ($ value)) { foreach ($ value as $ key => $ value) { echo $ key. "". $ value. "
"; } } echo "
"; } и добавьте вставку sql внутри – Oncodeeater
Я хочу, чтобы решение было настолько простым. См. Ниже класс, который я должен был создать. – DrBorrow