Returning Array From PHP Function - php

What is wrong with this code? I am trying to return an array and use it in the caller function.
function my_subjects()
{
$all_my_teams=my_teams();
$k=0;
$_subjects=array();
while($team=mysql_fetch_assoc($all_my_teams))
{
$q="SELECT $this->user_field FROM $team";
$r=mysql_query($q);
while($i=mysql_fetch_assoc($r))
{
$_subjects[k++]=$i;
}
}
return $_subjects;
}
Note: the function my_teams() returns the value similar to the $r variable which is used through all_my_teams variable. it contains all the names of teams.

Turn up error_reporting to see if your code is generating errors.
Check if your query is successful if( ! $r=mysql_query($q) ) { die(mysql_error()); }
var_dump($_subjects); to see if the data is what you expect it to be.
Maybe actually tell us what's going wrong? You've just posted a block of code and told us "it doesn't work." which isn't terribly indicative of a problem.
$k is irrelevant, just use $_subjects[]=$i;. [wouldn't cause an error, just easier]
Stop using mysql_* functions and port your code to PDO or MySQLi to:
Benefit from parameterized queries which can help protect against SQL injection.
Stop everyone on SO starting an unrelated argument in the comments about it.

while($i=mysql_fetch_assoc($r))
{
$_subjects[k++]=$i;
}
Here you also have to provide a field name for $i. Something like
while($i=mysql_fetch_assoc($r))
{
$_subjects[$k++]=$i["field_name"];
}
Array returning part is just fine.
Edit: Your variable k was missing a $ sign as well.

$_subjects[$k++] = $i;
should be fine, since you're using mysql_fetch_assoc() $i will contain an associative array of the result set.
If this is returning an empty array (is that the correct problem?), you should double check that your sql is correct and actually returning data/data that you expect.
Edit: Like Hanky Panky mentioned, 'k' is missing a $ sign in your code - that is likely to be your problem - PHP should be throwing a parse error for that one, so make sure you have error_reporting() enabled.

Related

PHP Array - Missing Entry

Can anyone tell me, if there is an error in the following code, please?
eval ("\$typeselectbit = \"".$cmstpl->get("admin_selectbitdefault")."\";");
$result = $cmsdb->query("SELECT * FROM cms".$n."_type WHERE deleted = '0' ORDER BY typename ASC");
while ($type = $cmsdb->fetch_array($result))
{
$typeid = $type['typeid'];
$typename = $type['typename'];
eval("\$typeselectbit .= \"".$cmstpl->get(ifelse($GPC['typeid'] == $typeid, "typeselectbit2", "typeselectbit"))."\";");
}
It doesn't output the first entry from the array. But maybe the error is somewhere else.
At the moment, I'm not sure, where this problem is coming from.
What do you think? Does it look correct to you?
And if not, what do I have to fix and how exactly should it look like?
Or do I have to look somewhere else in the script?
Any specific hints, which could help to find the reason?
Thank you for your help! :)
The last line in your code eval("\$typeselectbit .= \"".$cmstpl->get(ifelse($GPC['typeid'] == $typeid, "typeselectbit2", "typeselectbit"))."\";"); has a parse error. ifelse is not valid PHP syntax (unless that is a function you have declared previously). It could also be any other number of errors occurring inside of the eval construct.
According to the manual
If there is a parse error in the evaluated code, eval() returns FALSE and execution of the following code continues normally. It is not possible to catch a parse error in eval() using set_error_handler().
It's not clear why you chose to use eval at all here, but one of the down sides, among others, is that you typically can't easily debug these kinds of errors inside of eval. If you ran this code outside of eval you'd immediately see the parse error.

Using die() to return ajax value in PHP

Are there any reasons to not to use die($result) to return Ajax request result in PHP? Please note that this is theoretical question, about code semantics.
Simple example (of course functions may be much complicated and return different values).
JS:
<script>
function checkLogin(login){
$.post('/ajax/check',{'login':login},function(res){
if(res == 1) return 1; else return 0;
}
}
</script>
PHP:
<?php
$db = mysql_connect(...);
$login = mysql_real_escape_string(stripslashes($_POST['login']));
$res = mysql_query("SELECT * FROM project.users WHERE login = '$login'");
if(mysql_num_rows($res)) die('0'); else die('1');
?>
PS. I know tha that mysql_*() functions are deprecated, no need to comment that. I simply like using them and will. As far as it will be possible.
EDIT:
I wonder why noone noticed that checkLogin() function has no sense, as request is async, and function always returns undefined ;-)
Since die() does not send any HTTP error status, there is no problem using it to return a string for an ajax call, but what stays there to say is, for the readability of the code, I don't think it's a good idea, but other than that, for functionality, there is no problem with it,since it outputs the message.
but also, now that's it's said, you have to take into consideration cases like CLI PHP in which the returned integer can really mean something for the shell(just for mentioning).
I would say that no, you don't want to do this. It is not made to return something to an ajax call, it is an equivalent to exit(), and you can give it a status.
That is just opinion though, but one that does have to do with semantics: it isn't meant to be used as a sort of echo, so don't use it as one.
The fact that you can have it 'return' an integer (as in, that works), but if you'd put in 255 it will not because it is reserved makes it tricky and unreadable.
So sure, while syntactically it works for values like '0', it would consider it bad form to use a language structure to return arbitrary messages, as it cannot return all messages.
Yes, there's a problem. In your too simple case no, but imagine this:
die($Result);
How will that behave? You don't know what that will do, since you don't know the type of $Code. As hank pointed out, if it's an integer it won't print anything. So you have a line of code that will behave differently depending of $Result. It seems very prone to heisenbugs.
PHP documentation:
Note: PHP >= 4.2.0 does NOT print the status if it is an integer.
A better solution would be to improve the control of the flow:
if ($this_is_NOT_an_ajax_call) {
// Do what you need to do
}
else {
echo $Result;
}

