PHP / MySQLI
$query = $conn->query(
"SELECT
cart.cart_id,
cart.user_ip,
cart.cart_amount,
cart.fk_product_id,
products.product_id,
products.prod_amount
FROM
cart
INNER JOIN
products
ON
cart.fk_product_id = products.product_id
WHERE
fk_product_id = '{$productID}' AND user_ip = '{$ip}'
");
$item = $query->fetch_assoc():
$FKproductID = $item['fk_product_id'];
$FKproductID = iSQLsecure($objConnection, $FKproductID);
$FKproductID = trim($FKproductID);
$CartAmount = $item['cart_amount'];
$CartAmount = iSQLsecure($objConnection, $CartAmount);
$CartAmount = trim($CartAmount);
$ProductAmount = $item['prod_amount'];
$ProductAmount = iSQLsecure($objConnection, $ProductAmount);
$ProductAmount = trim($ProductAmount);
$one = 1;
$add_amount = $CartAmount + $one;
$remove_amount = $ProductAmount - $one;
if($FKproductID == $productsID) {
$update_cart_item = $objConnection->query("UPDATE cart SET cart_amount = '{$add_amount}' WHERE fk_product_id = '{$productID}' AND user_ip = '{$ip}'");
$update_product_amount = $objConnection->query("UPDATE products SET prod_amount = '{$remove_amount}' WHERE product_id = '{$productID}'");
} else {
$add_item = $objConnection->query("INSERT INTO cart (user_ip, add_amount, fk_product_id) VALUES ('{$ip}', '{$add_amount}', '{$productID}')");
$update_product_amount = $objConnection->query("UPDATE products SET prod_amount = '{$remove_amount}' WHERE product_id = '{$productID}'");
}
$objConnection->close();
My Problem
$update_product_amount = $objConnection->query("UPDATE products SET prod_amount = '{$remove_ProductAmount}' WHERE product_id = '{$productID}'");
I use this two places if($FKproductID == $productsID) { /*HERE1*/ } else { /*AND HERE2*/}
For some reason it works in "HERE1" but not in "HERE2"?
If item is not in cart
It will insert it into my "cart" database and update "products" amount value. It is supposed to remove 1 from the current product amount (10 becomes 9). Instead it turns 10 into -1.
If item is in cart
It updates perfectly and turns 10 into 9. The code is the exact same but gives two different results?
I'll assume the above code isn't complete, since some variable name is inconsistent ($remove_amount vs $remove_ProductAmount) and yet your code run fine on some case.
For the queries, why don't you just subtract the amount on update query? Something like
UPDATE table SET field = field - 1 WHERE x = y
Even if the number 1 is dynamic, it's safer to generate the number on variables then cast it to integer. On worst case, it would be converted to zero (which can be easily added on your if() as additional validation).
I also recommend using debugger. Something like Kint or PsySH would suffice if you don't want to trouble yourself with setting up XDebug.
I think the issue may be with your INNER JOIN. From what I can tell, if the item isn't in your cart, then the cart.fk_product_id won't exist, and therefore the query will return an empty object.
If you have error display turned off (likely in the php.ini with display_errors = Off), non-existant array keys will be treated as null during equations.
When it comes time to do the equations, php will convert null to integer(0) which results in 0 - 1 = -1 if it fails the if statement.
Have you tried to output the returned object of the query? You can do this by using:
echo "<pre>"; print_r($item); echo "</pre>";
(the <pre> tag makes it a bit more readable).
Also, check the status of your httpd/apache error log if you have log_errors turned on.
Related
I have a query about this project that I am doing, I make a query to my two tables and the data that I call in this case is a quantity number for both, the data displayed is the one that has the same id for both tables.
The problem occurs when I pass two identifiers and to those two identifiers I want to add their current amount with the amount obtained from the other table
In general, what I want to do is add the amounts obtained, this is my code that I am working with, I would really appreciate if you can help me solve it or guide me.
$id_servis = [1077,1078];
$sum_quantity_add = Servis_tareas::where('servis_id',$id_servis)->get();
foreach($sum_quantity_add as $sum_add){
$quantity_two[] = $sum_add->quantity;
}
$quantity_actual = Servis::wherein('id',$id_servis)->get();
foreach($quantity_actual as $quantity_act){
$quantity_one[] = $quantity_act->quantity_final;
}
dd($id_servicios,$quantity_one, $quantity_two);
//ERROR
$total[] = $quantity_one + $quantity_two;
//ERROR
if(is_numeric($total) < 0 ){
Servis::wherein('id',$id_servis)->update(['quantity_final' => 0]);
}else{
Servis::wherein('id',$id_servis)->update(['quantity_final' => $total]);
}
In MySql/SQL there is SUM query which handles the addition and they are called Aggregation Functions, and in Laravel there is a Eloquent equivalent of these Laravel Aggregates, using these methods you will be able to count, max, min, avg on the query end rather than in the PHP end.
So, your code will look like
$id_servis = [1077, 1078];
$sum_quantity_add = Servis_tareas::where('servis_id', $id_servis)->SUM('quantity');
$quantity_actual = Servis::wherein('id', $id_servis)->SUM('quantity_final');
$total = $sum_quantity_add + $quantity_actual;
What you are trying is treating array as numeric value and adding it, which is wrong, + operator behaves totally different while you are using with array, it merges the two array, it is different than array_merge too, so i recommend giving this answer a read + operator for array in PHP
UPDATED:
I still don't understand if you want to replace with the SUM from Servis_tareas in the Servis Table or sum the each others quantity and save it, Code below sum the data from both table and save it.
$id_servis = [1077, 1078];
$servisTareas = Servis_tareas::selectRaw("SUM(`quantity`) as total, `servis_id` ")
->where('servis_id', $id_servis)
->groupBy('servis_id')
->having('total', '>', 0)
->get();
$foundId = [];
$servisTotal = Servis::query()->whereIn('id', $id_servis)->pluck('quantity_final', 'id')->toArray();
foreach ($servisTareas as $servisTarea) {
$foundId[] = $servisTarea->servis_id;
$total = $servisTarea->total + ($servisTotal[$servisTarea->servis_id] ?? 0)
Servis::where('id', $servisTarea->servis_id)->update(['quantity' => $total]);
}
if (!empty($foundId)) {
Servis::whereNotIn('id', $foundId)->update(['quantity' => 0]);
}
I'm creating a basic main menu for a stock market simulator where the price of a company will be updated periodically. For testing purposes, I need to make a loop to display the price of a share on the website five times (with the website automatically updating without refreshing) and to update the database at the same time.
I have successfully wrote some code which will both update the database with the current share price and will also update the website as well. However, when I have tried to include a loop I have come to a problem. I have included a loop to iterate five times but the problem that I am having is that the code continues to iterate even after five tries.
PHP:
<?php
$conn = mysqli_connect("localhost", "root", "", "prices");
if ($conn->connect_error)
{
die("Connection error: ". $conn->connect_error);
}
$result = $conn->query("SELECT `price` FROM `priceTable` WHERE `company` = 'Bawden'");
$x = 0;
if ($result->num_rows > 0)
{
while ($row = $result->fetch_assoc())
{
echo $row['price'];
echo '<br><br>';
echo $x;
if ($x < 5)
{
$random = (rand(3300, 3700) / 100);
$sql = $conn->query("UPDATE `priceTABLE` SET `price` = '$random' WHERE `company` = 'Bawden'");
$x++;
}
}
}
?>
The above code will be displayed in a separate document with Javascript code and I can post this if required in the original post however I originally chose not to as I believe this is a PHP only problem. I have chosen to display $x to see if the value will increment. However, when running, the value of $x will stay at 0.
My expected result is that, on the website, there will only be five different updates and in the database, the database will only be updated five times.
However, my actual result is that the website and database are both continuously being updated, not stopping after five times.
I'm trying to limit the update command to only 5 updates yes. At the
moment, for testing purposes, there is only one company in my database
with one price only. So I'm updating this one company's price five
times
If you need to do the update 5 times for each row returned from the database, change your if statement to a for loop. Change this :-
if ($x < 5)
{
$random = (rand(3300, 3700) / 100);
$sql = $conn->query("UPDATE `priceTABLE` SET `price` = '$random' WHERE `company` = 'Bawden'");
$x++;
}
to this
for ($x = 0, $x < 5, $x++)
{
$random = (rand(3300, 3700) / 100);
$sql = $conn->query("UPDATE `priceTABLE` SET `price` = '$random' WHERE `company` = 'Bawden'");
}
This will repeat the process exactly 5 times and not rely on a separate counter (remove the other references to $x). Not sure why you would want to update the same record 5 times with different random values though.
The else will break the first loop, the second one will stop on the first while loop.
while ($row = $result->fetch_assoc())
{
echo $row['price'];
echo '<br><br>';
echo $x;
if ($x < 5)
{
$random = (rand(3300, 3700) / 100);
$sql = $conn->query("UPDATE `priceTABLE` SET `price` = '$random' WHERE `company` = 'Bawden'");
$x++;
}else{
break;
}
break;
}
What makes you think the loop should stop after 5 iterations?
You need to add the condition $x<5 in the while ($row = $result->fetch_assoc())
Edit following your comment
What you initially wrote is something like loop hundreds of times if need be and do something in the first 5 occurrences (starting loop 6, keep looping but do nothing).
Now for the 2nd half of your comment, I'm not sure what you mean.
What I see in your code is:
Select all prices for company = 'Bawden'
Update all the prices for company = 'Bawden' 5 times (loop) with a random value, the same one, on all the records.
Not enough information to tell for sure but I don't think it makes sense: on one hand, you except to have several records under company = 'Bawden (= reason why you created a loop), on the other hand, your update feels like it is written under the assumption there would be 1 record only...
Are you missing something like a price date from your table? What is the primary key of priceTable?
Try to post more technical details about your table (definition, sample of data) or it will be complicated to help further.
foreach ($_POST as $nazwa_checkboxa=>$id) {
$s = "SELECT uprawnienie FROM user WHERE Id_user=".$id;
$helpdesk = 0;
if ($s == 0) {
$helpdesk = 1;
}
$z = "UPDATE user SET uprawnienie = ".$helpdesk." WHERE Id_user=".$id;
$wynik = $polaczenie->query($z);
$zmienione++;
}
Column uprawnienie return 0 = normal user and 1 = administrator
The update always set value to 1 and I can change user to administrator (0 to 1) but it doesnÄ…t work 1 to 0
Actually, you can do it using one query, e.g.:
update user
set uprawnienie = (SELECT if(uprawnienie=1,0,1) FROM user WHERE Id_user = '<id>')
where Id_user = '<id>'
Looks like you haven't actually run the query() for $s. Therefore, the if ($s==0) is not checking the query results, but rather whether "SELECT..."==0. Per the PHP docs, "Strings will most likely return 0" when cast to integers for such comparisons.
I have a query like this:
$sql = "SELECT * FROM doctors WHERE city ='$city' LIMIT 10 ";
$result = $db->query($sql);
And I show the result like this :
while($row = $result->fetch_object()){
echo $row->city;
}
The Problem :
Mysql , will search through my database to find 10 rows which their city field is similar to $city.
so far it is OK;
But I want to know what is the exact row_number of the last result , which mysql selected and I echoed it ?
( I mean , consider with that query , Mysql selected 10 rows in my database
where row number are:
FIRST = 1
Second = 5
Third = 6
Forth = 7
Fifth = 40
Sixth = 41
Seventh = 42
Eitghth = 100
Ninth = 110
AND **last one = 111**
OK?
I want to know where is place of this "last one"????
)
MySQL databases do not have "row numbers". Rows in the database do not have an inherent order and thereby no "row number". If you select 10 rows from the database, then the last row's "number" is 10. If each row has a field with a primary id, then use that field as its "absolute row number".
You could let the loop run and track values. When the loop ends, you will have the last value. Like so:
while($row = $result->fetch_object()){
echo $row->city;
$last_city = $row->city;
}
/* use $last_city; */
To get the row number in the Original Table of the last resultant (here, tenth) row, you could save the data from the tenth row and then, do the following:
1. Read whole table
2. Loop through the records, checking them against the saved data
3. Break loop as soon as data found.
Like So:
while($row = $result->fetch_object()){
echo $row->city;
$last_row = $row;
}
Now, rerun the query without filters:
$sql = "SELECT * FROM doctors";
$result = $db->query($sql);
$rowNumber = 0;
while($row = $result->fetch_object()) {
if($row == $last_row) break;
$rowNumber++;
}
/* use $rowNumber */
Hope this helps.
What you can do is $last = $row->id; (or whatever field you want) inside your while loop - it will keep getting reassigned with the end result being that it contains the value of the last row.
You could do something like this:
$rowIndex = 0;
$rowCount = mysqli_num_rows($result);
You'd be starting a counter at zero and detecting the total number of records retrieved.
Then, as you step through the records, you could increment your counter.
while ( $row = $result->fetch_object() ) {
$rowIndex++;
[other code]
}
Inside the While Loop, you could check to see whether the rowIndex is equal to the rowCount, as in...
if ($rowIndex == $rowCount) {
[your code]
}
I know this is a year+ late, but I completely why Andy was asking his question. I frequently need to know this information. For instance, let's say you're using PHP to echo results in a nice HTML format. Obviously, you wouldn't need to know the record result index in the case of simply starting and ending a div, because you could start the div before the loop, and close it at the end. However, knowing where you are in the result set might affect some styling decisions (e.g., adding particular classes to the first and/or last rows).
I had one case in which I used a GROUP BY query and inserted each set of records into its own tabbed card. A user could click the tabs to display each set. I wanted to know when I was building the last tab, so that I could designate it as being selected (i.e., the one with the focus). The tab was already built by the time the loop ended, so I needed to know while inside of the loop (which was more efficient than using JavaScript to change the tab's properties after the fact).
At this time I have this very complex query that I loop through and I get something like this:
List of Challenges:
TEAM A
- Challenge 1
TEAM A
- Challenge 4
TEAM A
- Challege 6
And I want to change to something like:
TEAM A
- Challenge 1
- Challenge 4
- Challenge 6
My question is, since the query is a very complex one, maybe I could do this inside the loop but, if that's the case, how can we achieve something like that?
Can I ask an example case so that I can use, in order to solve this issue?
Thanks a lot,
MEM
UPDATE:
The query is something like this:
Translated:
public function listachallengesPendentes()
{
$select = $this->getAdapter()->select();
$select->from(array("e"=>"teams"),array('name'));
$select->join(array("de"=>"challengeperteam"),"e.cod_team = de.cod_teamFk",array());
$select->join(array("d"=>"challenges"),"d.cod_challenge = de.cod_challengeFk",array('title'));
$select->columns(array("e.cod_team"
,"name_team"=>"e.name"
,"d.cod_challenge"
,"name_challenge"=>"d.title"
,"d.details"
,"d.score"
,"category"=>"d.cod_categoryFk"
,"de.proof"
,"de.date_concluded"
,"de.cod_challenge_team"
));
$select->where("de.status = 0");
$select->order(array('e.cod_team DESC', 'de.cod_challenge_team DESC'));
return $this->getAdapter()->fetchAll($select);
}
So I need to add a distinct some part :s :D ?
The foreach actually is pretty basic:
foreach ($challenges as $d){
//display the name:
echo $d['name_team'];
...
}
UPDATE 2
The clean query (not tested):
SELECT e.name
,d.cod_team
,d.cod_challenge
,d.title
,d.details
,d.score
,de.proof
,de.date_concluded
,de.cod_challenge_team
FROM teams e
INNER JOIN challengeperteam de ON de.cod_teamFk = e.cod_team
INNER JOIN challenges d ON d.cod_challenge = de.cod_challengeFk
WHERE de.status = 0
ORDER BY e.cod_team DESC, de.cod_challenge_team DESC;
Something along the lines of:
$current_team = null;
foreach($challenges as $challenge){
if($current_team != $challenge->team){
$current_team = $challenge->team;
echo $current_team, "\n";
}
echo $challenge->challenge_name, "\n";
}
At a very basic level, ie in the loop, you can just detect if the TEAM A variable is equal to the current (previous) value, and if so, don't print it a second time. This relies on the result set being sorted on the TEAM A column.
However, you can also do this in the SQL query, so if you can provide the current SQL Query, I can explain how you'd update it.
you could store the array results in a multi-dimensional array like so:
$query_Challenges = "SELECT `Team`,`Challenges` FROM YourTable";
$Challenges = mysql_query($query_Challenges, $dbconnection) or die(mysql_error());
$row_Challenges = mysql_fetch_assoc($Challenges);
$challengeResults = array();
do{
if(!array_key_exists($row_Challenges['cod_team'])){
$challengeResults[$row_Challenges['cod_team']] = array();
}
$challengeResults[$row_Challenges['cod_team']][] = $row_Challenges['cod_challenge_team'];
}while($row_Challenges = mysql_fetch_assoc($Challenges));
EDIT
looking at your query statement, the data should be already sorted properly by your ORDER clause, so if you just need not repeatedly print the team as shown in codeblock 2, then something like:
$team = '';
do {
if($team != $row_Challenges['cod_team']){
echo "TEAM $row_Challenges['cod_team']<br/>";
$team = $row_Challenges['cod_team'];
}
echo " - $row_Challenges['cod_challenge_team']<br />";
}while($row_Challenges = mysql_fetch_assoc($Challenges));
you could easily substitute a foreach for the do loop, as long as there is a variable used as the "current team" and an if statement used to say "dont print the next team name unless its different than the current team name"