2

I am getting Warning: array_push() expects parameter 1 to be array, string given in ... for array_push() on this piece of code. The warning occurs in the first push, how do I fix this?

$url = $_SERVER['QUERY_STRING'];

$chunk = explode("&",$url);
array_pop($chunk);

foreach($chunk as $key => $value)
{
    $pieces = explode("=",$value);
    if($pieces)
    {
        $val = $pieces[0];
        if(isset($$val))
        {
            array_push($$val,$pieces[1]);
        }else{
            $$val = array();
            array_push($$val,$pieces[1]);
        }
    }
}

Note: I am not using $_GET because my querystring can contain multiple parameters with the same name like this

?q=1&q=2&q=3&q=4
RiggsFolly
  • 93,638
  • 21
  • 103
  • 149

5 Answers5

1

You don't need to explode and push/pop the query string. Just use the $_GET superglobal.

http://php.net/manual/en/reserved.variables.get.php

Edit: $_GET is an array, you can loop over it in the same way as any other array. If you need to get all of them separately then you can do this:

foreach ($_GET as $key => $value) {
    // whatever
}

Edit2: OK, I still think that whatever you are doing with those params is the wrong way to do it but if you need a function then you can try something like this:

function extractVars($url)
{
    $query = explode('?', $url);

    $extract = array();

    if (!isset($query[1])) {
        return $extract;
    }

    $params = explode('&', $query[1]);
    foreach($params as $param) {
        if (strpos($param, '=') !== false) {
            list($key, $value) = explode('=', $param);
            $extract[$key][] = $value;
        }
    }

    return $extract;
}

$string = 'url?a=1&a=2&a=3&b=1&b=2&b=3';
print_r(extractVars($string));

Which gives an output like this:

Array
(
  [a] => Array
  (
    [0] => 1
    [1] => 2
    [2] => 3
  )

  [b] => Array
  (
    [0] => 1
    [1] => 2
    [2] => 3
  )
)
rich97
  • 2,809
  • 2
  • 28
  • 34
  • That would require me to re-write the whole code and GET each variable one by one, which is fine if you have 1 or 2 variables but not if you have a lot of them. The code is working fine I just get this warning and would like to find out how to get rid of it. – Bruno Domingues Sep 04 '14 at 09:09
  • $$val can be or not an array. The same querystring parameter can be repeated more than once like &q=123&q=456&q=789 – Bruno Domingues Sep 04 '14 at 09:25
  • @BrunoDomingues Your code isn't working fine, though. It's throwing a warning. Code that works doesn't throw warnings. It's also counter-intuitive, most PHP programmers will be expecting you to use $_GET to get at the query string parameters. Any code that doesn't do that will have a higher "WTF/Minute" ratio than it should. http://www.osnews.com/story/19266/WTFs_m – GordonM Sep 04 '14 at 09:27
  • Yes I meant it isn't causing any fatal error, the list of items displays anyway and looks OK, might have something missing somewhere due to this warning. I only saw this when I turned the warnings on, have had this code working for a year and never knew there was anything wrong. :) – Bruno Domingues Sep 04 '14 at 09:29
  • The code is not working fine. You are extracting the data you need in the most inefficient and unmaintainable way possible. See my edit. – rich97 Sep 04 '14 at 09:33
  • It wasn't done by me, had a freelancer do it about a year ago, I am a .Net coder, don't know a lot about PHP, still learning. Sadly most freelancers don't seem to know how to code properly so now I have to fix their mistakes. Extremely hard to find a decent coder. – Bruno Domingues Sep 04 '14 at 09:47
  • Please dont paint all freelancers with the same brush. Also they have a lot to put up with i.e. permies with bad attitude, who dont know how to specify/develop/design/manage. – RiggsFolly Sep 04 '14 at 09:52
  • See my edit. I can modify it to fit the return values to something closer to what you are expecting if need be. – rich97 Sep 04 '14 at 09:55
  • I said most, not all. :) in this case I actually had the code properly done in .Net and all this guy had to do was make a PHP version of it on a server that supports both .Net and PHP. I have no idea why he chose to use this method of getting querystring variables, I did not do it in this way on my .Net code. – Bruno Domingues Sep 04 '14 at 09:55
  • Minor edit: Added strict check to strpos to prevent 0 from evaluating to false. – rich97 Sep 04 '14 at 09:58
1

This piece of code will only work if $$val is already an array. If it is not it will generate that error.

array_push($$val,$pieces[1]);

So try this :-

foreach($chunk as $key => $value)
{
    $pieces = explode("=",$value);
    if($pieces)
    {
        $val = $pieces[0];
        if( isset($$val) && is_array($$val) ) {
            array_push($$val,$pieces[1]);
        } else {
            $$val = array();
            array_push($$val,$pieces[1]);
        }
    }
}

Of course it would be easier to use the $_GET array which PHP prepares automatically for you

Additional thought after your comment

