2014-02-17 6 views
1

Я использую Laravel и пытаюсь написать команду artisan, которая принимает аргумент $ content, который затем должен быть перенесен в массив. Например:PHP: преобразование строки в вложенный массив

// An example of a value that is being passed in from the CLI and stored as $content 
    $content = "['div']['div'][0]['h2']['a']"; 

Для уточнения, $content затем передается в качестве аргумента функции, где он будет использоваться, чтобы вытащить значения из фактического результирующего набора. Другими словами, я получаю ответ от API, а $content - это путь к значениям, которые мне нужно вытащить из ответа. Например, жёстко вариант реализации выглядит следующим образом:

$result = $report['div']['div'][0]['h2']['a']; 

Теперь $result содержит значения, которые мне нужно обработать. Тем не менее, я пытаюсь сделать эту динамику, поэтому я не повторяюсь каждый раз, когда добавляю новый источник данных для проверки отчетов. В настоящее время у меня есть 4 функции, каждая из которых имеет жестко закодированные пути к желаемому результату; цель состоит в том, чтобы сделать это так, чтобы я мог передать аргумент, который содержит путь к желаемым значениям и рефакторинг моего кода, поэтому у меня есть только одна функция, которая принимает путь к значениям в качестве аргумента.

Надеюсь, что это прояснит конечную цель и почему я только ссылаюсь на ключи, а не на ценность.

В любом случае, вернемся к проблеме. Я пытался различные варианты следующие:

// Attempting to parse the string into an array 
    $arr = explode("]", trim(str_replace("[","",$content), "]")); 

Это приводит к следующему массива:

array (size=5) 
     0 => string ''div'' (length=5) 
     1 => string ''div'' (length=5) 
     2 => string '0' (length=1) 
     3 => string ''h2'' (length=4) 
     4 => string ''a'' (length=3) 

Но, что мне нужно для массива должен быть отформатирован, как следующее:

$array = ['div']['div'][0]['h2']['a'] 

Я попытался сделать foreach($array as $element) над $arr и сделать array_push для каждого элемента, но это привело к тому же выводу, что и $arr.

Как я могу перебирать строку и анализировать ее в массив? Кроме того, мне нужно 0, чтобы оставаться в качестве индекса, а не быть литым как строка. И, последнее замечание, значение $content будет совершенно различным каждый раз, поэтому мне нужно, чтобы он был достаточно гибким. Единственная часть, которая останется постоянной, - это [, а ] всегда будет инкапсулировать ключи.

Мне бы хотелось услышать, как другие решат эту кажущуюся тривиальную проблему (я отработал несколько лет от программирования и, по-видимому, забыл больше, чем я хотел бы признать;)). Я честно думал, что str_replace и explode собираются предоставить мне результат, который я ожидал ...

Но после повторного чтения документа php.net/explode он всегда будет отображать каждый элемент в виде строки (таким образом, переопределяя мой индекс 0), и я не знаю, как превратить его в вложенный массив, а не простой, плоский массив.

С нетерпением жду ваших советов и прозрения. Благодарю.

EDIT:

В том числе функции, которая делает использование аргументов, чтобы помочь обеспечить некоторую большую ясность.

private function yql_check_website($url, $xpath, $content) { 

    require_once('../vendor/OAuth.php'); 

    $statement = "select * from html where url='{$url}' and xpath='{$xpath}' "; 

    $cc_key = $this->key; 
    $cc_secret = $this->secret; 
    $url = "http://query.yahooapis.com/v1/public/yql"; 
    $args = array(); 
    $args["q"] = $statement; 
    $args["format"] = "json"; 

    $consumer = new OAuthConsumer($cc_key, $cc_secret); 
    $request = OAuthRequest::from_consumer_and_token($consumer, NULL,"GET", $url, $args); 
    $request->sign_request(new OAuthSignatureMethod_HMAC_SHA1(), $consumer, NULL); 
    $url = sprintf("%s?%s", $url, OAuthUtil::build_http_query($args)); 
    $url .= "&env=store://datatables.org/alltableswithkeys"; 
    $ch = curl_init(); 
    $headers = array($request->to_header()); 
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 
    curl_setopt($ch, CURLOPT_URL, $url); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); 
    $rsp = curl_exec($ch); 
    $report = json_decode($rsp, true); 

    // Dynamically inspect the $report object for the xpath content 
    $result = $report . $content; 

    unset($report); 

    return $result; 
} 

