php functions within functions - php

ihave created a simple project to help me get to grips with php and mysql, but have run into a minor issue, i have a working solution but would like to understand why i cannot run this code successfully this way, ill explain:
i have a function,
function fetch_all_movies(){
global $connection;
$query = 'select distinct * FROM `'.TABLE_MOVIE.'` ORDER BY movieName ASC';
$stmt = mysqli_prepare($connection,$query);
mysqli_execute($stmt);
mysqli_stmt_bind_result($stmt,$id,$name,$genre,$date,$year);
while(mysqli_stmt_fetch($stmt)){
$editUrl = "index.php?a=editMovie&movieId=".$id."";
$delUrl = "index.php?a=delMovie&movieId=".$id."";
echo "<tr><td>".$id."</td><td>".$name."</td><td>".$date."</td><td>".get_actors($id)."</td><td>Edit | Delete</td></tr>";
}
}
this fetches all the movies in my db, then i wish to get the count of actors for each film, so i pass in the get_actors($id) function which gets the movie id and then gives me the count of how many actors are realted to a film.
here is the function for that:
function get_actors($movieId){
global $connection;
$query = 'SELECT DISTINCT COUNT(*) FROM `'.TABLE_ACTORS.'` WHERE movieId = "'.$movieId.'"';
$result = mysqli_query($connection,$query);
$row = mysqli_fetch_array($result);
return $row[0];
}
the functions both work perfect when called separately, i just would like to understand when i pass the function inside a function i get this warning:
Warning: mysqli_fetch_array() expects
parameter 1 to be mysqli_result,
boolean given in
/Applications/MAMP/htdocs/movie_db/includes/functions.inc.php
on line 287
could anyone help me understand why?
many thanks.

mysqli_query failed to run your query:
Returns FALSE on failure. For
successful SELECT, SHOW, DESCRIBE or
EXPLAIN queries mysqli_query() will
return a result object. For other
successful queries mysqli_query() will
return TRUE.
Before running mysqli_fetch_array test $result... Something like:
if ($result !== false)
$row = mysqli_fetch_array($result);
else
return false;
Seems like a variable scope issue within your SQL statement. Outputting the SQL should show you the "true" error.

You may want to try using classes with your functions, for example:
class getInfo {
function fetch_all_movies(){
global $connection;
$query = 'select distinct * FROM `'.TABLE_MOVIE.'` ORDER BY movieName ASC';
$stmt = mysqli_prepare($connection,$query);
mysqli_execute($stmt);
mysqli_stmt_bind_result($stmt,$id,$name,$genre,$date,$year);
while(mysqli_stmt_fetch($stmt)){
$editUrl = "index.php?a=editMovie&movieId=".$id."";
$delUrl = "index.php?a=delMovie&movieId=".$id."";
echo "<tr><td>".$id."</td><td>".$name."</td><td>".$date."</td><td>".get_actors($id)."</td><td>Edit | Delete</td></tr>";
}
}
function get_actors($movieId){
global $connection;
$query = 'SELECT DISTINCT COUNT(*) FROM `'.TABLE_ACTORS.'` WHERE movieId = "'.$movieId.'"';
$result = mysqli_query($connection,$query);
$row = mysqli_fetch_array($result);
return $row[0];
}
}
$showInfo = new getInfo;
//fetch all movies
$showInfo->fetch_all_movies();
//List actors from movie 1
$showInfo->get_actors("1");

In case of an error mysqli_query will return false. You have to handle the error a simple way to do this might be:
$result = mysqli_query($connection,$query);
if (!$result) {
die(mysqli_error($connection));
}
$row = mysqli_fetch_array($result);
Please note that terminating (by doing die() ) usually is no good way to react on an error, log it, give the user anice error page etc. It's alsonogood practice to give the low level error message toauser, this might motivate users to try to exploit a possile security issue.
Last remark: you were writing
$query = 'SELECT DISTINCT COUNT(*) FROM `'.TABLE_ACTORS.'` WHERE movieId = "'.$movieId.'"';
you should properly escape the movieId there.

Related

PHP code mysql query isnt working