Could the reason for this warning be that you are using an old version of PHP and have the parameter register_globals = on.

So assuming a url of www.xx.com?q=1&q=2&q=3

This would mean that PHP had already created a $q variable for you. So the first pass through your code would find all the variables in the query string already exists as strings i.e. PHP will have already created the variables like this invisibly to you.

$q = '1';
$q = '2';
$q = '3';

So the first time your code attempts the array_push($$val,$pieces[1]); $$val which equates to $q but $q is already a scalar string variable, hence your error message.

You can check if this is the case by adding

print_r($GLOBALS);

just before the section of your script you posted. Then check the url against variables that already exist.

Another thought

The only way to explain this warning is that one or more of the variables you are trying to create in this code snippet already exists, for whatever reason.

Its quite possible that this code worked originally without the warning, but since then the code was amended and someone created one or more or there variables for some temporary purpose earlier on in the code.

As your querystring parameters equate to variables like

cid, val, np, wgt, w, l, h

Its quite possible someone used $w or $l or $h especially for some temporary purpose within a loop to hold a value. Its common practice to use single letter variables names to denote that the variable is only used within the few lines that you can see on a screen. But uncommon for people to destroy them once they are no longer required.

Anyway its worth having a look to see if one or more of these variable have been created prior to your code snippet.

Add a

print_r($GLOBALS) 

just before your code snippet and see if any of these variables already exist.

RiggsFolly
  • 93,638
  • 21
  • 103
  • 149
  • $$val can be or not an array. The same querystring parameter can be repeated more than once like &q=123&q=456&q=789 – Bruno Domingues Sep 04 '14 at 09:17
  • Well that explains why you are not using the $_GET array. – RiggsFolly Sep 04 '14 at 09:23
  • See my additional though based on your comment – RiggsFolly Sep 04 '14 at 09:35
  • PHP version is 5.5.11, auto_globals_jit = On – Bruno Domingues Sep 04 '14 at 09:40
  • That would not cause this problem I dont think. try adding the `print_r($GLOBALS) to see if these variables actually exist just before you execute your code. – RiggsFolly Sep 04 '14 at 09:45
  • [_GET] => Array ( [cid] => BE [val] => 0 [np] => 1 [wgt] => 1 [w] => 20 [l] => 20 [h] => 20 [1409824209759] => ) – Bruno Domingues Sep 04 '14 at 09:51
  • No you need to look at $GLOBALS, $_GET will not reflect the actual paramters you pass on the url as it will only have the LAST value of any parameter that you repeat more than once. Also it is not relevant as you are creating these new variables in GLOBAL memory and not the $_GET array – RiggsFolly Sep 04 '14 at 09:54
  • Yes, I did print globals and just copy paste the part that seemed relevant. There is also this: [REQUEST_URI] => /getQuote.php?cid=BE&val=0&np=1&wgt=1&w=20&l=20&h=20&1409824209759 as far as I can see there are no variables in the global, just session info querystring info and so on. – Bruno Domingues Sep 04 '14 at 09:58
0

Given that the url is something like www....php?a=b&c=d&e=f, you explode it so several elements a=b, c=d, e=f. You drop the a&b, and continue with c=d and e=f. You then pickup the c=d, explode it into the values c and d. Therfore unlikely that c is an array, which is proven by the error message.

Try to look at the content by adding print_r($val) and print_r($$val). It should give you an overview of what is actually evaluated, and work from there. I think you will find out that the variable variable doesn't work as expected either.

cootje
  • 449
  • 1
  • 5
  • 11
  • The URL is not like that, it can be a=b&a=c&a=d&b=1&b=2&b=3 – Bruno Domingues Sep 04 '14 at 09:20
  • Given the code it still doesn't give you an array for $$a by default. You need to define it first, or maybe as an alternatiev a contruction like $$a[] = $b works, however I can't test it at the location i'm at now. – cootje Sep 04 '14 at 10:10
0

OK guys I sorted it out by following your advice of getting rid of the loop code and replacing it with proper code.

It is now working perfectly and it was a simple solution.

$h   = $_GET["h"];
$w   = $_GET["w"];
$l   = $_GET["l"];
$wgt = $_GET["wgt"];
$np  = $_GET["np"];
$cid = $_GET["cid"];

if (!is_array($h))   $h   = [$h];
if (!is_array($w))   $w   = [$w];
if (!is_array($l))   $l   = [$l];
if (!is_array($wgt)) $wgt = [$wgt];

The first part gets the parameters into variables, one by one, the second part converts them into an array when it is a string.

Thanks for your help and advice. :)

-4

Just remove the one dollar($) in the $$val.

  • You too missed the purpose of the `$$` completely. [The manual](http://php.net/manual/en/language.variables.php) – RiggsFolly Sep 04 '14 at 09:06
  • http://php.net/manual/en/language.variables.variable.php You almost never want to use them because they are very confusing but they are a legitimate part of the language. – rich97 Sep 04 '14 at 10:01