views:

85

answers:

4

In my database, some field settings are serialized and stored. When I do this:

print_r(unserialized($r['settings']));

I'll get this:

Array ( 
[prefix] => 
[suffix] => 
[min] => 
[max] => 
[allowed_values] => 1|Common 2|Rare 3|Almost Extinct 
)

I'm trying to create an array based on the values for allowed_values like this:

Array (
[1] => Common
[2] => Rare
[3] => Almost Extinct
)

The problem is, when I use explode("|", $r['allowed_values']), I get:

Array(
[0] => 1
[1] => Common 2
[2] => Rare 3
[3] => Almost Extinct
)

Which, makes sense, but obviously not what I was hoping for... So, I'm just wondering if there's a simple way to do what I'm trying here? I thought about using explode multiple times, once for spaces, and once for pipes, but that won't work either because of the space in "Almost Extinct"...

A: 

I think this should work. This splits the first number and the "|" char

<?php
$string = "1|Faruk 2|Test";
$array = preg_split('/\d/', $string, -1, PREG_SPLIT_NO_EMPTY); 
$content = explode("|", implode($array));

var_dump($content);
?>

And here is the Result

array(3) {
  [0]=>
  string(0) ""
  [1]=>
  string(6) "Faruk "
  [2]=>
  string(4) "Test"
}
streetparade
+3  A: 

try this:

 $tab=array();
 preg_match_all("/\s*(\d+)\|([^\d]+)/",$r['allowed_values'],$tab);
 print_r(array_combine($tab[1],$tab[2]));

this should make the trick :)

dweeves
Except `(\w+)` will not match 'Almost Extinct'. Replace that with `([^\d]+)` which should do the trick assuming the "values" will never have numbers in them. With the fixed regex, this answer is the best solution I think because it does not assume that the numbers will be sorted lowest to highest and blindly push each value onto the end of an array
MooGoo
edited the response to take comment into account
dweeves
I like this method.
Mike
+2  A: 

If the original indexes are not sequential from 1, and you need to keep them as they are, see dweeves answer, as that keeps the indexes and values bound together correctly.

$string = unserialized($r['settings']['allowed_values']);
//$string = '1|Common 2|Rare 3|Almost Extinct';

print_r (preg_split("/\d+\|/", $string, -1, PREG_SPLIT_NO_EMPTY));

Outputs:

Array
(
    [0] => Common 
    [1] => Rare 
    [2] => Almost Extinct
)
Mike
It looks different than the array from the question (different keys).
tomp
I'd just used the output from `unserialized($r['settings']['allowed_values'])` as the content of `$string`. I've clarified this now.
Mike
A: 

I would use a regex to match the pattern of each entry, but capture only the text of interest. Using preg_match_all(...), the $match object is populated with sub-arrays of the capture groups.

$input = '1|Common 2|Rare 3|Almost Extinct';
preg_match_all('/\d+\|([^\d]+)/',$input, $match);
print_r($match[1]);

Produces:

Array
(
    [0] => Common 
    [1] => Rare 
    [2] => Almost Extinct    
)

Note that if you're labels will use numbers, you'll need to tweak the regex.

This method also allows you to capture the number and create your own ordered array, if the values stored in your tables might be out of order.

Chadwick