I created a mysql query to check if user is banned or not and if he's the system give him return false. But it wont get the information.
public static function checkban($username)
{
if(LOGINCHECKBAN == false)
{
$vusername = engine::securyt($username);
$getIdBYname = "SELECT id FROM players WHERE username='".$vusername."' LIMIT 1";
$getNOW = mysql_query($getIdBYname);
$IDbyNAME = mysql_free_result($getIdBYname);
$queryforban = mysql_query("SELECT * FROM bans WHERE data = '".$IDbyNAME."' LIMIT 1");
$query = mysql_num_rows($queryforban);
if($query == 0) {
return true;
} else {
return false;
}
}
}
Note: engine::securyt($username) is the form type to get his username when he try to login.
What can be wrong on my code?
edit: I belive that "mysql_free_result" can be the problem, but im not sure what i need to put on replace of it.
mysql_free_result() frees a mysql result set. It does not actually retrieve data from the result.
You will want something like:
$getIdBYname = "SELECT id FROM players WHERE username='".$vusername."' LIMIT 1";
$result = mysql_query($getIdBYname);
$row = mysql_fetch_assoc($result);
if($row) { //a user was found
//$row['id'] is the found user
$result = mysql_query("SELECT COUNT(*) cnt FROM bans WHERE data = '". $row['id'] ."' LIMIT 1");
$row = mysql_fetch_assoc($result);
return ($row && $row['cnt'] == 0);
} else {
// no user; return something appropriate
}
However, if all you need is to determine is whether a particular user name is banned (and not actually get their user id), you can do that directly in the database with one query:
SELECT COUNT(*)
FROM players p
INNER JOIN bans b ON b.data = p.id
WHERE p.username = $username;
WARNING: Note that using mysql_* functions is strongly discouraged for new code (since mysql_* has been removed in PHP 7), and directly including variables in your query strings is a pretty major security vulnerability. You should look into using prepared statements/parameterized queries with mysqli or PDO.

Create single PHP Function for similar queries but with different WHERE clauses

I'm not sure if this is doable or not, and I'm not entirely sure how to search for this. I have several dynamic web pages that all link to the same MySQL database table, but pull different results. So for example, a dynamic web page with ID = 5 will run a query like:
SELECT * FROM myTable WHERE category1 = 1
The web page where ID = 7 will run:
SELECT * FROM myTable WHERE category2 = 1
And so on. The queries are all grabbing the data from the same table, but the WHERE clause is different for each query - its not looking at the same column. The page with ID 7 should ONLY be returning results where category2 = 1, and ignoring the results that would be returned for the page with id = 5. My website has about 20 different pages/queries like this which is why I'm looking to see if it can be done in a function instead.
Is there a way I can put that into a function, and if so, how would I set up the parameters correctly? Or is this an instance where I will have to just write out all the queries separately on each page?
function find_results(what to put here?) {
global $connection;
$query = "SELECT * FROM myTable WHERE (how to code this part?)";
$result = mysqli_query($connection, $query);
confirm_query ($result);
return $result;
}
You would add the necessary parameters to your functions argument list, then provide the values at runtime.
function find_results($column, $value)
{
global $connection;
$query = "SELECT * FROM myTable WHERE {$column} = $value";
$result = mysqli_query($connection, $query);
confirm_query ($result);
return $result;
}
//Usage:
$result = find_results("category2", 1)
If the value you are returning records by ever ends up being a string make sure your wrap $value in single quotes.
if its a constant relation between pageId and categoryId, you can just create an array to hold it indexed by pageId like:
$pageIdToCategoryMapping = [
1 => 'cateogory1',
2 => 'category5',
...
]
and then just use it to pass data to your function like
find_results($pageIdToCategoryMapping[$pageId])
function find_results($category) {
(...)
$query = "SELECT * FROM myTable WHERE ({$category} = 1)";
(...)
}
I have been using class and object methods for mysql operations. source code available in github
I would recommend you to pass array as an argument and can return query or result as array in format you required. And this function will work any number or condition
<?php
$arg['db']="database";
$arg['tabe']="table";
$arg['search']['id1']="id1";
$arg['search']['id2']="id2";
//
function searchAndReturnResultAsArray($arg)
{
$return = NULL;
$query="SELECT * FROM ".$arg['table'];
$flag=false;
foreach($arg['search'] as $key=>$value)
{
if($flag)
$query.=" AND ";
else
$flag=true;
$query.= $key." = '".$value."' ";
}
$row = mysqli_num_rows($query);
$field = mysqli_fetch_object($query);
if($row >= 1)
{
while($data = mysqli_fetch_array())
{
$return[] = $data;
}
}
return $return;
}
?>
Or alternatively you can just return query once it is ready.

mysql_num_rows() return 0 when using AND

I am trying to retrieve the number of rows based on this query in wordpress:
protected function wp_has_facility($fid)
{
//global $wpdb;
$fid = intval($fid);
$sql = "SELECT post_id FROM wprf_postmeta WHERE meta_value = '".$fid."' AND meta_key = 'facility_id'";
$result = mysql_query($sql) or die(mysql_error());
$num_rows = mysql_num_rows($result);
echo $num_rows;
return $num_rows;
}
$num_rows returns 0 when this function is ran.
If I echo the query string and run it in phpmyadmin, it selects successfully giving me a number of rows.
After further investigation it looks like when I hardcode the meta_value it will give me a row count. But if I'm populating the string with variables it doesn't work.
Any ideas?
This only means your table currently contains no record that satisfies both criteria.
Remarks about your code:
Concatenation is not necessary, you may replace the query with:
$sql = "SELECT post_id FROM wprf_postmeta WHERE meta_value = '$fid' AND meta_key = 'facility_id'";
mysql_* functions are deprecated, you should avoid using them as they will be removed in a future version of PHP. Here are the alternatives.

