php and mysql counting amount - php

Im trying to display the amount of a certain pokemon that is in the game by the name of the pokemon and by the type, ( there is two types normal and shiny ) I want it to only grab one type hard to explain... right now its grabing both types and I don't know why here's my code :/
$sql23 = "
SELECT * FROM user_pokemon
WHERE belongsto='". $_SESSION['username']."'AND (slot='1')
";
$result = mysql_query("
SELECT * FROM user_pokemon
WHERE belongsto='". $_SESSION{'username'}."'AND (slot='1')
");
while($row = mysql_fetch_array($result))
{
$sql = "SELECT * FROM pokemon WHERE name='".$row['pokemon']."'";
$result = mysql_query($sql) or die(mysql_error());
$battle_get = mysql_fetch_array($result);
$count = mysql_query("
SELECT count(*) FROM user_pokemon WHERE pokemon='".$row['pokemon']."
'AND type='".$row['type']."'
");
$count2 = mysql_fetch_array($count);
I honestly don't understand why it doesn't work, any help would be appreciated :)
$row['pokemon'] is the name of the pokemon
$row['type'] is the type of the pokemon (shiny, normal, ect..)
user_pokemon table as asked:
Field Type Null Default Comments
-----------------------------------------------------------
id int(11) No
hp int(55) No 30
pokemon varchar(50) No
belongsto varchar(50) No
exp int(50) No 500
item varchar(50) No No Item
nickname varchar(50) No No Nickname
move1 varchar(50) No Ember
move2 varchar(50) No Ember
move3 varchar(50) No Ember
move4 varchar(50) No Ember
slot int(50) No
level int(90) No 5
time_stamp timestamp No CURRENT_TIMESTAMP
gender varchar(25) No Male
type varchar(55) No Normal Type: normal/shiny etc
safari_zone int(10) No 0

One of the things I regularly see on StackOverflow is lack of code formatting. In my view fixing this is a great way to make your code much more readable both to yourself (aids learning) and to others (aids your readers here). It additionally reduces the need for horizontal scrolling, allowing you to place several editors side-by-side on your screen.
Here is your code with suggested code formatting:
$sql23 = "
SELECT
*
FROM
user_pokemon
WHERE
belongsto = '{$_SESSION['username']}'
AND (slot = '1')
";
$result = mysql_query($sql23) or die(mysql_error());
while($row = mysql_fetch_array($result))
{
$sql = "
SELECT * FROM pokemon WHERE name = '{$row['pokemon']}'
";
$result = mysql_query($sql) or die(mysql_error());
$battle_get = mysql_fetch_array($result);
$count = mysql_query("
SELECT
COUNT(*)
FROM
user_pokemon
WHERE
pokemon='{$row['pokemon']}'
AND type='{$row['type']}'
");
$count2 = mysql_fetch_array($count);
}
This helped indicate that your while was missing a closing brace, and that the variable $sql23 wasn't actually used. Also note that you can use array values inline in double-quoted strings, by wrapping them in braces.
As noted in the comments, you should upgrade to PDO or mysqli. Also, be careful about injecting values directly into the SQL if they have come from the user, as this can lead to SQL injection vulnerabilities. Look into query parameterisation, or at least untainting, to ensure your code is safe.

Related

PDO/mysql UPDATE query doesn't do anything or display errors

The code that starts on line 49 is doing absolutely nothing. I have tried to display PHP errors, used try and catch with the PDO set attributes etc, which also didn't display an error.
The code worked before in mysqli when I was using the mysql extension to connect but I'm currently in the process of converting the entire application to PDO.
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
//mysqli_report(MYSQLI_REPORT_ALL);
error_reporting(E_ALL);
ini_set("display_errors", 1);
if(!isset($_SESSION['eid'])){ header("Location: index.php"); } else {
require('dbconn.php');
$sessionuser = $_SESSION['eid'];
$messageid = $_GET['id'];
try{
$db = new PDO($dsn, $db_user, $db_pass);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$sql = "SELECT * FROM messages WHERE id = :messageid";
$rs_result1 = $db->prepare($sql);
$rs_result1->bindParam(":messageid", $messageid);
$rs_result1->execute();
$result1 = $rs_result1->fetch(PDO::FETCH_ASSOC);
$senderid = $result1['eidfrom'];
$recid = $result1['eidto'];
$sql1 = "SELECT * FROM employees WHERE eid = :senderid";
$rs_result2 = $db->prepare($sql1);
$rs_result2->bindParam(":senderid", $senderid);
$rs_result2->execute();
$result2 = $rs_result2->fetch(PDO::FETCH_ASSOC);
$sql2 = "SELECT * FROM employees WHERE eid = :recid";
$rs_result3 = $db->prepare($sql2);
$rs_result3->bindParam(":recid", $recid);
$rs_result3->execute();
$result3 = $rs_result3->fetch(PDO::FETCH_ASSOC);
echo "<table>";
echo "<tr><td>To: </td> <td>".$result3['fname']." ".$result3['lname']."</td></tr>";
echo "<tr><td>From: </td> <td>". $result2['fname'] ." ".$result2['lname']."</td></tr>";
echo "<tr><td>Date: </td><td> ". date("l, jS F Y H:i:s", strtotime($result1['date']))."<br /> </td></tr>";
echo "<tr><td>Subject: </td><td>".$result1['subject']."</td></tr>";
echo "<tr><td colspan='2'><img src =\"images/newssplit.gif\"></td></tr>";
echo "<tr><td>Message: </td><td>". $result1['body']." </td></tr>";
echo "</table>";
//line 49 below
if($sessionuser == $senderid) {
$sql3 = "UPDATE `messages` SET `reads`='1' WHERE `id`= :messageid";
$result4 = $db->prepare($sql3);
$result4->bindParam(":messageid", $messageid);
$result4->execute();
} else {
$sql4 = "UPDATE `messages` SET `read`='1' WHERE `id`= :messageid";
$result5 = $db->prepare($sql4);
$result5->bindParam(":messageid", $messageid);
$result5->execute();
}
} catch (mysqli_sql_exception $e) {
throw $e;
}
}
?>
To say the least I am stuck! I've read many a post on here with people having the same issues, and I don't see anything wrong with the code. What am I missing?
EDIT: So far I have checked the schema to ensure that my fields to actually exist, tried using query(), tried using standard variables rather than bindParam placeholders, The variable $messageid definitely has a value at that stage, as I test printed $sql3 after replacing :messageid with $messageid. I have posted some related files and the export of the schema in a zip ZIP. Haven't come to a solution yet, very stuck on this, as the UPDATE query on line 42 of inbox.php works just fine.
EDIT2: Code above updated with safer select queries, schema has been updated with correct data types and indexes cleaned up. But still what's now on Line 49 will not update the value in messages, OR return an error.
EDIT::SOLVED:
The problem wasn't my query, but my if statement. I hadn't fully tested the functionality of the statement and the queries. What I was doing was testing the queries on a message to and from the same user. An eventuality which I hadn't prepared my if statement for (as it happens the statement and queries combined were working all along for normal user 1 to user 2 and vice versa messages). Here's how I got it to work.
if($sessionuser == $senderid && $sessionuser == $recid) {
$result4 = $db->prepare("UPDATE `messages` SET `read_s`='1', `read_`='1' WHERE `id`= :messageid");
$result4->bindParam(":messageid", $messageid);
$result4->execute();
} elseif($sessionuser == $senderid) {
$result5 = $db->prepare("UPDATE `messages` SET `read_s`='1' WHERE `id`= :messageid");
$result5->bindParam(":messageid", $messageid);
$result5->execute();
} else {
$result6 = $db->prepare("UPDATE `messages` SET `read_`='1' WHERE `id`= :messageid");
$result6->bindParam(":messageid", $messageid);
$result6->execute();
}
I changed the column headers from reads and read, to underscored after reading something about reserved words. But then also found it that it actually didn't matter. Thanks for the help everyone!!! The other notes and feedback that I got regarding the schema etc have helped me learn some good practice!! TYTY
based on your provided zip file in comments
Schema
CREATE TABLE IF NOT EXISTS `employees` (
`eid` int(11) NOT NULL AUTO_INCREMENT,
`fname` varchar(50) NOT NULL,
`lname` varchar(50) NOT NULL,
`dob` varchar(50) NOT NULL, -- why not date datatype?
`sdate` varchar(50) NOT NULL, -- why not date datatype?
`address1` text NOT NULL,
`address2` text NOT NULL,
`city` varchar(50) NOT NULL,
`postcode` varchar(50) NOT NULL,
`telephone` varchar(50) NOT NULL,
`mobile` varchar(50) NOT NULL,
`email` text NOT NULL, -- why text?
`password` varchar(50) NOT NULL, -- I can help you solve this next
`depid` int(11) NOT NULL,
`userlevel` int(11) NOT NULL,
`blocked` int(11) NOT NULL,
PRIMARY KEY (`eid`), -- makes sense
UNIQUE KEY `eid` (`eid`) -- why a duplicate key (as PK) ? you already have it covered
) ENGINE=MyISAM;
truncate table employees;
insert employees(fname,lname,dob,sdate,address1,address2,city,postcode,telephone,mobile,email,password,depid,userlevel,blocked) values
('Frank','Smith','dob','sdate','addr1','addr2','c','p','t','m','e','p',1,2,0);
insert employees(fname,lname,dob,sdate,address1,address2,city,postcode,telephone,mobile,email,password,depid,userlevel,blocked) values
('Sally','Jacobs','dob','sdate','addr1','addr2','c','p','t','m','e','p',1,2,0);
CREATE TABLE IF NOT EXISTS `messages` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`eidto` int(11) NOT NULL,
`eidfrom` int(11) NOT NULL,
`read` int(11) NOT NULL,
`reads` int(11) NOT NULL,
`inbox` int(11) NOT NULL,
`sentbox` int(11) NOT NULL,
`subject` text NOT NULL, -- why a text datatype? was it gonna be huge?
`body` text NOT NULL,
`date` varchar(50) NOT NULL, -- why this data type?
PRIMARY KEY (`id`), -- makes sense
UNIQUE KEY `id` (`id`), -- why this dupe?
KEY `id_2` (`id`) -- why?
) ENGINE=MyISAM;
insert messages(eidto,eidfrom,`read`,`reads`,inbox,sentbox,subject,body,`date`) values
(1,2,1,1,1,1,'subject','body','thedatething');
inbox.php
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
//mysqli_report(MYSQLI_REPORT_ALL);
error_reporting(E_ALL);
ini_set("display_errors", 1);
session_start();
//$sessionuser = $_SESSION['eid'];
$sessionuser = 1;
require('dbconn.php');
try {
$db = new PDO($dsn, $db_user, $db_pass);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // line added
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); // line added
if (isset($_GET["page"])) {
$page = $_GET["page"];
}
else{
$page=1;
};
$start_from = ($page-1) * 10;
$sql = "SELECT * FROM messages WHERE eidto = $sessionuser AND inbox = 1 ORDER BY date DESC LIMIT $start_from, 10";
echo $sql;
$sql2 = "SELECT COUNT(*) FROM messages WHERE eidto = $sessionuser AND inbox = 1 ORDER BY date DESC LIMIT $start_from, 10";
$rs_result = $db->query($sql);
$count = $db->query($sql2)->fetchColumn();
echo "<h3>Inbox</h3>";
echo "<form action='".$PHP_SELF."' method='post'><table><tr><b><td>#</td><td>From</td><td>Subject</td></b></tr>";
while ($row = $rs_result->fetch(PDO::FETCH_ASSOC)) {
$senderid = $row['eidfrom'];
echo "<br>".$senderid;
$messageid = $row['id'];
$result2 = $db->query("SELECT * FROM employees WHERE eid = $senderid");
$row2 = $result2->fetch(PDO::FETCH_ASSOC);
if($row['read'] == 0) {
echo "<tr> <td><input type='checkbox' name='checkbox[]' value='".$row['id']."' id='checkbox[]'></td>";
echo "<td><b>".$row2['fname']." ".$row2['lname']."</b></td>";
echo "<td><b><u><a href='usercp.php?action=messages&f=message&id=".$row['id']."'>".$row['subject']."</a></u></b></td></tr>";
} else {
echo "<tr> <td><input type='checkbox' name='checkbox[]' value='".$row['id']."' id='checkbox[]'></td>";
echo "<td>".$row2['fname']." ".$row2['lname']."</td>";
echo "<td><a href='usercp.php?action=messages&f=message&id=".$row['id']."'>".$row['subject']."</a></td></tr>";
}
};
echo "<tr><td><input type='submit' id='delete' name='delete' value='Delete'></table></form>";
if(isset($_POST['delete'])){
for($i=0;$i<$count;$i++){
$del_id = $_POST['checkbox'][$i];
$sql = "UPDATE `messages` SET `inbox`='0' WHERE `id`='$del_id'";
$result = $db->prepare($sql);
$result->execute();
}
if($result){
echo "<meta http-equiv=\"refresh\" content=\"0;URL=usercp.php?action=messages&f=inbox\">";
}
}
// NEED TO MODIFY CODE BELOW SO THAT PREVIOUS LINK DOESN'T LINK TO PAGE 0 WHEN ON PAGE 1
// AND NEXT DISAPPEARS WHEN ON LAST PAGE WITH RECORDS
$sql = "SELECT * FROM messages WHERE eidto = $sessionuser AND inbox = 1";
$sql2 = "SELECT COUNT(*) FROM messages WHERE eidto = $sessionuser AND inbox = 1";
$rs_result = $db->query($sql);
$rows = $db->query($sql2)->fetchColumn();
if($rows > 10) {
$total_pages = ceil($rows / 10);
echo "<a href='usercp.php?action=messages&f=inbox&page=".($page-1)."'>Previous</a>";
for ($i=1; $i<=$total_pages; $i++) {
echo "<a href='usercp.php?action=messages&f=inbox&page=".$i."'>".$i."</a> ";
}; echo "<a href='usercp.php?action=messages&f=inbox&page=".($page+1)."'>Next</a>";
} else { }
} catch (mysqli_sql_exception $e) {
throw $e;
}
?>
Check for errors. You had a typo on fetchColumn, something error reporting told me.
Add error reporting to the top of your file(s) which will help find errors.
<?php
mysqli_report(MYSQLI_REPORT_ALL);
error_reporting(E_ALL);
ini_set('display_errors', 1);
The Op has said he is re-writing his code to PDO. As such,
You need to switch to PDO with prepared statements for parameter passing to protect against SQL Injection attacks.
By the way, above line and color poached from Fred's great PHP Answers
Note that I added the try/catch block, and a PDO connection exception attribute to support it.
Here is a checklist of things to cleanup:
Move your GETS toward $_POST due to url caching security concerns, and size limitations.
If you haven't, look into hashing and password_verify. Here is An Example I wrote.
Clean up the datatypes and indexes. Comments are seen in your schema.
Move to safe prepared statements as mentioned above.
So, as for functionality given here, the fake data I inserted appears, and the delete works. I am sure you can take it from here.
Edit
Best practice is to choose column names that are not Reserved Words. The ones in that list with an (R) next to them. The use of back-ticks around all column names in queries is a safeguard against query failure in that regard.
As far as your question of why I back-ticked some and not others. It was 3am, those were showing up as red in my query editor, and I was being lazy in not back-ticking all of them.

Check if row exists so user cannot tamper with input

NOTE: I've edit the whole post, trying to make it clearer.
I'm terrible at getting my question clear, but this is my last try.
I got this which gets sent when clicking the button;
echo"Auto/Prijs<br><br><select name='autos'>";
echo"<br><br>";
$sql = "SELECT `garage`.`id`, `car_id`, `schade`, `naam`, `prijs` FROM `garage` LEFT JOIN `cars` ON (`garage`.`car_id` = `cars`.`id`) WHERE `user_id`=".ID." ORDER BY `id` ASC LIMIT ".($page * 10).", 10";
$sql = mysql_query($sql) or die(mysql_error());
$i = 1;
while($res = mysql_fetch_assoc($sql)){
echo"
<option value='".$res['car_id']."'>".$res['naam']."</option><br>
";
This is a dropdown, showing carnames instead of car_id's.
Now, the car_id is not unique, but refers to a car. The 'id' in the 'garage' table IS unique. Am I able to like call the 'id' too, and on sending check if that ID is actually the sent 'car_id'? Because, you can tamper the sent car_id and simply change it.
This happens on sending:
if(isset($_POST['start'])){
$prijs = $_POST['prijs'];
$carr = $_POST['autos'];
$sql = mysql_query("SELECT `id` FROM `automarkt` WHERE `seller_id`=".ID." LIMIT 1") or die(mysql_error());
mysql_query("INSERT INTO `automarkt`(`seller_id`, `prijs`, `car_id`) VALUES (".ID.", ".$prijs.", ".$carr.")") or die(mysql_error());
I'm out of idea's, and can't get clear enough on what I need to do. I need to check if the sent car_id is actually in the 'user''s garage. (Trying to do it by checking the unique entry 'id' in the 'garage' table.
Fixed it by matching rows.
$sql = mysql_query("SELECT `id` FROM `garage` WHERE `car_id`=".$carr." AND `user_id`=".ID) or die(mysql_error());
} elseif(mysql_num_rows($sql) == 0){
$msgs = bad("x");
Thanks for replies.

using LIKE in Sql in PHP web page

I have the code below to search for the text 'english' anywhere in the field language. I've tried formatting the code from SQL into a web PHP page but it doesn't display any information. When I run the sql version select language from media where language like '%english%' it works.
$result = mysql_query("SELECT `language` FROM `media` WHERE `language` LIKE \'%english%\'");
while ($row = mysql_fetch_array($result)) {
echo $row[''];
echo ' ' , $row['language'];
echo '<br />';
}
Don't escape the single quotes around your search term.
$result = mysql_query("SELECT `language` FROM `media` WHERE `language` LIKE '%english%'");
You don't need to escape the ''s. It should just work. So try this:
$result = mysql_query("SELECT `language` FROM `media` WHERE `language` LIKE '%english%'");

retrieve id value from sql database in php which IS NOT last inserted

I have a database that is designed for Football players and so have the table with the following fields:
Person_ID
First_Name
Surname
NicName
Address_Line_1
Contact_Number
Date_of_birth
Postcode
I need to extract the Person_ID for a player without actually entering the ID number as players will not know their individual number and is designed to be used just by the system.
I have the My sql code for selecting a player when certain values are entered:
SELECT `Person_ID` FROM `person` WHERE `First_Name` = 'A Name' and `Surname` = 'Another Name'
This does not however return very well within php when placed into a function. The function I currently have is shown below (php)
function showid($fname, $sname, $d) {
$sql = "SELECT `Person_ID` FROM `person` WHERE `First_Name` = '$fname' and `Surname` = '$sname'";
$result = mysqli_query($d, $sql);
if (!$result)
print ("$sql failed".mysqli_error($d));
else {
print ("$fname $sname is selected<br>");
}
}
$name and $sname are values which will be entered by the user and they will then be able to transfer to a different team or update their account etc but I need to have the ID selected so that further functions and queries can work fully.
If you want to fetch the ID of the selected player, use the fetch_array function
http://php.net/manual/en/mysqli-result.fetch-array.php
function showid($fname, $sname, $d) {
$sql = "SELECT `Person_ID` FROM `person` WHERE `First_Name` = '$fname' and `Surname` = '$sname'";
$result = mysqli_query($d, $sql);
if (!$result)
print ("$sql failed".mysqli_error($d));
else {
print ("$fname $sname is selected<br>");
}
$row = $result->fetch_array(MYSQLI_ASSOC);
echo "Your ID is" . $row['Person_ID'];
}
This of course assumes there is only one result (otherwise we would have to loop) so you might want to check $result->num_rows is equal to 1 and return an error if it isnt (assuming you arent using UNIQUE in your database)

Can these queries be turned into a REPLACE INTO?

$sql2 = "SELECT `id` FROM `saa_game` WHERE `domain_id` = '".$row['id']."' AND `unique_id` = '".s($oGame->unique_id)."' AND `year` = '".$iYear."' AND `month` = '".$iMonth."' LIMIT 1";
$result2 = mysql_query($sql2) or die(mail('rpaiva#golevel.com','SAA Gather Error',mysql_error()));
if(mysql_num_rows($result2) == 1)
{
$row = mysql_fetch_assoc($result2);
$sql3 = "UPDATE `saa_game` SET `plays` = '".s($oGame->plays)."' WHERE `id` = '".$row['id']."' LIMIT 1";
$result3 = mysql_query($sql3) or die(mail('email#sample.com','SAA Gather Error',mysql_error()));
}
else
{
$sql3 = "INSERT INTO `saa_game` (`domain_id`,`type`,`source`,`unique_id`,`plays`,`year`,`month`) VALUES ('".$row['id']."','".s($oGame->type)."','".s($oGame->source)."','".s($oGame->unique_id)."','".s($oGame->plays)."','".$iYear."','".$iMonth."')";
$result3 = mysql_query($sql3) or die(mail('email#sample.com','SAA Gather Error',mysql_error()));
}
I've got this set of queries running 40,000 times on a single page load on a cron job every 10 minutes. This takes so long that it almost runs into the next cron job. If I could reduce this into one query instead of two, that'd be great. (as long as there will actually be a performance difference)
If the select hits all of the right indexes, there won't be a performance increase. In fact, it's likely to be worse! MySQL's REPLACE INTO is implemented as a delete, then an insert!
Consider MySQL's INSERT INTO ... ON DUPLICATE KEY UPDATE instead.
Keep in mind that both of these options are exclusive to MySQL.

Categories