5
\$\begingroup\$

I'm tying to convert from this formatted string:

$filtersStr = "id:1||name:alex";

to:

['id' => 1,'name' => 'alex']

My solution for now:

foreach(explode('||', $filtersStr) as $filter){
 list($k, $v) = explode(':', $filter);
 $filters[ $k ] = $v;
 }

I'm looking for a more elegant way.

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Aug 26, 2015 at 7:34
\$\endgroup\$
0

3 Answers 3

3
\$\begingroup\$

You can use the amazing parse_str() function. It does everything you need. But you are using different delimiters for key => value pairs. If you change those to & and =, you can do like this:

$filtersStr = 'id=1&name=alex';
parse_str($filtersStr, $filters);

And $filters will have what you want. But that's not the case, so, one could do this:

parse_str(
 str_replace(
 array('%', '=', '&', '||', ':'),
 array('%26', '%3D', '%26', '&', '='),
 $filtersStr
 ),
 $filters
);

The characters %, = and & will have a special meaning. They have to be replaced with their URL-codes. parse_str() works on URL-encoded strings and leaving those characters unchanged would cause all sorts of bugs. The order of the elements in the array is VERY important.

Here's how it works:

  • Replace % by %26
    It must be the first of you will be replacing % everywhere and break it
  • Replace = by %3D
    This guarantees that no meaningful = will be replaced
  • Replace & by %26
  • Replace || by &
  • Replace : by =
    At this point, your 'id:1||name:alex' will be 'id=1&name=alex'
  • Hand it over to parse_str()

And done! I prefer the first method instead of this kludge. Use this second one with extreme care!


In a comment, it was explained that it's usage was like this:

/arena?filter=id:1||content_name:alex&anotherParam=smth

If you can change the URL, throw this whole code away and do like this:

/arena?filter[id]=1&filter[content_name]=alex&anotherParam=smth

This will have the exact structure you wish. Simply use $_GET['filter'] to access all values. And done! An alternative with 0 lines of code!

answered Aug 26, 2015 at 9:20
\$\endgroup\$
1
  • \$\begingroup\$ this have to be one parameter in url like /arena?filter=id:1||content_name:alex&anotherParam=smth \$\endgroup\$ Commented Aug 26, 2015 at 9:28
2
\$\begingroup\$

If you're writing the structure on string formatting, then I'd suggest considering JSON as a better alternative.

It's a better alternative than , because, its support is inbuilt into many languages, including PHP with the json_encode and json_decode functions.


Consider this:

$object = ['id' => 1,'name' => 'alex'];
$JSON = json_encode($object);
$DAL->do_whatever($JSON);

or:

$JSON = $DAL->retrieve_whatever();
$object = json_decode($JSON);
buildProfile($object);
answered Aug 26, 2015 at 9:49
\$\endgroup\$
0
\$\begingroup\$

Alternatives are good because we find the solution handy, which are well described by @Quill and @Ismael,

If you have decided to go with the current format of your string, here is the alternative i wrote,

foreach(explode('||', $filtersStr) as $val)
{
 $filters[strtok($val, ':')] = trim(strstr($val, ':'), ':');
} unset($val);

Here strtok($val, ':') will stop at first : it encounters, in our case it will be id and name, so no : will be in final array keys.

strtok($val, ':') will get the whole string after first : it encounters and trim will clear suffixed :s.

The benefit is that when it encounters values like,

$filtersStr = 'id:1||name:alex:mercer';

It outputs as is,

Array
(
 [id] => 1
 [name] => alex:mercer
)

Other results are same.

answered Sep 1, 2015 at 7:27
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.