AddItem function does not seem to be working - php

I go this thing to sorta work but my AddItem function doesn't seem to work. I click the "add item" link on the products page and it takes me to the cart page. But nothing is on the cart page. I am hoping somoneone can see it and tell me what to do to correct it.
The AddItem function:
function AddItem($itemId, $qty) {
// Will check whether or not this item
// already exists in the cart table.
// If it does, the UpdateItem function
// will be called instead
// Check if this item already exists in the users cart table
$result = mysql_query("select count(*) from cs368_cart where cookieID = '" . GetCartID() . "' and itemId = $itemId");
$row = mysql_fetch_row($result);
$numRows = $row[0];
if($numRows == 0) {
// This item doesn't exist in the users cart,
// we will add it with an insert query
mysql_query("insert into cs368_cart(cookieID, itemId, qty) values('" . GetCartID() . "', $itemId, $qty)");
}
else {
// This item already exists in the users cart,
// we will update it instead
UpdateItem($itemId, $qty);
}
}
I just checked my cs368_cart tables of the database and it is empty.
mysql> select * from cs368_cart
-> ;
Empty set (0.00 sec)
So apparently nothing is being added. I am wondering if my query is correct?
My tables:
mysql> select * from cs368_products
-> ;
+--------+----------------+---------------------------------------------+-----------+
| itemId | itemName | itemDesc | itemPrice |
+--------+----------------+---------------------------------------------+-----------+
| 1 | French Vanilla | A medium blend with a hint vanilla | 9.79 |
| 2 | Hazelnut Cream | A light blend with a spicy note of Hazelnut | 9.69 |
| 3 | Columbian | A medium-dark blend straight up | 9.89 |
+--------+----------------+---------------------------------------------+-----------+
3 rows in set (0.00 sec)
and my cart tables;
mysql> show columns from cs368_cart;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| cartId | int(11) | NO | PRI | NULL | auto_increment |
| cookieId | varchar(50) | NO | | | |
| itemId | int(11) | YES | | NULL | |
| qty | int(11) | YES | | NULL | |
+----------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
This is my GetCartId I have in a seperate php file which is bieng called correctly by the php file with this AddItem function.
function GetCartId(){
if(isset($_COOKIE["cartId"])){
return $_COOKIE["cartId"];
}
else {
session_start();
setcookie("cartId", session_id(), time()+((3600*24)*30));
return session_id();
}

It looks like you are trying to insert cartId as a string when your table has cartId as an integer. Take a closer look at your SQL in the PHP strings.

You should change your insert query to something similar to below which will tell you what is wrong with your insert sataement (also it is good practice to handle any errors gracefully)
<?php
$queryResult = mysql_query("insert into cs368_cart(cookieID, itemId, qty) values('" . GetCartID() . "', $itemId, $qty)");
if (!$queryResult) {
die('Invalid query: ' . mysql_error());
}
?>
based on example in http://php.net/manual/en/function.mysql-query.php

Related

using one key to multiple values in php

I'm developing a webaplicattion in php where there will be an area called 'My Products'. This area you can see the products that you listed. Lets say you placed a car to sell. You will have something like:
Model: R8
Color: Yellow
Brand: Audi
Type: Diesel
Price: 90000
CarID: 1
My problem: How can I select the carid so that I have the cardid as the key and the other values (eg. model, color, etc...) as values?
I'm using mysql to store the listings. SQL TABLE:
+---------+------------------------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+------------------------------------------+------+-----+---------+----------------+
| carid | int(11) | NO | MUL | NULL | auto_increment |
| brand | enum('Alfa Romeo','Aston Martin','Audi') | NO | | NULL | |
| color | varchar(20) | NO | | NULL | |
| type | enum('gasoline','diesel','eletric') | YES | | NULL | |
| price | mediumint(8) unsigned | YES | | NULL | |
| mileage | mediumint(8) unsigned | YES | | NULL | |
| model | text | YES | | NULL | |
| year | year(4) | YES | | NULL | |
| user | varchar(30) | YES | | NULL | |
+---------+------------------------------------------+------+-----+---------+----------------+
My pseudo code is something like this:
Fetch ID of the cars that was listed by certain user;
Use that ID as a key;
Get every other options to be the values (diesel, yellow, etc...)
I have tried some codes since array_combine to foreach inside foreach.
This is the code I have ended up so far:
$qry_id = "select carid from cars where user='$login'";
if ($car_id = mysqli_query($link, $qry_id)){
while ($row = mysqli_fetch_assoc($car_id)){
//It will fetch the iD of the user in the DB
$user_id = $row["carid"];
$qry_model = "select model from cars where carid='$user_id'";
if($model_obj = mysqli_query($link, $qry_model)){
while ($row_2 = mysqli_fetch_assoc($model_obj)){
$model = $row_2['model'];
$final_array = array($user_id => $model);
}
}
}
}
I don't know if this is the right approach since it's my first webapp I'm building.
I'm just using the model value in this code for the simplicity sakes.
$q = "SELECT * FROM cars where user=?";
if ($stmt = $pdo->preapre($q)){
$result=[];
$stmt->execute([$login]);
while ($row = $stmt->fetchObject()){
$carId = $row->carid;
unset($row->carid);
$result[$carId]=$row;
}
}
now note that $pdo is object of pdo connecttion to the database not mysqli, you can do the same thing with mysqli but i am not uses to it
also i don't recommend that you use the user name on every column you should instead store the userId as foreign key to the primary key id in the table user
that will save alot more storage make the query faster ( it's easier to look for numbers than string ) and user can change it's name without having to change his name in all other tables ( userid won't be changing of course )
also carid should be unsigned int(10) not int(11) if wondering why 10 see that post MySQL datatype INT(11) whereas UNSIGNED INT(10)?
To avoid SQL injection, use prepared statements. You can use one query to fetch all attributes for the cars:
$qry_id = "select carid, model, price, color from cars where user=?";
$stmt = mysqli_prepare($link , $qry_d) or die("SQL statement error");
// Bind the login parameter to the statement
mysqli_stmt_bind_param($stmt, "s", $login);
mysqli_stmt_execute($stmt);
// bind every column in the SELECT
mysqli_stmt_bind_result($stmt, $user_id, $carid, $model, $price, $color);
while (mysqli_stmt_fetch($stmt)){
$final_array[] = array(
"model" => $model,
"price" => $price,
"color" => $color
);
}
You may do the following
Note this query is not safe and pron to SQL Injection, I would recommend to use prepared statements or PDO
The $carArray variable will finally have the array with carid as key in it
$query = "select * from cars where user='$login'";
$result = mysqli_query($query);
$carArray = array();
while ($row = mysqli_fetch_assoc($result)){
$carArray[$row['carid']] = $row;
}

loops in PHP MYSQL to insert accumulated data from one table to new one

I have a table like this:
id | order_id | code |
1 | 2200 | 489512444756 |
2 | 2200 | 489512444756 |
3 | 2200 | 489512444777 |
4 | 2200 | 489512444777 |
5 | 2200 | 489512444777 |
6 | 2201 | 489512444788 |
7 | 2201 | 489512444788 |
8 | 2201 | 489512444777 |
I'm trying to use for loops to fill another table in MySQL with accumulated data (aggregate the codes to provide qty) with the following columns:
id | order_id | code | qty |
The PHP code used to do this as the following:
mysql_select_db($database, $server);
$query_Recordset1 = "SELECT `order_id` FROM stock GROUP BY order_id ";
$Recordset1 = mysql_query($query_Recordset1, $beharserver) or die(mysql_error());
while ($row_orders = mysql_fetch_assoc($Recordset1)){
foreach ($row_orders as $ord) {
$query_Recordset2 = "SELECT `order_id`, code, COUNT(id) AS qty FROM stock WHERE `order_id` = '".$ord."' GROUP BY code";
$Recordset2 = mysql_query($query, $server) or die(mysql_error());
$row_orders2 = mysql_fetch_assoc($Recordset2);
foreach ($row_orders2 as $itm) {
$insert_qty = "INSERT INTO orders_agg (order_id, code, qty) VALUES ( '".$itm[0]."','".$itm[1]."','".$itm[2]."' )";
$qty = mysql_query($insert_qty, $server) or die(mysql_error());
}
}
}
The code above is not working well, and inserted data in new table are different from what exactly required.
The inserted data looks like this:
id | order_id | code | qty |
1 | 3 | 6 | 0 |
etc...
You should use one SQL statement to do all work. It is:
INSERT INTO orders_agg
(SELECT NULL, `order_id`, code, COUNT(*) AS qty FROM stock
GROUP BY order_id, code)
I'll guess that the problem is that your code is not inserting values into the second table.
You'll need to reference the result values from the array by name -- e.g. $itm['order_id'], $itm['qty'], etc.

SQL updating tables recursively with PHP

I have a conversation table and conversation reply table:
conversation table:
+-------+-------+--------+
| cid | u_1 | uid_2 |
+-------+-------+--------+
| 1 | 8 | 3 |
| 2 | 8 | 5 |
| 3 | 8 | 2 |
+-------+-------+--------+
conversation_reply table:
+-------+-------+--------+--------+
| cr_id | reply | uid_fk | cid_fk |
+-------+-------+--------+--------+
| 1 | | 8 | 1 |
| 2 | | 8 | 11 |
| 3 | | 8 | 11 |
+-------+-------+--------+--------+
I need to be able to update the conversation table with a new record if one doesn't exist when a new reply is created, however I get the following error:
Cannot add or update a child row: a foreign key constraint fails
(`_db`.`conversation_reply`, CONSTRAINT `conversation_reply_ibfk_2`
FOREIGN KEY (`cid_fk`) REFERENCES `conversation` (`cid`))
Any help much appreciated!!!!
EDIT
I have put the convo reply query into the create new convo query, it will create a new convo but still doesn't insert the reply:
if (!empty($_GET['conv_id'])) {
$cid = mysql_real_escape_string($_GET['conv_id']);
echo $cid;
}
if($user_one!=$user_two){
// Check convo doesn't already exist.
$q_exist= mysql_query("SELECT c_id FROM mc_conversation WHERE (user_one='$user_one' and user_two='$user_two') or (user_one='$user_two' and user_two='$user_one') ") or die(mysql_error());
if(mysql_num_rows($q_exist)==0) {
$query = mysql_query("INSERT INTO mc_conversation (user_one,user_two,ip,time) VALUES ('$user_one','$user_two','$ip','$time')") or die(mysql_error());
$q=mysql_query("SELECT c_id FROM mc_conversation WHERE user_one='$user_one' ORDER BY c_id DESC limit 1");
$v=mysql_fetch_array($q);
return $v['c_id'];
$v_cid = $v['c_id'];
// Insert reply.
$qR= mysql_query("INSERT INTO mc_conversation_reply (user_id_fk,reply,ip,time,c_id_fk) VALUES ('$uid','$reply','$ip','$time','$v_cid')") or die(mysql_error());
// Convo already exists.
} else {
$v=mysql_fetch_array($q_exist);
return $v['c_id'];
// Insert reply
$qR= mysql_query("INSERT INTO mc_conversation_reply (user_id_fk,reply,ip,time,c_id_fk) VALUES ('$uid','$reply','$ip','$time','$cid')") or die(mysql_error());
echo $cid;
}
}
You have called "return" in your else loop, which will end execution of the function, or if called from the global scope, execute the current script.
http://php.net/manual/en/function.return.php
Try this:
// Insert reply
$v=mysql_fetch_array($q_exist);
$qR= mysql_query("INSERT INTO mc_conversation_reply (user_id_fk,reply,ip,time,c_id_fk) VALUES ('$uid','$reply','$ip','$time','$cid')") or die(mysql_error());
echo $cid;
From the code that you have posted I think the problem is with the return statement.
The reply is not getting inserted because you have
return $v['c_id'];
before the INSERT query code. And if this code is inside a function, it will just return the value and not execute any further line.
You should have the return statement at the very end of the function / after doing all required operations. If it is for debugging purpose, you can use echo statement.

multilevel menu item deletion recursion function

I want to delete category from multilevel menu with recursion function. To understand situation more carefully , lets take a look first at mysql table structure
CREATE TABLE IF NOT EXISTS menu(
id INT(5) NOT NULL AUTO_INCREMENT PRIMARY KEY,
p_id INT(5),
sort_id INT(5) NOT NULL,
title VARCHAR(50) CHARSET utf8 COLLATE 'utf8_unicode_ci' NOT NULL,
);
it looks like this when it is retrieved
id | p_id | sort_id | title |
1 | 0 | 1 | root1 |
2 | 1 | 1 | sub of root1
3 | 0 | 2 | root2 |
4 | 2 | 1 | sub of "sub of root1"
... | ... | ... | ....
etc ...
I've written php script for delete category, here it is =>
function del_cat($connection,$id){
if (!$connection->connect_errno){
if ($connection->set_charset("utf8")){
if ($r = $connection->query("SELECT id FROM menu WHERE p_id=" . $id . "")){
if ($r->num_rows>0){
while ($row = $r->fetch_assoc()){
del_cat($connection,$row['id']);
}
} else {
$connection->query("DELETE FROM menu WHERE id=" . $id . "");
}
$r->free();
}
}
}
}
$connection variable is a just mysql connection object, and $id is id in table.
It works just fine when I'm deleting one row ( I mean when category doesn't have a child , sub categories), for example 1 | 0 | 1 | root1 |, but when I want to delete for example 4 | 2 | 1 | sub of "sub of root1" it doesn't delete category with sub categories . Any idea how to solve this problem ? thanks
The delete is only in else so you never actually delete the parent category. I think you need something like:
del_cat($connection, $row['id']);
$connection->query("DELETE ...");
} else {
$connection->query("DELETE ...");
By the way you should escape the ID input.

need advice on mysql normalization and php class structure

i am trying to build a system that logs, media (photo, video, audio) upload statistic. so i come up with 3 tables, 1 for audio, 1 for video, and 1 for photo. and here's the structure
+-----------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| member_id | int(10) | NO | | NULL | |
| counter | int(11) | NO | | NULL | |
| daydate | text | NO | | NULL | |
| epochtime | text | NO | | NULL | |
+-----------+---------+------+-----+---------+----------------+
all three tables has the same fields, since i think (so far) i need to differentiate the medias on each and particular table, is this redundant ??
anyway since each of the media is treated the same, so i think i should only build once class and kinda use the methods depending of what media i am accessing at the time. here's the class :
require_once(INC_PATH.DS.'database.php');
class Log extends DatabaseObject {
protected static $db_fields = array('id', 'member_id', 'counter', 'daydate', 'epochtime');
public $id;
public $member_id;
public $counter;
public $daydate;
public $epochtime;
public function find_counter($table_name){
global $database;
$time = date('d-m-Y');
$timestamp = time();
$sql = "SELECT * FROM ". $table_name;
$sql .= " WHERE daydate = '".$this->daydate."'";
$sql .= " AND member_id = '".$this->member_id."'";
return self::find_by_sql($sql);
}
public function add_log($table_name){
global $database;
$tes = $this->find_counter();
if(!empty($tes)){
$sql = "UPDATE ".$table_name;
$sql .= " SET counter = counter+1";
$sql .= " WHERE daydate = '".$this->daydate."'";
$sql .= " AND member_id = '".$this->member_id."'";
$database->query($sql);
return ($database->affected_rows() == 1) ? true : false;
}else{
$sql = "INSERT INTO ".$table_name;
$sql .= " (id, member_id, user_privelege, counter, daydate, epochtime)";
$sql .= " VALUES ('', '".$this->member_id."'";
$sql .= " , '".$this->user_privelege."', '1', '".$this->daydate."', '".$this->epochtime;
$sql .= "')";
$database->query($sql);
return ($database->affected_rows() == 1) ? true : false;
}
}
}
so far this is pretty much working but, i still have doubts on the way i break the table in to 3 tables, and the way i use the $table_name as parameter. any suggestions for better approach ?? i really want to improve my codes, thank you very much
Regards
UPDATE
alright, based on everybody's answer, i would like to clear somethings up:
i only need to log the uploaded media
i already have another separate table to record other information (length, filename, titles, etc) for each media.
lets just say i add a field called "media_id" and merge the table into one, and since the way that i add and update my rows is based on the day-date, it will INSERT if the given daydate and the member_id is not found, and otherwise it will UPDATE, i think i should also change the way my add_log() method works, into something like:
public function add_log($table_name, $media_id){
global $database;
$tes = $this->find_counter();
if(!empty($tes)){
$sql = "UPDATE ".$table_name;
$sql .= " SET counter = counter+1";
$sql .= " WHERE daydate = '".$this->daydate."'";
$sql .= " AND member_id = '".$this->member_id."'";
$sql .= " AND media_id = '".$media_id."'";
$database->query($sql);
return ($database->affected_rows() == 1) ? true : false;
}else{
$sql = "INSERT INTO ".$table_name;
$sql .= " (id, member_id, media_id, counter, daydate, epochtime)";
$sql .= " VALUES ('', '".$this->member_id."'";
$sql .= " , '".$media_id."', '1', '".$this->daydate."', '".$this->epochtime;
$sql .= "')";
$database->query($sql);
return ($database->affected_rows() == 1) ? true : false;
}
}
what do you guys think ??
thanks again
Put it all in one table and have a media_type column.
+-----------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| member_id | int(10) | NO | | NULL | |
| counter | int(11) | NO | | NULL | |
| daydate | text | NO | | NULL | |
| epochtime | text | NO | | NULL | |
| media_type| int | NO | | NULL | |
+-----------+---------+------+-----+---------+----------------+
Create a foreign key relationship to another table that defines media_type.
+-----------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+----------------+
| media_type_id| int | NO | PRI | NULL | |
| description | text | NO | | NULL | |
+-----------+---------+------+-----+---------+----------------+
This would hold media_type_id (e.g. 1) and media_type_description (e.g. audio).
e.g.
1, audio
2, video
3, photo
The main table would then just include on each row the id of 1, 2, 3 to denote which media type it is. You can then use this from your application to constrain via the WHERE clause, which media you're referring to. e.g. SELECT * FROM maintable WHERE media_type_id = 3 to just get the photos.
Make it one table with an extra column "media_type". Your design would require you to make an extra table for every new media type and that is possibly poor design.

Categories