I am currently busy on a textbased RPG game, but I am stuck at one part right now.
In order to start a mission, the player does need some items, these are stored in a string: item:1x3-item:5x1 - (basicly item:IDxamount).I have already made a function that explodes the string into variables, but now the script needs to check if the player does have all the items listed.
I've tried to solve the issue with a foreach, but that returns positive or negative for every item, and I only need to know if the player has all items at once.
(don't mind the unsafe query)
$parseAmount is an array, containing all item ID's.
$uid is an variable containing userID
// check if player has all items
foreach($parseAmount as $itemID)
{
$check_query = mysql_query("SELECT * FROM `player_items` WHERE `player`='$uid' AND `item`=='$itemID' AND `value`>='$parseAmount[1]'");
if(mysql_num_rows($check_query)>=1)
{return true;}
else
{return false;}
}
If you want me to post the whole function, please let me know.
If I understood your question correctly you need something like:
foreach($parseAmount as $itemID) {
$sql = "SELECT COUNT(*) AS count
FROM player_items
WHERE player = '".mysql_real_escape_string($uid)."'
AND item = '".mysql_real_escape_string($itemID)."'
AND value >= ".intval($parseAmount[1]);
$row = mysql_fetch_array(mysql_query($sql));
if ($row['count'] == 0) {
return false;
}
}
return true;
You must not early return true. You know the result is true only after checking all the items. My code could be improved by selecting all the items at once, but it's up to you to build this.
Keep in mind my comment about the deprecation of the MySQL extension, using MySQLi and Prepared Statements it will look something like this (note that I never worked with MySQLi before and built it with help of the manual):
foreach($parseAmount as $itemID) {
$sql = "SELECT COUNT(*) AS count
FROM player_items
WHERE player = ?
AND item = ?
AND value >= ?"
$stmt = $mysqli->prepare($sql);
$stmt->bind_param("ssi", $uid, $itemID, $parseAmount[1]);
$stmt->execute();
$row = $stmt->get_result()->fetch_array();
if ($row['count'] == 0) {
return false;
}
}
return true;
Related
I'm sorry to have to post this, I know it seems similar to other posts, so I ask you to please bear with me...
What I am trying to do: I have a sql query that is in a function, the point of the function is to find if there are TinyInts of a particular value (1 or 0), I am doing a count, and need to just return effectively if it found the value in the specified in the query. What should be coming back is 1 but I only get 0's back...
Here is the whole function:
//return count of VALUES
function getcountsroles($searchParams, $searchCrit){
/// does query, gets results, counts the number and returns that true or false
///this willbe used to show the dashboard user control more efficently.
// $searchParams == column
// $searchCrit == int 1 or 0
//should fetch back the count back from the query
global $db, $dashboard_message_users;
$count_Data=array();
$query = "SELECT COUNT(userID) AS countVal FROM roles WHERE ? = ?";
$stmnt = $db -> prepare($query);
if(!$stmnt){
echo var_dump($stmnt);
}
$stmnt -> bind_param("si", $searchParams, $searchCrit);
if(!$stmnt -> execute()){
$dashboard_message_users = "<p class='alert alert-danger'>The db query faulted.</p>";
}
$result = $stmnt -> get_result();
while ($data = $result->fetch_assoc()){
$count_Data[] = $data;
}
$test = 'userID';
$value = (int)($data['countVal']);
echo var_dump($test);
echo var_dump($searchCrit);
echo var_dump($searchParams);
echo var_dump($value);
echo var_dump($count_Data);
if ($value > 0){
return true;
}else{
return false;
}
}
The calling function sends the column to count the values of, and the the value that we are looking for. when I run the query against the database I get the correct values, I have tested with different columns and values (again 1 or 0)
SELECT COUNT(*) as 'countVal' FROM roles WHERE isUser = 1;
SELECT * FROM roles WHERE isUser = 1;
SELECT * FROM roles;
SELECT COALESCE(COUNT(isUser),0) AS totid FROM roles;
the first one returns 2, the second is all the rows where isUser is value of 1,
third grabs all rows... and the last one was a attempt to see if it was going work... but it still only returns 0 to the result... I have also tried to get the count of rows should be 1, either if true or false... This i getting annoying, Unfortunately I happen to be using mysqli lib and most exampled are for POD or old mysql_PHP, and in OO it seems to not like the prepared statements.
I am positive its something I am doing, I have looked over and over my code and I cant see what the issue is... Maybe if a fresh pair of eyes.
Any time or replies that help me and others out would be greatly appreciated.
Jesse Fender
I have looked on here about if statements. I have found a few things but I am having issues figuring out the proper statement formula.
I have 2 tables in the database with the following 2 fields
table 1
rct_app_id
table 2
uid
now if the uid field matches the rct_app_id field I want it to
echo "Green Light";
if they don't match
echo "No Go"
this is my formula
<?php
$user_id = $_SESSION['uid'];
$sql = "SELECT * FROM recruits WHERE rct_app_uid = {$user_id}";
$result = query($sql);
$rct_app_id = ['rct_app_id'];
if ($rct_app_id == 'uid') {
echo "Green Light";
} else {
echo "No Go";
}
?>
function query($query)
{
global $connection;
return mysqli_query($connection, $query);
}
Try this. but keep in mind its hard for people to figure out whats going on by bits and pieces and it makes it harder to help you.
<?php
$user_id = $_SESSION['uid'];
$sql = "SELECT * FROM recruits WHERE rct_app_uid = {$user_id}";
$result = query($sql);
while(($row = mysqli_fetch_assoc($result))!=false){
$rct_app_id = $row['rct_app_id'];
if ($rct_app_id == $user_id) {
echo "Green Light";
} else {
echo "No Go";
}
}
}
?>
You need to fix two lines. $result has the results from the database, so that's the source for the rct_app_id data. Then, when you do the comparison, you need to compare the two variables.
$rct_app_id = $result['rct_app_id'];
if ($rct_app_id == $user_id) {
The way you have it, you're comparing an array to a string.
When you do this:
$rct_app_id = ['rct_app_id'];
You're actually setting the variable $rct_app_id equal to an array with one element, although the syntax is incorrect. Instead, you need to get one element of the array that is returned from the database. This assumes that you have a function called query() that is working properly and returning an array.
Instead, we need to set the variable equal to one element of the array like so:
$rct_app_id = $result['rct_app_id'];
Then, when you do a comparison like this:
if ($rct_app_id == 'uid') {
you're saying if the variable $rct_app_id is equal to the string uid, which it's not. Variables always start with $ in php, strings are quoted. The variable set earlier in the script is $user_id (from SESSION), so we need to compare to that:
if ($rct_app_id == $user_id)
UPDATE: You've specified your sql lib, I've edited the answer below to work with your updated answer.
Since you didn't specify the library, I'm making the answer and the code edits with the assumption that you're using mysql. Though all queries and return functions use similar syntax, ie: mysql_fetch_assoc() = mysqli_fetch_assoc(), pg_fetch_assoc(postgres).
<?php
$user_id = $_SESSION['uid'];
$sql = "SELECT * FROM recruits WHERE rct_app_uid = {$user_id}";
$result = query($sql); //What type of query runs as just query()? mysql_query would go here if this was mysql. Some Libraries offer this as a function, but since you didn't specify the library, I'm going to change it to mysql_query and proceed as if you're using mysql.
//$rct_app_id = ['rct_app_id'];//This will never work.
//You need this:
while($row=mysqli_fetch_assoc($result)){
//We only expect one result
$rct_app_id=$row['rct_app_id'];
}
if ($rct_app_id == 'uid') {
echo "Green Light";
} else {
echo "No Go";
}
function query($query)
{
global $connection;
return mysqli_query($connection, $query);
}
?>
This question already has answers here:
Row count with PDO
(21 answers)
Closed 2 years ago.
I know this question has been asked before but it seems like the solutions have been specific to the problem presented.
I have a codebase with hundreds of instances where mssql_num_rows is used.
Code example:
$db->execute($sql);
if ($db->getRowsAffected() > 0) {
$total = $db->fetch();
In db class:
$this->rowsaffected = mssql_num_rows($this->query_result);
I can't create generic SELECT count(*) FROM table queries as I have too many specific select statements.
I could run a preg_replace to remove everything between SELECT and FROM and then replace with a COUNT(*) and run a second query but this assumes all queries are setup a certain way.
I could fetchAll first then count() the results but that means upgrading all instances of the if statements.
So what is the best all around replacement to a *_num_rows function if people are updating their code to PDO. Not something that solves a specific problem, but something that replaces the functionality of *_num_rows. If that's not possible what allowed it to be possible before?
If you want to count the rows you can do this with PDO:
$sql = 'select * from users';
$data = $conn->query($sql);
$rows = $data->fetchAll();
$num_rows = count($rows);
There is no way to directly count rows when using a SELECT statement with PDO as stated in the docs.
PDOStatement::rowCount() returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement executed by the corresponding PDOStatement object.
Only do a row count if you absolutely need the count, otherwise you can verify that the query worked with other methods. You should also not use this method if you expect to be returning thousands of rows from a table, instead, use the COUNT() function in a query for just performing the count.
So with everyone's help this is what I built.
function getRowsAffected() {
$rawStatement = explode(" ", $this->query);
$statement = strtoupper($rawStatement[0]);
if ($statement == 'SELECT' || $statement == 'SHOW') {
$countQuery = preg_replace('/(SELECT|SHOW)(.*)FROM/i', "SELECT count(*) FROM", $this->query);
$countsth = $this->pdo->prepare($countQuery);
if ($countsth->execute()) {
$this->rowsaffected = $countsth->fetchColumn();
} else {
$this->rowsaffected = 0;
}
}
return $this->rowsaffected;
}
$this->rowsaffected is already being updated in the execute phase if the statement is an INSERT, UPDATE, or DELETE with $sth->rowCount() so I only needed to run this second query on SELECT and SHOWS.
if ($statement == 'INSERT' || $statement == 'UPDATE' || $statement == 'DELETE') {
$this->rowsaffected = $this->sth->rowCount();
}
I feel bad though, because just as I mentioned in my question, that I was looking for an overall solution I seem to have stumbled onto a specific solution that works for me since the code already asks for the number of rows using a function. If the code was doing this:
if (mysql_num_rows($result) > 0) {
then this solution would still create work updating all instances to use that custom function.
So let me explain my problem, lets assume that I run query like so:
$myquery = sql_query("SELECT name FROM table WHERE name='example' LIMIT 0,1");
Now.. I want to store the retrieved name into a variable so I would do something like this:
while ($myrow = sql_fetch_assoc($myquery)) {
transfer_row($myrow);
print"Name: $row_name";
}
$stored_name = $row_name;
NOTE: transfer_row() is just a function I wrote that takes $myrow['name'] and stores it in $row_name, for easier reference
Now, all is fine at this stage, here is where it gets interesting. Note that at this stage I still have a name assigned to $row_name. Further down the page I run another query to retrieve some other information from the table, and one of the things I need to retrieve is a list of names again, so I would simply run this query:
$myquery = sql_query("SELECT name, year FROM table WHERE DESC LIMIT 0,10");
while ($myrow = sql_fetch_assoc($myquery)) {
transfer_row($myrow);
$year = $row_year;
$link = "/$year";
print "<li style=\"margin-bottom: 6px;\">$row_name\n";
}
Now, I want to write an if statement that executes something if the $row_name from this query matches the $row_name from the old query, this is why we stored the first $row_name inside the variable.
if ($row_name == $stored_name){
// execute code
}
However as most of you know, this WONT work, the reason is, it simply takes $stored_name again and puts the new $row_name into $stored_name, so therefore the value of the first $row_name is lost, now it is crucial for my application that I access the first $row_name and compare it AFTER the second query has been run, what can I do here people? if nothing can be done what is an alternative to achieving something like this.
Thanks.
EDIT, MY transfer_row() function:
function transfer_row($myrow) {
global $GLOBALS;
if(is_array($myrow)) {
foreach ($myrow as $key=>$value) {
$key=str_replace(":","",$key);
$GLOBALS["row_$key"] = $value;
}
}
}
Without you posting the code for the function transfer_row, we won't be able to give you an answer that exactly matches what you request, but I can give you an answer that will solve the problem at hand.
When matching to check if the names are the same, you can modify the if statement to the following.
if ($row_name == $myrow['name']){
// execute code
}
What I suggest you do though, but since I don't have the code to the transfer_row function, is to pass a second variable to that function. The second variable will be a prefix for the variable name, so you can have unique values stored and saved.
Refrain from using the transfor_row function in the second call so your comparison becomes:
if ($myrow['name'] == $row_name)
If you need to use this function, you could do an assignment before the second database call:
$stored_name = $row_name;
...
transfer_row($myrow);
In your first query you are selecting the name field WHERE name='example' , Why are you quering then? You already have what you want.
Your are querying like:
Hey? roll no 21 what is your roll no?
So perform the second query only and use the if condition as :
if ($row_name == 'example'){
// execute code
}
Does it make sense?
Update
//How about using prefix while storing the values in `$GLOBAL` ??
transfer_row($myrow, 'old_'); //for the first query
transfer_row($myrow, 'new_'); //for the second query
function transfer_row($myrow, $prefix) {
global $GLOBALS;
if(is_array($myrow)) {
foreach ($myrow as $key=>$value) {
$key=str_replace(":","",$key);
$GLOBALS["$prefix"."row_$key"] = $value;
}
}
}
//Now compare as
if ($new_row_name == $old_row_name){
// execute code
}
//You'll not need `$stored_name = $row_name;` any more
I have a time dependent script I am working on and used microtime() to find the bottle neck. I determined the time increase is caused by doing a check on 300+ values to see if they exist in a database one at a time at 0.04 seconds a query.
The background of the script is it is a caching script. I need to see if it exists in the DB so I need a true/false (obtained by a rowCount) but i also need a way to relate a false to a value so I can update it. I know using a WHERE tag IN (:ARRAY) would work faster than the individual calls, but I cant think of a way to apply an association of true/false to value in this method.
My current code is below:
//loop through all our values!
//prepare out reusuable statement
$stmt = $db->prepare("SELECT * from cache WHERE value=?");
foreach($values as $tempVal)
{
//find if its in the database
try
{
$stmt->execute(array($tempVal));
$valCount = $stmt->rowCount();
} catch(PDOException $ex) {
echo "PDO error send this to us: " . $ex->getMessage();
}
//update flag
$addToUpdate = 1;
//if its in the database
if($valCount > 0)
{
//get the tag data
$valRes= $stmt->fetch();
//check if cache expired
$addToUpdate = 0;
}
//add to update list
if($addToUpdate)
{
//needs updating
$updateList[] = $tempVal;
//add to not in DB list to minimize queries
if($tagTCount == 0)
{
$notInDB[$tempVal] = $tempVal;
}
}
Any suggestions? I can explain more if anything is not clear.
Thank you,
Nick
So you just issue your query with the complete array, using the IN (?,?,?,?,?...) list:
// abstract, use a PDO wrapper of your choosing
$query = db("SELECT * FROM cache WHERE value IN (??)", $values);
Then iterate over the result list. Only matched $values will return. So build your first list from that:
foreach ($query as $row) {
$updateList[] = $row["value"];
}
To get the list of absent entries, just diff that against your original array:
$notInDB = array_diff($values, $updateList);
You could of course use a second NOT IN query. But doing that differentiation in PHP is simpler.