Итак, $ отчет содержит полный ответ API, но единственное, что мне нужно, это содержание, которое содержится в $report['div']['div'][0]['h2']['a'] (для этого примера, по крайней мере, путь различен для каждого отчета, что я соскоб). Таким образом, причина, по которой я пытаюсь преобразовать аргумент командной строки в массив, заключается в том, что он может использоваться в приведенном выше коде, где вызывается $content, чтобы перемещаться по ответу API и возвращать значения из этого сегмента.

Надеюсь, это имеет смысл. И, если есть лучший способ достичь этой конечной цели, не стесняйтесь говорить об этом. Я могу принимать неправильный подход ...

+1

'$ массив = [ 'DIV'] [ 'DIV'] [0] [ 'h2 '] [' a '] 'не имеет смысла. У вас есть куча ключей, но нет значения. – meagar

+0

Вы хотите, чтобы ваш массив $ был следующим: '$ array [0] = ['div'], $ array [1] = ['div'], $ array [2] = ['0'] ... '? –

+0

@meager, я обновил вопрос, чтобы уточнить, почему я только ссылаюсь на ключи. – DroBuddy

ответ

1

Laravel имеет несколько методов доступа к массиву, которые обеспечивают «точку» доступ к массивам, в том числе array_get. Метод прототип выглядит следующим образом:

function array_get(array $array, string $key, mixed $default = null) 

Таким образом, в вашем случае, вы могли бы написать:

$results = array_get($report, "div.div.0.h2.a"); 
+0

Это намного чище и работает как шарм. Большое вам спасибо! – DroBuddy

0

Вы могли бы просто использовать preg_match_all здесь ..

$content = "['div']['div'][0]['h2']['a']"; 
$expression = /\['([a-zA-Z0-9]+)\']/; 
$results = preg_match_all($expression, $content, $matches); 
print_r($matches); 

Если вы должны иметь массив подобно тому, что вы говорите, вы могли бы сделать что-то вроде этого (для начала - это немного некрасиво, хотя, как это ...)

// array(['div']['div'][0]['h2']['a'] 
// visualizing... 
// array('div' => array ('div' => 'array("0" => array("h2" => array("a"))))); 

function createDepth($source, $currentKey, $nextDepth = null) { 
    if(!is_array($nextDepth)) { 
    $source[] = array($currentKey => $nextDepth); 
    } else { 
    $nextKey = array_shift($nextDepth); 
    $source[] = createDepth(array($currentKey => array()), $nextKey, $nextDepth); 
    } 
    return source; 
} 
// Edit: doh, unset the first key.. 
unset($matches[0]); 

// Continue from here. 
$currentKey = array_shift($matches); 
$holder = array(); 
$final = createDepth($holder, $currentKey, $matches); 
print_r($final); 

Примечание: Все вышесказанное не тестировался ...

+0

Я сделаю снимок и дам вам знать, как это работает. Спасибо, Джонатан. – DroBuddy

+0

Ну, это закончилось тем, что возвращалось 'Array ([0] => Array ([0] => ['div'] [1] => ['div'] [2] => ['a']) [1 ] => Массив ([0] => div [1] => div [2] => a)) ', но я думаю, что вы здесь. Я поиграю с 'preg_match_all' и посмотрю, смогу ли я получить выраженное выражение, чтобы обеспечить результат, который я ищу. Спасибо, что указал мне в твердом направлении. Если я смогу заставить его работать, я с удовольствием приму это в качестве ответа. – DroBuddy

+0

круто. не забудьте проверить мой отредактированный ответ ... создал рекурсивную функцию для его создания. Это непроверено, хотя (я построил его в редакторе и на самом деле не кодировал PHP чуть больше года). –

0

является ли это то, что вы хотите?

$str = "['div']['div'][0]['h2']['a']"; 
$str = preg_split('/]\[/', substr(str_replace("'", "", $str), 1, -1)); 
print_r($str); 

Array (
    [0] => div 
    [1] => div 
    [2] => 0 
    [3] => h2 
    [4] => a 
) 
+0

Это довольно близко, но мне нужно, чтобы это было многомерным, так что это похоже на массив ('div' => array ('div' => 'array ("0" => array ("h2" => array ("a «))). Но это дает мне хорошее представление о том, как идти по вещам. – DroBuddy

Смежные вопросы