Problems with converting mysql over to mysqli errors with mysqli_query & mysqli_fetch_row

Here is the edited script without errors. And the 2 fixes applied to it. To those who helped in part, thank you. To mentions that the code is unclear or messy is inconsequential. Given that most of the following is common structure in mysql queries. Even the example documentation for mysql followed this similar flow. Members who reply should negate from pointless internet banter. Its more worth your time, and my own to do so. Those who stayed on topic and assisted, I thank you.
For example:
$row = mysqli_fetch_row(mysqli_query($con, "SELECT test_table.points FROM test_table WHERE test_table.key = '" . $key . "'"));
if ($row[0] > 0){ // exists
Where $row will return a non-zero result if true. Otherwise 0 on false. There is little need to check mysqli_fetch_row and/or mysqli_query. Since checking $row in simplicity works fine. It is unneeded to check mysqli_fetch_row and/or mysqli_query individually in a general exists condition. It does accurately provide exist / does not exist results. There is no $result $row $query just $row.
The noted deviation to that normal flow was my desire to use call_user_func. And to poll in func and params through $_GET. Will be looking more at PDO. However, the clean code before exec should do alright job for now. Which is to clean before exec.
All in all, the code works just as it should. And have since written more to manage a mysql database. From write, write chunk, read, read chunk, delete, delete chunk.
Also to collect numbered records on request. For example say you have 6 records for the same John Smith. You can now collate and scan for differences in those records. Either for what you want, dont want, etc. Or if say you just want to blindly call the first 3 of those records for John Smith.
mysqli_fetch_row & mysqli_fetch_row fix :
FROM Calling $con outside function then into as per mysql. Which in mysqli does not work as expected. There was no error with the functions, over how $con was being handled.
TO Calling $con inside function with just the added global $con. May end up using $GLOBALS even for this.
Result : Calling $con outside function then in works fine in mysql. In mysqli it requires global be set within the function. ie global $con. Or it fails.
call_user_func non-critical error fix :
FROM call_user_func($func($_GET['user'],$_GET['key'],$_GET['points'],$_GET['type']));
TO call_user_func($func,$_GET['user'],$_GET['key'],$_GET['points'],$_GET['type']);
Result : Both lines execute correctly. From executed with a non-critical error. TO does the same thing, but with no following non-critical error.
Sample Output for both : user=MY_Name;key=34342$ee56i1;points=1234;type=
-- code removed as fixes solved the issues --
You are using call_user_func wrong read the manutal
call_user_func first parameter is the callback - in your case it's a function inside your class so it should be something like this:
If you have a non-static function in an object:
class Test{
public function doit($a){
echo($a);
}
}
$t = new Test();
call_user_func(array($t,'doit'),'asfaasfs');
and in static functions inside object:
class Test{
public static function doit($a){
echo($a);
}
}
call_user_func('Test::doit','asfaasfs');
You have a few problems.
$con is declared outside the class, and is thus not available inside the class. You need to pass it into the class (the better option), or specify it as a global (the quick+dirty option).
mysqli_fetch_row(mysqli_query($con,'...'))
This code is obviously converted directly from your old mysql_xx() code, but it's not great.
You're ignoring any possible error condition that is returned by mysqli_query(). This means that if it fails, it'll pass false into the mysqli_fetch_row() function, which will then fail with a meaningless error expects parameter 1 to be mysqli_result, rather than actually telling you what the error was in the query.
The thing is, because of my first point above, with $con not being set, mysqli_query() is failing, and this is why you're getting the error in mysqli_fetch_row().
Ideally, you should split this code out into multiple lines. Call mysqli_query() on its own, then do some error checking, then call mysqli_fetch_row() only once you know that the query actually worked.
Hope that helps explain what the problems are here. Solve those two points, and you should be well on the way to sorting the whole thing out.
Once you've got rid of those fatal errors, you should also take time to work on the problem that your code is vulnerable to SQL injection attacks. You're currently passing your $_GET variables directly into the query strings without any sanitisation. This will make your system very fragile and easy to hack. You should consider using Parameterised Queries, which is a feature of the mysqli library designed to make it easier to deal with variables in SQL queries in a safe and secure way.
Your class is pointless at the moment, perhaps stick to writing imperative style code as it will at least be cleaner.
At the moment, you should pass $con to your MYsql class to use itself as a resource, not try to access it as a global variable.
Your are not filtering your user's input either, this is dangerous and could lead to SQL injection attacks on your site.
I'd encourage you to read through these two articles, and once you grok them, I'd also encourage you to simply switch to using PDO with prepared statements. This will stop SQL injection attacks that your code currently allows.
http://net.tutsplus.com/tutorials/php/pdo-vs-mysqli-which-should-you-use/
http://net.tutsplus.com/tutorials/php/why-you-should-be-using-phps-pdo-for-database-access/

Is it always necessary to use "is_array()" before a foreach?

I was wondering if it is always necessary to use something like is_array() before every foreach i do.
In case the variable is not an array, it throws an error.
So i always use:
if(is_array($users)) {
foreach($users as $user){
}
}
What would you recommend me?
Thanks.
Well if you know your code well enough, there should be no reason to have to check if it is an array.
Otherwise, if the variable changes type that often I would suggest tweaking your code a bit so it does not do that.
Other than that, using that if statement is the way to go.
If you're sure that something is an array or otherwise implements Iterable, you obviously don't need the extra if condition. If you're not sure, then obviously checking the type will make your code more reliable.
Some hacks I've seen include casting the variable to an array: (array)$users. This is not recommended though, it's better to explicitly check the type.
Also, if this is code inside a function you can use argument typing:
function mycode(array $users)
{
foreach ($users as $user) { }
}
When the function is called with the wrong type it will trigger an error.
Assuming this happens in a function:
function doSomethingWithUsers($users)
{
if(!is_array($users))
{
throw new Exception('$users is expected to be an array');
}
foreach($users as $user){
...
}
}
This way you'll immediately see whenever it's called with the wrong parameters.
In general, it's better not to.
A good general principle in programming is not to hide or ignore errors.
If a variable should be an array, it does you no service to specifically ignore the situation if it's not an array. Instead, it is better for you to be informed of the problem with the built-in error handling. Otherwise, you're not fixing the problem, just hiding its effects. This can make debugging subsequent problems difficult.
However, there's a number of assumptions here:
This is assuming that the variable is supposed to be an array. If you're using foreach () on it, I assume this to be the case. If you're running foreach () on something that might legitimately not be an array it might be an indication your code may need re-working.
Your error reporting and/or logging (reporting on a development server, logging on production) needs to be set up correctly in order to benefit from what PHP errors tell you. Specifically, it's almost never a good idea to ignore PHP warnings - despite being called "warnings" they usually indicate a failure which (in my opinion) should stop execution.
That said, it's not necessarily wrong to use an is_array() in front of a foreach ().
What would you recommend me?
Yes it is good idea and such considerations make you a defensive programmer :)
It's better for me:
foreach (is_array($arr) ? $arr : array() as $key=>$val) {
//..
}

