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.

\$\endgroup\$
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!

\$\endgroup\$
  • \$\begingroup\$ this have to be one parameter in url like /arena?filter=id:1||content_name:alex&anotherParam=smth \$\endgroup\$ – Alex Kneller Aug 26 '15 at 9:28
  • \$\begingroup\$ Yep get to this 5 min ago but thanks \$\endgroup\$ – Alex Kneller Aug 26 '15 at 9:50
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);
\$\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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.