mySQL/PHP: SQL Statement, query and result assignment in ONE line?

Is it possible to re-write the code below, maybe even with an if (result > 0) statement, in just one line (or simply shorter)?
// a simple query that ALWAYS gets ONE table row as result
$query = $this->db->query("SELECT id FROM mytable WHERE this = that;");
$result = $query->fetch_object();
$id = $result->id;
I've seen awesome, extremely reduced constructs like Ternary Operators (here and here - btw see the comments for even more reduced lines) putting 4-5 lines in one, so maybe there's something for single result SQL queries like the above.
You could shorten
$query = $this->db->query("SELECT id FROM mytable WHERE this = that;");
$result = $query->fetch_object();
$id = $result->id;
to
$id = $this->db->query("SELECT id FROM mytable WHERE this = that")->fetch_object()->id;
but this, and the original code will emit errors, if any of the functions returns an unexpected response. Better to write:
$query = $this->db->query("SELECT id FROM mytable WHERE this = that");
if (!$query) {
error_log('query() failed');
return false;
}
$result = $query->fetch_object();
if (!$result) {
error_log('fetch_object() failed');
return false;
}
$id = $result->id;

mysql_query inside for loop gives mysql_fetch_assoc related error/warning

Im trying to get the id's of the questions that are answered or asked by particular user and than im trying to use those id's and get questions where id is different from the id's retrieved from the first query.While trying to achieve this im getting an mysql_fetch_assoc() related error/warning and as a result my program crashes.
Following is the code from my DB_Functions.php file where im executing queries on database.
public function getQuestions($username){
$result = mysql_query("SELECT question_id FROM answered WHERE asked_by = '$username' OR answered_by = '$username'");
if($result){
$data = array();
while($row = mysql_fetch_assoc($result)) {
$data[] = array(
$r=$row["question_id"]);}
for($i=0; $i<sizeof($data); $i++){
$result2 = mysql_query("SELECT * FROM answers EXCEPT WHERE question_id='$data[i]'") or die(mysql_error());
return ($result2);
}
}else{
return false;}
}
Following the code located in index.php where im trying to receive the result from DB_Functions.php
if($tag == 'getQuestions'){
$username = $_POST['username'];
$getAllQuestions = $db->getQuestions($username);
$data = array();
while($row = mysql_fetch_assoc($getAllQuestions)) { //I'm getting ERROR on this line
$data[] = array(
$response["getAllQuestions"]["id"] = $row["id"],
$response["getAllQuestions"]["username"] = $row["username"],
$response["getAllQuestions"]["question_id"] = $row["question_id"],
$response["getAllQuestions"]["question"] = $row["question"],
$response["getAllQuestions"]["tag1"] = $row["tag1"],
$response["getAllQuestions"]["tag2"] = $row["tag2"],
$response["getAllQuestions"]["tag3"] = $row["tag3"],
$response["getAllQuestions"]["question_time"] = $row["question_time"]);}
echo json_encode($data);
}
Below is the logcat message:
06-26 21:08:13.920: D/JSON(478): <b>Warning</b>: mysql_fetch_assoc() expects parameter 1 to be resource, null given in <b>C:\xampp\htdocs\android_php_1\index.php</b> on line <b>178</b><br />
Thanks
MySQL does not support the EXCEPT keyword, so the query returns null to $result2 because no result set was formed, which is why you're getting that error. Instead, you can actually consolidate those two queries into one like so:
SELECT
a.*
FROM
answers a
LEFT JOIN
(
SELECT DISTINCT question_id
FROM answered
WHERE ? IN (asked_by, answered_by)
) b ON a.question_id = b.question_id
WHERE
b.question_id IS NULL
In your getQuestions() function, you can replace the whole thing with:
public function getQuestions($username) {
$filtered_username = mysql_real_escape_string($username);
$sql = "
SELECT a.*
FROM answers a
LEFT JOIN
(
SELECT DISTINCT question_id
FROM answered
WHERE '$filtered_username' IN (asked_by, answered_by)
) b ON a.question_id = b.question_id
WHERE b.question_id IS NULL";
return mysql_query($sql) ?: false;
}
Also note that your previous code was vulnerable to SQL injection. In my solution, I first passed the username variable through mysql_real_escape_string() to prevent that (not as good as prepared statements, but still better than nothing). NEVER pass user-input directly into a query.

Categories