Fatal error: Can't use function return value in write context

I have a pretty nasty error I can't get rid of. Here's the function causing the issue:
function get_info_by_WatIAM($WatIAM, $info) {
$users_info = array();
exec("uwdir -v userid={$WatIAM}", $users_info);
foreach ($users_info as $user_info) {
$exploded_info = explode(":", $user_info);
if (isset($exploded_info[1])){
$infoArray[$exploded_info[0]] = $exploded_info[1];
}
}
return $infoArray[$info]; }
Here's what's calling the function:
} elseif ( empty(get_info_by_WatIAM($_POST['ownerId'])) ) { ...
I would really appreciate any suggestion. Thanks very much!
If the code doesn't make sense, here's a further explanation: exec uses a program that stores information on all the users in a school. These include things like faculty, name, userid, etc. The $_POST['ownerId'] is a username -- the idea is that, upon entering a username, all of the user's information is automatically filled in
You do not need empty around function calls, in fact empty only works with variables and not functions (as you see). You only need empty if you want to test a variable that may not be set for thruthiness. It is pointless around a function call, since that function call must exist. Instead simply use:
} else if (!get_info_by_WatIAM($_POST['ownerId'])) { ...
It does the same thing. For an in-depth explanation, read The Definitive Guide To PHP's isset And empty.
empty can only be used on variables, not on expressions (such as the result of calling a function). There's a warning on the documentation page:
Note:
empty() only checks variables as anything else will result in a parse
error. In other words, the following will not work: empty(trim($name)).
Just one of PHP's best-left-alone quirks.
One workaround is to store the result in a variable and call empty on that, although it's clunky. In this specific case, you can also use
if (!get_info_by_WatIAM(...))
...although in general, if (empty($a)) and if(!$a) are not equivalent.
get the value of this
$a = get_info_by_WatIAM($_POST['ownerId'])
then chack
empty($a)
it will work

Categories