I made this script which is giving me a lot of troubles. I'm not so good at MySQL and maybe I'm trying to do stuff too advanced for my knowledge of SQL, but I would really really really like to make this work.
My php script is:
<?PHP
$getusername=$_GET['user'];
$getpassword=$_GET['pass'];
$getworldname=$_GET['worldname'];
$getblock=$_GET['block'];
$getpos=$_GET['pos'];
$user_name = "asdasdasd";
$password = "asdasd";
$database = "asdasd";
$server = "localhost";
$db_handle = mysql_connect($server, $user_name, $password);
$db_found = mysql_select_db($database, $db_handle);
$SQL="SELECT * FROM accounts WHERE username='$getusername' and password='$getpassword'";
$result=mysql_query($SQL);
$count=mysql_num_rows($result);
if($count==1){
$blockstring=$getpos.'/'.$getblock.'|';
$SQL="SELECT LOCATE('$getpos', blocks) FROM worlds WHERE name='$getworldname'";
$result=mysql_query($SQL);
$count=mysql_num_rows($result);
echo $count;
//if there's already that block
if ($result!=0){
$posUnknown='|'.$getpos.'/';
$posKnown='|'.$getpos.'/'.$getblock;
$SQL="UPDATE worlds SET blocks=replace(blocks,concat('$posUnknown',substring_index(substring_index(blocks, '$posUnknown', 2), '|', 1),'|'),'$posKnown') WHERE name='$getworldname'";
$result=mysql_query($SQL);
}else{
$SQL="UPDATE worlds SET blocks=CONCAT(blocks,'$blockstring') WHERE name='$getworldname'";
$result=mysql_query($SQL);
}
print 'OK';
}else{
print 'NO';
}
?>
I'm sure I made some mistake, also big ones into the queries, but sadly I can't figure out what I'm doing wrong.
An example of the content of blocks could be:
x10y20z30/0|x999y1231z30/1|x3330y4444z0/99999|etc
What this script does, well, what I wanted it to do is:
Check username and password, and that works luckily,
check if the given block already exists in "blocks"
if it does exist replace the value (the one after the /) of the
already existing block with the new one,
if it doesn't exist just add it to "blocks".
But it doesn't work and I know why. I know it's because of the SQL, but I can't figure out how to make it work.
You have some serious issues with your code's security, as pointed out in a comment. I have done what I can without really changing what your code is doing:
<?PHP
$getusername=$_GET['user'];
$getpassword=$_GET['pass'];
$getworldname=$_GET['worldname'];
$getblock=$_GET['block'];
$getpos=$_GET['pos'];
$user_name = "asdasdasd";
$password = "asdasd";
$database = "asdasd";
$server = "localhost";
You should be using mysqli, not mysql:
$db = new mysqli($server, $user_name, $password, $database);
All input needs to be escaped before it is used in a query with real_escape_string:
$SQL="SELECT * FROM accounts WHERE username='" . $db->real_escape_string($getusername) . "' and password='" . $db->real_escape_string($getpassword) . "'";
$result=$db->query($SQL);
$count=$result->num_rows;
if($count==1) {
$blockstring=$getpos.'/'.$getblock.'|';
$SQL="SELECT LOCATE('" . $db->real_escape_string($getpos) . "', blocks) FROM worlds WHERE name='" . $db->real_escape_string($getworldname) . "'";
$result=$db->query($SQL);
$count=$result->num_rows;
echo $count;
//if there's already that block
if ($count!=0) {
$posUnknown='|'.$getpos.'/';
$posKnown='|'.$getpos.'/'.$getblock;
This is probably where you're having trouble, because it looks like you're storing all of this information in a single row:
$SQL="UPDATE worlds SET blocks=replace(blocks,concat('" . $db->real_escape_string($posUnknown) ."',substring_index(substring_index(blocks, '" . $db->real_escape_string($posUnknown). "', 2), '|', 1),'|'),'" . $db->real_escape_string($posKnown) . "') WHERE name='" . $db->real_escape_string($getworldname). "'";
$result=$db->query($SQL);
} else {
$SQL="UPDATE worlds SET blocks=CONCAT(blocks,'" . $db->real_escape_string($blockstring) ."') WHERE name='" . $db->real_escape_string($getworldname) . "'";
$result=$db->query($SQL);
}
print 'OK';
} else {
print 'NO';
}
?>
Since all of your block information is being shoved together in a single column, your database is not normalized at all and appears to be like this:
Worlds
name blocks
Your database should probably be structured a lot more like this:
Worlds
id | name
---------------
1 | demoworld
Blocks
id | WorldID | x | y | z | data
-----------------------------------------
1 | 1 | 10 | 20 | 30 | 0
2 | 1 | 999 | 1231 | 30 | 1
3 | 1 | 33330 | 4444 | 0 | 99999
You can recreate the data layout you provided when you query the data, and when someone tries to add something like x20y30z40/12345, you can parse that to get the x, y, z, and data portions.
Related
Table 1 (Which needs to be updated)
+-----------------+
|name |qty |
+-----------------+
|area | 1 |
|length | 2 |
|breadth | 3 |
|width | 4 |
+-----------------+
Table Which needs to be fetched for what values and rows have to be update
+-------------------------------------+
|name | upd_qty | Cart_id | cid |
+-------------------------------------+
|area | 6 | 12 | 1 |
|length | 8 | 20 | 2 |
|breadth | 11 | 34 | 3 |
+-------------------------------------+
How can i do this using php. Help me with this please.
this is the code i have used for my original work. Table 1 & Table 2 have name in common and conditions are
1 . UPDATE should done for the rows which are fetched from table to with where condition.
2. Table 2 upd_qty will be updated in table 1 qty while fetching data from table 2 where condition.
$con=mysqli_connect("localhost","root","","medical");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
error_reporting(E_ALL ^ E_NOTICE);
$query = "SELECT * FROM cart WHERE cid='$id' AND 'cart'='$cart_id'";
$result = $con->query($query);
while($row = $result->fetch_assoc()) {
$mediname = $row['name'];
$mediqty = $row['upd_qty'];
for($i=0;$i<$count;$i++){
$sql="UPDATE stock SET qty='$mediqty' WHERE name='$mediname' AND
'cart'='$cart_id'";
if (!mysqli_query($con,$sql))
{
die('Error: Failed' . mysqli_error($con));
}
I don't think you need this line:
for($i=0;$i<$count;$i++){
There's already a "while fetch" loop.
Also, don't use single quotes around identifiers, use backticks if the identifier needs to be escaped.
With this:
... AND 'cart' = ...
'cart' will be evaluated a string literal, not a column reference.
With this
... AND `cart` = ...
cart is an identifier, a reference to a column.
Also, if we can't use prepared statements with bind placeholders, at a minimum, we use mysqli_real_escape_string to mitigate SQL Injection vulnerabilities
Also, there's a confusing mix of procedural style and objected oriented style calls...
procedural style
mysqli_query($con,$sql)
mysqli_error($con)
object oriented style
$con->query($query)
$result->fetch_assoc()
I recommend you choose one style or the other, and stick to that pattern.
$query = "SELECT * FROM cart WHERE `cid` = '"
. $con->real_escape_string($id)
. "' AND `cart` = '"
. $con->real_escape_string($cart_id)
. "'";
$result = $con->query($query);
if( !$result ) {
die('Error: ' . $con->error());
}
while( $row = $result->fetch_assoc() ) {
$mediname = $row['name'];
$mediqty = $row['upd_qty'];
$sql="UPDATE stock SET `qty` = '"
. $con->real_escape_string($mediqty)
. "' WHERE `name` = '"
. $con->real_escape_string($mediname)
. "' AND `cart` = '"
. $con->real_escape_string($cart_id)
."'";
if(!$con->query($sql) ) {
die('Error: Failed' . $con->error());
}
}
EDIT
If there's not a specific reason for the loop, if the goal is just to perform the UPDATE operation and there is not other logic or conditions, we can do the UPDATE in one statement, without a need for multiple query executions:
UPDATE cart c
JOIN stock s
ON s.cart = c.cart
AND s.name = c.name
SET s.qty = c.upd_qty
WHERE c.cid = ?
AND c.cart = ?
Personally, I would just do the one UPDATE statement using a prepared statement
// connect to mysql
$con = new mysqli(...)
if( $con->connect_error ) {
die( 'Connect error: ' . $con->connect_error );
}
// update statement
$sql = '
UPDATE cart c
JOIN stock s
ON s.cart = c.cart
AND s.name = c.name
SET s.qty = c.upd_qty
WHERE c.cid = ?
AND c.cart = ? ';
$sth = $con->prepare($sql);
if(!$sth) {
die( 'Prepare error: ' . $con->error() );
}
$sth->bind_param('ii',$id,$cart_id);
if(!$sth->execute()) {
die( 'Execute error: ' . $con->error() );
}
Code worked for me for what i want exactly is :
$con=mysqli_connect("localhost","root","","medical");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
error_reporting(E_ALL ^ E_NOTICE);
$query = "SELECT * FROM cart WHERE cid='$id' AND cart='$cart_id'";
$result = $con->query($query);
while($row1 = $result->fetch_assoc())
foreach ($result as $row1){
$sql="UPDATE stock SET qty='$row1[upd_qty]' WHERE name='$row1[name]'";
if (!mysqli_query($con,$sql))
{
die('Error: Failed' . mysqli_error($con));
}
}
I ran into a problem with strange behavior of mysqli_query. There's a foreach-loop to update table rows but the update for the last loop doens't get written to the database (all the other updates get written successfully). There's no error and mysqli_affected_rows returns 1 as it should. The code pases through till the end, confirmed by an echo-statement after mysqli_query.
I tried to loop trough an array with only one element and the same problem.
What's going on here? Does anyone ran into the same problem?
OK...here's the significant part of the code, the whole code isn't possible cause there maximum 30000 characters allowed. I also echoed out the sql-string and everything is perfect. But as I said the update for the last loop (the last time when the loop is beeing executed) doesn't get written to the MySQL-DB.
$sql_getRelations = "SELECT id_machine, device_id, serial_number, variant_id, company_id, last_file FROM view_machines "
. "WHERE company_id NOT IN ('" . implode( '\',\'' , $btc_companies) . "') "
// . "AND id_machine = 158 "
. "AND device_type_id = 4 AND machine_status = 'active' "
. "ORDER BY id_machine ASC;";
$result_relations = mysqli_query($db_ed, $sql_getRelations);
$relations_arr = mysqli_fetch_all($result_relations, MYSQLI_ASSOC);
mysqli_free_result($result_relations);
foreach($relations_arr as $machine){
//...some other code here
$sql_update_device = "UPDATE device SET last_file = '" . $str_max_ts . "' WHERE id_device = " . $machine['device_id'] . ";";
$update_device = mysqli_query($db_ed, $sql_update_device);
if (!$update_device) {
error_log("\r\n" . date("Y-m-d H:i:s") . ': !!!!Updatefehler device: ' . $machine['device_id'] . ": " . mysqli_error($db_ed), 3, "C:/xampp/htdocs/cronjob/error_log.txt");
}
echo $machine['id_machine'] . ', ';
}
mysqli_close($db_ed);
I would perform debugging like the following to a text file. Wedge your data collection in the outer loops then rem that out and zero in on inner chunks. A divide and conquer strategy.
I would have tried to get my head into your email php but it is 675 lines of one foreach block :p
PHP:
<?php
//mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
mysqli_report(MYSQLI_REPORT_ALL);
error_reporting(E_ALL); // report all PHP errors.
ini_set("display_errors", 1);
echo "start<br/>";
// $file="/home/nate/debug123.txt";
$file="c:\\nate\\debug123.txt";
date_default_timezone_set('America/New_York');
$debugStr=date('Y-m-d H:i:s').": Start";
file_put_contents($file, $debugStr."\n", FILE_APPEND | LOCK_EX);
try {
$mysqli= new mysqli('localhost', 'theUser', 'thePassword', 'theDB_Name');
if ($mysqli->connect_error) {
die('Connect Error (' . $mysqli->connect_errno . ') '
. $mysqli->connect_error);
}
echo "I am connected and feel happy.<br/><br/>";
$query = "INSERT INTO `t921`(`thing`,`uniqueNum`,`views`) values ('aaa',577,0)"; // change that 577 each time else it fails unique
echo $query."<br>";
$mysqli->query($query);
$debugStr=date('Y-m-d H:i:s').": Affected rows: " .$mysqli->affected_rows.", Insert id: ".$mysqli->insert_id;
echo $debugStr."<br><br>";
file_put_contents($file, $debugStr."\n", FILE_APPEND | LOCK_EX);
$query = "UPDATE `t921` SET `views`=`views`+1 WHERE id=1";
echo $query."<br>";
$mysqli->query($query);
$id=1;
$debugStr=date('Y-m-d H:i:s').": UPDATE id=".$id.", Affected rows: " . $mysqli->affected_rows;
echo $debugStr."<br><br>";
file_put_contents($file, $debugStr."\n", FILE_APPEND | LOCK_EX);
$query = "UPDATE `t921` SET `views`=`views` WHERE id=1";
echo $query."<br>";
$mysqli->query($query);
$id=1;
$debugStr=date('Y-m-d H:i:s').": UPDATE id=".$id.", Affected rows: " . $mysqli->affected_rows;
echo $debugStr."<br><br>";
file_put_contents($file, $debugStr."\n", FILE_APPEND | LOCK_EX);
$mysqli->close();
} catch (mysqli_sql_exception $e) {
throw $e;
}
?>
Sample log file (debug123.txt):
2016-09-19 18:23:57: Start
2016-09-19 18:23:57: Affected rows: 1, Insert id: 27
2016-09-19 18:23:57: UPDATE id=1, Affected rows: 1
2016-09-19 18:23:57: UPDATE id=1, Affected rows: 0
Note the last update stmt was meant to change no data thus affected=0
Schema:
create table t921
( id int auto_increment primary key,
thing varchar(100) not null,
uniqueNum int not null,
views int not null,
unique key(uniqueNum)
);
This may seem like a bit of an odd request, but it's important that I get this working. It's for a game i'm making. So basically, my users have their own accounts on my website. I have different plans that they can select and each plan costs a different amount every month.
What I want to do is have 4 seperate PHP crons that automatically subtract a certain amount from their accounts each month based on the plan they have selected. For example, if a user has the "Ultimate" plan, and currently has $1,049.99 in their account, I want it to subtract 49.99 from the "balance" row in the database, and then update the table to 1000.00 (as it has subtracted the plan amount).
At registration, the database is loaded with the value "chargeday" which is basically the day of the month that the user registered. I want the cron to run every day (which I know how to do) and only run this code if the current day equals the chargeday listed on the database. (I've been running this code with the if ($chargeday == date("d")) { and } lines removed.
I've tried the following but I can't get it to work the way I want:
<?php
$servername = "localhost";
$username = "myusername";
$password = "mypassword";
$dbname = "advenaio_myaccount";
$chargeday = date("d");
if ($chargeday == date("d")) {
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT email, plan, balance FROM advaccounts WHERE plan='ultimate'";
$result = $conn->query($sql);
$ultimateplan = "49.99";
$currentbalance = $row['balance'];
$newbalance = $currentbalance-$ultimateplan;
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
echo "plan: " . $row["plan"]. "<br>balance: " . $row['balance'] . "<br>new balance: " . $newbalance . "<br>email address: " . $row['email'] . "<br><br> ";
}
} else {
echo "0 results";
}
$sql = "UPDATE advaccounts SET balance=$newbalance WHERE plan='ultimate'";
if ($conn->query($sql) === TRUE) {
echo "Record updated successfully";
} else {
echo "Error updating record: " . $conn->error;
}
$conn->close();
?>
I'm sorry if my question doesn't make sense, I just really need this to work and I'm sort of desperate for it to work. Here is the structure of the database:
id_user | name | email | domain | username | password | plan | balance | joindate | chargeday | substatus | cic
you can use below sql to update the balance directly using one sql. No need to write php logic.
$sql = "UPDATE advaccounts SET balance=balance-49.99 WHERE plan='ultimate' and chargeday = '" . date('d'). "'";
I have two tables in a database. In reports I am storing info for reports and in report_roles I am assigning which user can access the report.
reports
+--+-----------+---------------+
|id|report_name|report_filename|
+--+-----------+---------------+
|13|Report 1 |reportname1 |
|14|Report 2 |reportname2 |
|15|Report 3 |reportname3 |
+--+-----------+---------------+
report_roles
+---------+-------+
|report_id|user_id|
+---------+-------+
|14 |1 |
|13 |1 |
|14 |2 |
|13 |2 |
+---------+-------+
I want to display all the reports from table reports with checkboxes and check only those which are added in the report_roles associated with the user id. This is the code I am running:
$id = $_POST['user_id'];
$query = "SELECT * FROM reports LEFT JOIN report_roles ON report_roles.report_id = reports.id";
$sql = mysqli_query($mysqli, $query);
if (!$sql) {
printf("Error: %s\n", mysqli_error($mysqli));
exit();
}
while($row = mysqli_fetch_array($sql, MYSQLI_ASSOC) ) {
if ($row['user_id'] == $id) {
echo "<input type='checkbox' name='" . ($row['id']) . "'" . "id='" . ($row['id']) . "'" . "value='yes'" . ($row['user_id'] == $id ? 'checked' : '') .">";
echo $row['report_name'];
} else {
echo "<input type='checkbox' name='" . ($row['id']) . "'" . "id='" . ($row['id']) . "'" . "value='yes'" . ">";
echo $row['report_name'];
}
}
If $id = 1 I am receiving this:
|checked| Report2 |checked| Report 1 |unchecked| Report2 |unchecked| Report 1 |unchecked| Report3
Which is completely right based on the code I wrote. I cannot figure out how to display all the reports without duplicates from reports table and check only those which are available in report_roles, something like this:
|checked| Report2 |checked| Report 1 |unchecked| Report3
I am sure I have to change my query with the join. Tried to do accomplish this task with two separate queries without joins but with no luck. Hope someone can help.
Actually I was just missing a statement in my query and thanks to Bernd Buffed I realized that I have to add one AND at the end of the query and it should look like this:
$query = "SELECT * FROM reports LEFT JOIN report_roles ON report_roles.report_id = reports.id AND user_id = $id";
Till now I was adding WHERE user_id = $id and was receiving only those reports which exists in report_roles. With the AND I am receiving all reports from reports table and my script can check only those which are in report_roles based on a simple php check.
So to better explain what I'm doing,
I'm trying to use php to query 1 table
Look if row 1 named "Site" matches my query
Then post the results of the entire column results
So I need to change my while statement to an if statement. Just a bit fuzzy on how to write it up so that it only posts every column that matches my query.
$con=mysqli_connect("$host", "$username", "$password","$db_name");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$result = mysqli_query($con,"SELECT * FROM table");
while($info = mysqli_fetch_array($result))
{
echo " | ".$info['site']. " | " .$info['asset']. " | " .$info['hostname']. " | " .$info['sys_name']. " | ". $info['ip']. " | ";
echo "<br>";
}
The wildcard in SQL is %. Everything before VANCOOVER or after it will be overlooked when VANCOOVER is written as %VANCOOVER%. In PHP, LIKE %$Search%
SELECT * FROM table WHERE site LIKE '%VANCOOVER%'