Intereting Posts
Обнаружение неудачного входа в Cake PHP-форму просто обновляет Symfony Circular Reference Exception для Doctrine onFlush Event Listener Service При попытке загрузки фотографий с метаданными в папку Picasa для Multipart должна быть ошибка Atom и media part. Получить текущий URL-адрес в Magento и показать что-то Soap answert string – преобразование в атрибут Приложение Symfony2 с аутентификацией RESTful, используя FOSRestBundle и FOSUserBundle тест, если ввод формы – это целое число 1 или 2 цифры с jquery и php PHP разбивает массивы на группы на основе равных значений Есть ли разница в скорости между <? Php echo $ var; ?> и <? = $ var?>? PHP + MySQL: разница между буферизированными и небуферизованными запросами Модификация Rewrite и PHP Хранить его в сеансе или в базе данных запросов каждой загрузки страницы? Невозможно получить доступ к константе класса из экземпляра с помощью оператора :: scope Как поместить данные HTML в заголовок tcpdf?

Как динамически задавать ключи массива в php

У меня есть некоторая логика, которая используется для сортировки данных, но в зависимости от пользовательского ввода данные группируются по-разному. Прямо сейчас у меня есть пять различных функций, которые содержат одну и ту же логику, но разные группы. Есть ли способ объединить эти функции и динамически установить значение, которое будет группироваться правильно. Внутри функции эти назначения происходят

Например, иногда я храню вычисления просто:

$calcs[$meter['UnitType']['name']] = ... 

но в других случаях требуется более конкретная группировка:

 $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] =... 

Как вы можете видеть, иногда он хранится в многомерном массиве, а иногда нет. Я пытаюсь использовать eval (), но безуспешно (не уверен, что это правильный подход). Хранение данных во временной переменной на самом деле мало экономит, потому что существует много вложенных циклов и операторов if, поэтому массив должен повторяться в нескольких местах.

РЕДАКТИРОВАТЬ

Надеюсь, следующий пример объясняет мою проблему лучше. Это, очевидно, тупиковая версия:

 if(){ $calcs[$meter['UnitType']['name']] = $data; } else { while () { $calcs[$meter['UnitType']['name']] = $data; } } 

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

 if(){ $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data; } else { while () { $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data; } } 

Есть ли способ абстрагировать ключи в массиве $ calc [], чтобы я мог иметь одну функцию вместо нескольких функций с разными ключами массива?

Не будет ли проще сделать следующее

 $calcs = array( $meter['Resource']['name'] => array( $meter['UnitType']['name'] => 'Some Value', $meter['UnitType']['name2'] => 'Some Value Again' ), ); 

или вы можете использовать объекты

 $calcs = new stdClass(); $calcs->{$meter['UnitType']['name']} = 'Some Value'; 

но я бы посоветовал вам построить вашу структуру в массивах, а затем сделать!

 $calcs = (object)$calcs_array; 

или вы можете зациклить свой первый массив на новый массив!

 $new = array(); $d = date('Y-m',$start); foreach($meter as $key => $value) { $new[$key]['name'][$d] = array(); } 

Дайте это назад и посмотрите, как выходит структура массива.

Попробуйте использовать корпус коммутатора.

 <?php $userinput = $calcs[$meter['UnitType']['name']] = $data;; switch ($userinput) { case "useriput1": while () { $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data; } break; case "userinput2": while () { $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data; } break; ... default: while () { $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data; } } ?> 

Я согласен с комментарием к OP by @Jake N, что, возможно, использование объектов – лучший подход. Тем не менее, если вы хотите использовать массивы, вы можете проверить наличие ключей в условном выражении, например:

 if( array_key_exists('Resource', $meter) ) { $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data; } else { $calcs[$meter['UnitType']['name']] = $data; } 

С другой стороны, если вы хотите использовать объекты, вы можете создать MeterReading объекта MeterReading , а затем добавить экземпляры MeterReading качестве элементов массива в ваш массив $calcs , например:

 // Object defintion class MeterReading { private $data; private $resource; private $startDate; private $unitType; public function __construct(Array $meter, $start, $data) { $this->unitType = $meter['UnitType']['name']; $this->resource = $meter['Resource']['name']; $this->startDate = date('Y-m',$start); } public function data() { return $this->data; } public function resource() { return $this->resource; } public function startDate() { return $this->startDate; } public function unitType() { return $this->unitType; } } // Example population $calcs[] = new MeterReading($meter, $start, $data); // Example usage foreach($calcs as $calc) { if($calc->resource()) { echo 'Resource: ' . $calc->resource() . '<br>'; } echo 'Unit Type: ' . $calc->unitType() . '<br>'; echo 'Start Date: ' . $calc->startDate() . '<br>'; echo 'Data: ' . $calc->data() . '<br>'; } 

Очевидно, вы можете принять это дальше, например, проверить наличие ключей массива в конструкторе объекта, предоставив resource свойства объекта значение по умолчанию, если оно не указано, и так далее, но это начало подхода OO.

Вы можете использовать это, если хотите получать и устанавливать значения массива динамически.

 function getVal($data,$chain){ $level = $data; for($i=0;$i<count($chain);$i++){ if(isset($level[$chain[$i]])) $level = $level[$chain[$i]]; else return null; // key does not exist, return null } return $level; } function setVal(&$data,$chain,$value){ $level = &$data; for($i=0;$i<count($chain);$i++){ $level = &$level[$chain[$i]]; // set reference (&) in order to change the value of the object } $level = $value; } 

Как это работает:

Вызов getVal($data,array('foo','bar','2017-08')) вернет эквивалент $data['foo']['bar']['2017-08'] .

Вызов setVal($data,array('foo','bar','2017-08'),'hello') установит значение так, как если бы вы назвали $data['foo']['bar']['2017-08'] = 'hello' . несуществующие ключи будут созданы автоматически с помощью php magic .

Это может быть полезно, если вы хотите динамически строить структуру массива.

Вот функция, которую я написал для установки глубоко вложенных элементов на массивы или объекты:

 function dict_set($var, $path, $val) { if(empty($var)) $var = is_array($var) ? array() : new stdClass(); $parts = explode('.', $path); $ptr =& $var; if(is_array($parts)) foreach($parts as $part) { if('[]' == $part) { if(is_array($ptr)) $ptr =& $ptr[]; } elseif(is_array($ptr)) { if(!isset($ptr[$part])) $ptr[$part] = array(); $ptr =& $ptr[$part]; } elseif(is_object($ptr)) { if(!isset($ptr->$part)) $ptr->$part = array(); $ptr =& $ptr->$part; } } $ptr = $val; return $var; } 

Используя данные примера:

 $array = []; $array = dict_set($array, 'resource1.unit1.2017-10', 'value1'); $array = dict_set($array, 'resource1.unit2.2017-11', 'value2'); $array = dict_set($array, 'resource2.unit1.2017-10', 'value3'); print_r($array); 

Результаты вывода:

 Array ( [resource1] => Array ( [unit1] => Array ( [2017-10] => value1 ) [unit2] => Array ( [2017-11] => value2 ) ) [resource2] => Array ( [unit1] => Array ( [2017-10] => value3 ) ) ) 

Второй аргумент dict_set() – это строка $path в точечной нотации . Вы можете построить это, используя динамические клавиши с разделителями периодов между частями. Функция работает с массивами и объектами.

Он также может добавлять инкрементные элементы к глубоко вложенному массиву, используя [] как элемент $path . Например: parent.child.child.[]