Errors when using array_push -- "First argument should be an array" - php

I have the following code:
<?php
function foo($bar)
{
global $products;
//$products = array();
$query = 'SELECT p_name FROM 0_products WHERE p_category IN (' . $bar . ')';
$results = mysql_query($query);
while($row = mysql_fetch_array($results, MYSQL_ASSOC))
{
array_push($products, $row);
echo 'name pushed, ';
}
}
require('mysql_ipb_connect.php'); // connect to ipb mysql database
$products = array();
foo(5);
?>
When I run it I get the following output:
Warning: array_push() [function.array-push]: First argument should be an array in /home/rgcpanel/public_html/category/category.php on line 14
name pushed,
Warning: array_push() [function.array-push]: First argument should be an array in /home/rgcpanel/public_html/category/category.php on line 14
name pushed,
Warning: array_push() [function.array-push]: First argument should be an array in /home/rgcpanel/public_html/category/category.php on line 14
name pushed,
If I uncomment "$products = array();" then the output is correct:
name pushed, name pushed, name pushed,
Why is this happening? I declare the $products array outside of a function (so it's global), and then specify it as being a global inside the function. Something is not right, but I'm not sure what that is?
Thanks for your advice.

Per the comments, $products was initialized by an included file which was included inside a function. That defines its scope to the function, rather than globally. So you'll need to use global $products; before calling the include.
function func_that_defined_products() {
global $products;
include('file_that_defines_products.php');
}
// Now when called globally later, it will be at the correct scope.
function foo($bar)
{
global $products;
$query = 'SELECT p_name FROM 0_products WHERE p_category IN (' . $bar . ')';
// etc...
}
In any case, I find it a little more readable to use $GLOBALS['products'] instead of the global keyword. And as always, wherever possible it is a preferred practice to pass the variable into a function rather than accessing it globally.
// If you can, do it this way
function foo($bar, $products) {
// $products was a param, and so global is unnecessary
}
However in your case, if the CMS defines it you may lose the flexibility to do it that way...

You haven't initialized the global variable as an array. To PHP, that variable is just null, which is NOT AN ARRAY.

Make sure you initialize variables before using them. Code like yours will result in side effects (working fine if there is a database result; failing if its empty).
Another point:
Why don't you return the result instead of using the global operator? This is really bad style.
Next one:
When creating SQL statements: escape your variables!

Uncomment this part
//$products = array();
Initialise the $products as an array

Related

PHP empty array deceleration throwing error

I am using the third party provided PHP binary for implementing chat server.
In that PHP binary, most of the PHP classes contain below code
$list = $list[0];
Just above the line $list=$list[0] there is one more line $db = Db::getInstance(); in my PHP class. I am not sure might be this getInstance code is trying to populate list array.
Whenever API is called the PHP classes its throwing below error
Undefined variable: list in /var/www/HeXXX/XXXX/city.php on line 53
I am new to PHP and not able to find the solution. Might be its duplicate question but I have already searched in StackOverflow and didn't get the similar post.
Full code :
public static function all() {
// $list = [0];
$db = Db::getInstance();
$list = $list[0];
$req = $db->query('SELECT * FROM users');
// we create a list of Post objects from the database results
foreach($req->fetchAll() as $user) {
$list[] = new User($user['userid'], $user['firstName'], $user['lastName'], $user['email'], $user['password'], $user['status'], $user['regTime'], $user['username'], $user['avata r'], $user['gender'], $user['dob'], $user['vCode'], $user['city_id'], $user['country'], $user['mobile'], $user['dating_status'], $user['interest_in'], $user['about_me'],$user['request_ limit']);
}
return $list;
}
The notice is telling you that something is accessing the $list variable before it has been set. This is caused by $list[0] having to be evaluated to give $list a value.
You (or the library author) probably wanted $list = array(); to initialize the $list variable to an empty array first.
Try replacing that line with:
if (!empty($list[0])){
$list = $list[0];
}

PHP scope issue within while loop

Trying to teach myself php and I am struggling with what I think is a scoping issue?
I have a query, while loop, if/else and a function.
I would like to echo the results of the function get_patronapi_data($id) within my while loop.
My code so far is as follows (stripped for legibility);
$stmt = $conn->prepare("SELECT... ..."); //QUERY here ...
if( $stmt->num_rows > 0 )
{
while ($stmt->fetch()) {
if (SomethingIsTrue){
echo get_patronapi_data($id);
}
else {
echo $somethingElse;
}
}//end while
}//end if
define("APISERVER", "http://mydomain:4500");
function get_patronapi_data($id) {
$apiurl = "APISERVER" . "/PATRONAPI/$id/dump";//line 135
$api_contents = get_api_contents($apiurl);
$api_array_lines = explode("\n", $api_contents);
foreach($api_array_lines as $line){
if(strpos($line, "EXP DATE") !== false){
$data = explode("=", $line);
return $data[1];
}//end if
}//end foreach
}//end function
function get_api_contents($apiurl) {
$api_contents = file_get_contents($apiurl);//line 154
$api_contents = trim(strip_tags($api_contents));
return $api_contents;
}//end function
echo get_patronapi_data($id); // this works and echoes $data on screen
Whenever I echo get_patronapi_data($id); outside of the functions I successfully see the data on screen. However when I echo get_patronapi_data($id); within the loop I receive the following errors;
Notice: Use of undefined constant APISERVER - assumed 'APISERVER' in
C:\xampp...search_1.php on line 135
Warning: file_get_contents(APISERVER/PATRONAPI/3047468/dump): failed
to open stream: No such file or directory in C:\xampp...search_1.php
on line 154
I'm sure I am doing something very silly however any help is appreciated.
Putting some of my comments to an answer.
You need to remove the quotes from:
$apiurl = "APISERVER" . "/PATRONAPI/$id/dump";
^ ^ <<< remove those
since that's treated as a string literal, rather than a constant.
It is declared in:
define("APISERVER", "http://mydomain:4500");
Reference:
http://php.net/manual/en/function.constant.php
Then your connection is out of scope and should be used inside your function(s).
I.e.:
function get_patronapi_data($conn, $id)
and do that for all your functions requiring a connection for them.
You will need to make sure that all folders/files have proper permissions to be written to.
The missing link is the statement:
$data = get_patronapi_data($id);
you should put before echo $data;.
It calls the function get_patronapi_data() passing the value of variable $id as argument and stores the values the function returns in the variable $data.
The variable $data you echo() is not the same as the one used by the function. They use the same name but they are different (I hope you don't use the keyword global in the function).
Read more about functions in the PHP documentation.
The updated (fragment of) code looks like:
if (SomethingIsTrue) {
$data = get_patronapi_data($id);
echo $data;
} else {
echo $somethingElse;
}
If you don't do further processing on the value returned by the function, you can, as well, remove the temporary variable $data from the code fragment above and just use:
if (SomethingIsTrue) {
echo get_patronapi_data($id);
} else {
echo $somethingElse;
}
Assuming you want to print the data from the get_patronapi_data() every iteration in the while loop, you need to actually call the method instead of using $data. Right now you're trying to print something called $data, though you never set a value to it. The $data you return in the function cannot be used outside of that function, so it does not exist in the while loop.
What you could do in your while loop is $data = get_patronapi_data();, and then echo $data. However, you can just echo get_patronapi_data(); first.
If you only want to call your function once, you need to set a variable before you start your while loop (i.e. $variable = get_patronapi_data()), and then use that variable in your while loop (i.e. echo $variable);
I'm not sure I fully understand your question. What happens if you just put
echo get_patronapi_data($id);
in the loop instead of
echo $data;
? As written, you're not calling the function in the loop.

Pass new variable as reference

I have a method in a class with this signature:
public static function execute($query, $data = array(), &$result = NULL, $onlyOne = true)
The point is to execute a SQL query with data (if relevant) and modify the result variable (if set to true) and finally returning only first row if the caller is interested in it only. It handles SQL errors etc. and overall is a convenience thing as I try to reduce the sql queries in the script to single line or two (checking the result).
Now I have a problem with this:
Db::execute("query with :data", array(":data" => "data"), ($row = true));
The PHP complains about the $row not being a variable:
Strict standards: Only variables should be passed by reference
As I understand the PHP scopes the scope is function-wide and not block-wide (as in C++ for example). Therefore the $row should be a variable in my function scope and available for passing as reference (and not just a temporary inside the function call). If I declare it beforehand it works but it inflates the code somewhat. Is there a way to keep the declaration of that variable in the function call like this?
EDIT: To add to the accepted answer. The reference can be assigned any default value so I changed my signature to:
public static function execute($query, $data = array(), &$result = -1, $onlyOne = true)
which allows me to call it using:
Db::execute("query with :data", array(":data" => "data"), $row);
without pre-declaring the result variable. Inside I simply check if the $result is not -1 (or I could check if it is NULL signifying new empty variable) to fill the result in.
Db::execute("query with :data", array(":data" => "data"), ($row = true));
^^^^^^^^^^^^^
That's an assignment. In PHP, the result of an assignment is the value being assigned, so you're passing true in to your function. That argument is defined as a reference, and you can't create a reference to true.
You'd have to do:
$row = true;
DB::execute(....., $row);

PHP. Pass variable by reference vs string. How to works with these two different arguments?

I'm writing my own debug functions and I need some help to fix the code below.
I'm trying to print a variable and its name, the file where the variable and the function was declared and the line of the function call. The first part I did, the variable, the variable name, the file and the line is printed correctly.
At the code, a($variable) works good.
The problem is I'd like this function accepts a string too, out of a variable. But PHP returns with a fatal error (PHP Fatal error: Only variables can be passed by reference in ...). At the code, a('text out').
So, how can I fix this code to accept a variable or a string correctly?
code (edited):
function a(&$var){
$backtrace = debug_backtrace();
$call = array_shift($backtrace);
$line = $call['line'];
$file = $call['file'];
echo name($var)."<br>".$var."<br>".$line."<br>".$file;
}
$variable='text in';
a($variable);
a('text out');
I need pass the variable by reference to use this function below (the function get the variable name correctly, works with arrays too):
function name(&$var, $scope=false, $prefix='unique', $suffix='value'){
if($scope) $vals = $scope;
else $vals = $GLOBALS;
$old = $var;
$var = $new = $prefix.rand().$suffix;
$vname = FALSE;
foreach($vals as $key => $val) {
if($val === $new) $vname = $key;
}
$var = $old;
return $vname;
}
The way your code is currently implementing pass by reference is perfect by design, but also by design cannot be changed to have two a() methods - one accepting a variable by reference and the other as a string-literal.
If the desire to pass a string literal instead of assigning it to a variable first is really needed, I would suggest creating a second convenience method named a_str() that actually accepts a string-literal instead of a variable by reference. This method's sole-purpose would be to relay the variable(s) to the original a() method - thereby declaring a variable to pass by reference.
function a_str($var) {
a($var);
}
The only thing to remember is, use a($variable); when passing by reference and a_str('some text'); when not.
Here is the same convenience-method for your name() function:
function name_str($var, $scope=false, $prefix='unique', $suffix='value'){
return name($var, $scope, $prefix, $suffix);
}
The only way to do what you are asking without writing an additional function like #newfurniturey suggests is plain and simply opening and parsing the file where your function was called as text (e.g. with fopen), using the data from debug_backtrace. This will be expensive in terms of performance, but it might be ok if used only for debugging purposes; and using this method you will no longer need a reference in your function, which means you can freely accept a literal as the parameter.

Making global var from inside a function in PHP

I am trying to define dynamically variables. I am using a function for this, but I don't know how to define the new var as global (because it never created before the function).
is that possible ?
Thanks.
edit
ok, this is what I've built. is it that dangerous ?
function extract_values($row) {
foreach ($row as $key => $value){
global $$key;
$$key = $value;
}
}
and then I'm trying to make my life easier like that:
$result = mysql_query("SELECT first_name, last_name, address FROM users ORDER BY id ASC");
while ($row = mysql_fetch_array($result)){
extract_values($row);
#[do some stuff with the variables.]#
}
I am doing it to save time. instead of creating for each column it's own variable like
$first_name = $row['first_name'];
This function does that for me.
I don't see why in this case it might be dangerous..
or as usuall, i am missing something..
Try this:
function doSomething() {
global $x;
$x = 5;
}
If you prefer to save a couple of bytes, you can use the $_GLOBALS array for this:
$_GLOBALS['x'] = 5;
Regarding your edit: It makes your code less understandable.
Actually, there already exists a function that is doing this: extract().
while (($row = mysql_fetch_assoc($result))){
extract($row);
// ...
}
extract() is even better, because it lets you specify what should happen if the variable already exists and/or lets you specify a prefix (so you don't overwrite already existing variables with that name). E.g. you could do:
extract($row, EXTR_PREFIX_ALL, 'db');
which would result in $db_first_name etc.
Surly, extract() is also doing some internal work here, but using built-in functions is always better than creating your own.
Another possibility would be to use list():
while (($row = mysql_fetch_row($result))){
list($first_name, $last_name, $address) = $row;
// ...
}
You can do it in two ways:
Make the variable global using the global keyword:
function fun1() {
global $foo;
$foo = 1;
}
Alternatively you can also create an new element in the $GLOBALS array:
function fun2() {
$GLOBALS['bar'] = 1;
}
Working code
Remember that these are considered bad practice, a function should have local variables invisible outside and should get inputs through the arguments passed. You should avoid getting arguments though global variables and must completely avoid crating global variables.

Categories