need advice on mysql normalization and php class structure - php

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.

Related

How to update data as null in mysql using php loop?

I have a table named users with a column called user_subs. It looks like this.
In user_subs I have stored the specific users session username. Lets say this specific users name is James.
Now how would I loop through a specific user_subs looking for "James" and remove him from that specific user_subs without removing all the other names.
This is what I have so far and the only problem is, its deleting all the usernames in user_subs instead of just "James".
if(isset($_GET['p_id'])) {
$the_post_id = $_GET['p_id'];
$the_post_author = $_GET['author'];
}
if(isset($_POST['delete_sub'])) {
$username = $_SESSION['username'];
$query = "SELECT user_subs FROM users WHERE username = '{$username}' ";
$select_users_by_id = mysqli_query($connection, $query);
while ($row = mysqli_fetch_array($select_users_by_id)) {
$user_subs = explode(',', $row['user_subs']);
foreach($user_subs as $out) {
$query = "UPDATE users SET user_subs = null WHERE username = '{$the_post_author}' ";
$unsubscribe_user = mysqli_query($connection, $query);
echo "Unsubscribed";
}
}
}
THIS IS JUST IN TEST, PREPARED STATEMENTS WILL BE USED BEFORE GOING LIVE
Thank you for your time.
I second the other user's comment about moving this column to a different table. In the meanwhile, if you want to achieve what you are asking for, you can try removing the user name from the column value and update it with the remaining text.
if(isset($_POST['delete_sub'])) {
$username = $_SESSION['username'];
$query = "SELECT user_subs FROM users WHERE username = '{$username}' ";
$select_users_by_id = mysqli_query($connection, $query);
while ($row = mysqli_fetch_array($select_users_by_id)) {
$user_subs = str_replace($username . ',', '', $row['user_subs']);
$query = "UPDATE users SET user_subs = '{$user_subs}' WHERE username = '{$the_post_author}' ";
$unsubscribe_user = mysqli_query($connection, $query);
echo "Unsubscribed";
}
}
OPTION-2
$user_subs = explode(',', $row['user_subs']);
$user_subs_new = [];
foreach($user_subs as $out) {
if ($out !== $username) {
$user_subs_new[] = $out;
}
}
$user_subs = implode(',',user_subs_new);
$query = "UPDATE users SET user_subs = '{$user_subs}' WHERE username = '{$username}' ";
$unsubscribe_user = mysqli_query($connection, $query);
echo "Unsubscribed";
}
Let's start over. Let's start here, in fact...
DROP TABLE IF EXISTS users;
CREATE TABLE users
(user_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,email VARCHAR(20) NOT NULL UNIQUE
);
DROP TABLE IF EXISTS user_subs;
CREATE TABLE user_subs
(user_id INT NOT NULL
, sub_id INT NOT NULL
, active TINYINT NOT NULL DEFAULT 1
, PRIMARY KEY(user_id,sub_id)
);
INSERT INTO users VALUES
(1,'b.smyth634#gmail.com'),
(2,'james#gmail.com'),
(3,'f#gmail.com'),
(4,'sally#gmail.com'),
(5,'thomas#gmail.com');
INSERT INTO user_subs (user_id,sub_id) VALUES
(1,5),
(1,2),
(1,1),
(1,4),
(2,1),
(2,2),
(2,4);
SELECT * FROM users;
+---------+----------------------+
| user_id | email |
+---------+----------------------+
| 1 | b.smyth634#gmail.com |
| 2 | james#gmail.com |
| 3 | f#gmail.com |
| 4 | sally#gmail.com |
| 5 | thomas#gmail.com |
+---------+----------------------+
SELECT * FROM user_subs;
+---------+--------+--------+
| user_id | sub_id | active |
+---------+--------+--------+
| 1 | 5 | 1 |
| 1 | 2 | 1 |
| 1 | 1 | 1 |
| 1 | 4 | 1 |
| 2 | 1 | 1 |
| 2 | 2 | 1 |
| 2 | 4 | 1 |
+---------+--------+--------+
SELECT u.*
, GROUP_CONCAT(us.sub_id) subs
FROM users u
JOIN user_subs us
ON us.user_id = u.user_id
GROUP
BY u.user_id;
+---------+----------------------+---------+
| user_id | email | subs |
+---------+----------------------+---------+
| 1 | b.smyth634#gmail.com | 1,2,4,5 |
| 2 | james#gmail.com | 1,2,4 |
+---------+----------------------+---------+
From here we have a choice. We can either DELETE subs we no longer wish to consider, or simply UPDATE them as 'inactive'.
Either way, we just need a DELETE or an UPDATE. So no SELECT needed. In fact a SELECT would, as I mentioned, be counterproductive - because a user may modify the data set in between the execution of the SELECT and the execution of the UPDATE/DELETE. This is known as a 'race condition'.

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;
}

PDO inserts an id as 0 for some reason

So I wrote this method, for my chrome plugin (which does an ajax request to run this method), and when it runs, file_put_contents shows an id of what ever was inserted, but then when it gets to the insert ignore into songs, it puts in 0 for the artist_id. I have no idea why... Can someone help my find the part where I am going wrong?
<?php
public function saveLyrics($artist, $title, $lyric){
$this->db->query("insert ignore into artists (artist_name) value (:artist)", array("artist" => $artist));
$artist_id = (int)$this->db->insertID();
file_put_contents(__DIR__ . "/../process/page", "artist id: $artist_id");
//return;
if($artist_id == 0){
$artist_id = (int)$this->db->getOne("select artist_id from artists where artist_name = :artist", array("artist" => $artist));
}
if($artist_id == 0){
return false;
}
$this->db->query("insert ignore into songs (artist_id, song_name) values (:aid, :title)", array("aid" => $artist_id, "title" => $title));
$song_id = (int)$this->db->insertID();
if($song_id == 0){
$song_id = (int)$this->db->getOne("select song_id from songs where artist_id = aid and song_name = :title", array("aid" => $artist_id, "title" => $title));
}
}
PDO Wrapper:
<?php
/**
* #property PDO $pdo Description
* #property PDOStatement $sql Description
*/
class DB{
protected $sql = null;
protected $pdo = null;
public function connect(){
$this->pdo = new PDO("mysql:dbname=envne;host=xxx", "xxx", "xxx");
}
public function query($query, $params = array()){
if($this->pdo === null){
$this->connect();
}
$this->sql = $this->pdo->prepare($query);
foreach($params as $key => $value){
$this->sql->bindParam($key, $value);
}
$this->sql->execute();
if(!$this->sql)
return false;
return true;
}
public function insertID(){
return (int)$this->pdo->lastInsertId();
}
public function getAll($query, $params = array()){
$this->query($query, $params);
return $this->sql->fetchAll();
}
public function getOne($query, $params = array()){
$this->query($query, $params);
return $this->sql->fetchColumn();
}
}
Artists:
mysql> describe artists;
+-------------+------------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+-------------------+----------------+
| artist_id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| artist_name | char(50) | YES | UNI | NULL | |
| add_date | timestamp | YES | | CURRENT_TIMESTAMP | |
+-------------+------------------+------+-----+-------------------+----------------+
3 rows in set (0.00 sec)
Songs:
mysql> describe songs;
+------------+------------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------------+------+-----+-------------------+----------------+
| song_id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| artist_id | int(11) unsigned | YES | MUL | NULL | |
| album_id | int(11) | YES | MUL | NULL | |
| song_name | char(50) | YES | | NULL | |
| track_id | int(11) | YES | | NULL | |
| date_added | timestamp | NO | | CURRENT_TIMESTAMP | |
+------------+------------------+------+-----+-------------------+----------------+
6 rows in set (0.01 sec)
I just decided to put the Id directly into the query, and that works.
$artist_id = (int)$this->db->insertID();
$this->db->query("insert ignore into songs (artist_id, song_name) values ($artist_id, :title)", array("title" => $title));
Another way that works is using a question mark instead
$artist_id = (int)$this->db->insertID();
$this->db->query("insert ignore into songs (artist_id, song_name) values (?, ?)", array($artist_id, $title));
I just had the same problem : new inserted items get an id of 0 even though the ID field is set to AUTO_INCRIMENT.
The solution I found is very similar to yours. Using your code this is what we get :
$this->db->query("insert ignore into songs (artist_id, song_name) values (LAST_INSERT_ID(), :title)", array("title" => $title));
As you can see, I replaced $artist_id = (int)$this->db->insertID(); and $artist_id with SQL function LAST_INSERT_ID().
I hope this can help someone someday :)
You're placeholders are incorrectly defined: (You're missing the colons)
I would do something like this:
public function saveLyrics($artist, $title, $lyric){
$this->db->query("insert ignore into artists (artist_name) value (:artist)", array(":artist" => $artist));
$artist_id = (int)$this->db->insertID();
file_put_contents(__DIR__ . "/../process/page", "artist id: $artist_id");
//return;
if($artist_id == 0){
$artist_id = (int)$this->db->getOne("select artist_id from artists where artist_name = :artist", array(":artist" => $artist));
return false;
}
$this->db->query("insert ignore into songs (artist_id, song_name) values (:aid, :title)", array(":aid"=>$artist_id, ":title"=>$title));
$song_id = (int)$this->db->insertID();
if($song_id == 0){
$song_id = (int)$this->db->getOne("select song_id from songs where artist_id = :aid and song_name = :title", array(":aid"=>$artist_id, ":title"=>$title));
}
}
Taking a look at your PDO-wrapper you have this code:
if(!$this->sql)
return false;
Because of this you would never notice an actual error. I guess the error is about the placeholder in this case.
(If $this->db->query("insert ignore into songs (... fails $song_id would just be false if there is an error when executing the query).
Use exceptions instead and catch the errors, that would be better.
I also noticed that:
$song_id = (int)$this->db->insertID();
would cast the value twice, first in above code and then in the actual function insertID() in the PDO-Wrapper. Maybe this is an issue also to consider.

PHP mysql LEFT JOIN output

I have php-script running on top of apache. Every time when user goes to specific URL, he/she will get csv-file.
Column names are fetched like this (thanks to Daniel Figueroa :)
$csv_output .= "\n";
// get the column name from the first DB (ins.data)
mysql_select_db($db, $link) or die("Can not connect to DB1.");
$result = mysql_query("SHOW COLUMNS FROM ".$table." WHERE Field NOT IN
('ID','Key','Text')");
$i = 0;
if (mysql_num_rows($result) > 0) {
while ($row = mysql_fetch_assoc($result)) {
$csv_output .= $row['Field']."; ";
$i++;
}
}
// get the column names from the second DB (Cu.data)
mysql_select_db($db2, $link) or die("Can not connect to DB2.");
$result = mysql_query("SHOW COLUMNS FROM ".$table2." ");
;
$i = 0;
if (mysql_num_rows($result) > 0) {
while ($row = mysql_fetch_assoc($result)) {
$csv_output .= $row['Field']."; ";
$i++;
}
}
$csv_output .= "\n";
Actual query on PHP-script goes like this:
$values = mysql_query(" SELECT ins.data.`Date`, ins.data.`Number`,
ins.data.`Email`, ins.data.`TargetId`, ins.data.`CSW`,
ins.data.`TSW`, ins.data.`CType`,
Cu.data.`Cus`, Cu.data.`Co`,Cu.data.`Ci`,
Cu.data.`SID`, Cu.data.`SType`
FROM ins.data
LEFT JOIN Cu.data ON (ins.data.TargetId = Cu.data.TargetID)
ORDER BY ins.data.ID DESC");
Output of 'desc':
mysql> desc ins.data;
+-------------------+------------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+------------------+------+-----+---------------------+----------------+
| ID | int(10) unsigned | NO | PRI | NULL | auto_increment |
| Date | timestamp | NO | | 0000-00-00 00:00:00 | |
| Number | text | NO | | NULL | |
| Text | text | NO | | NULL | |
| Email | text | NO | | NULL | |
| TargetId | varchar(20) | NO | | NULL | |
| CSW | text | NO | | NULL | |
| TSW | text | NO | | NULL | |
| Key | text | NO | | NULL | |
| CType | text | NO | | NULL | |
+-------------------+------------------+------+-----+---------------------+----------------+
10 rows in set (0.00 sec)
mysql> desc Cu.data;
+----------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| Title | decimal(15,0) | NO | | NULL | |
| Cu | text | NO | | NULL | |
| Co | text | NO | | NULL | |
| Ci | text | NO | | NULL | |
| SID | text | NO | | NULL | |
| TargetID | varchar(20) | NO | MUL | NULL | |
| SType | text | NO | | NULL | |
| empty1 | int(11) | NO | | NULL | |
| empty2 | int(11) | NO | | NULL | |
| empty3 | int(11) | NO | | NULL | |
| empty4 | int(11) | NO | | NULL | |
| empty5 | int(11) | NO | | NULL | |
| empty6 | int(11) | NO | | NULL | |
| empty7 | int(11) | NO | | NULL | |
+----------+---------------+------+-----+---------+-------+
12 rows in set (0.00 sec)
UPDATE 3:
This is no more NATURAL LEFT JOIN-issue. Replaced with LEFT JOIN.
Added fields empty1-5 to ins.data to get data to csv-file. Without fields empty1-5, only data from first db (ins.data) was on csv.file.
Now i have data on all fields but field (or column names on excel) names on csv are on wrong order and not wanted fields (columns) are visible like Title and empty1-5.
Any ideas how to fix this? Some other way to get Field names to csv-file without "SHOW COLUMNS"?
I could write with 'echo' in the beginning of csv-file values what i want. ie
"Date; Number; Email; TargetID, CSW; TSW; CType; Cu; SID; Co; Ci; SType;" but i am so newbie with PHP that i don't know how :(
Another issue is that if field ID is first column on excel, excel cannot handle that and it must be excluded from SHOW COLUMNS output.
UPDATE4: Added more empty-fields to DB2 (Cu.data) and reordered SQL-query, now all values are visible and on right order.
EDIT
First of all, your table naming schema is weird and unusual... but assuming I understand it correctly then this query should work (if it does not then rename your tables without the dots (periods) to make things less confusing:
mysql_query('SELECT ins.data.Date, ins.data.Number, ins.data.Email, ins.data.TID, ins.data.CSW, ins.data.TSW, ins.data.CType, CU.data.SID, cu.data.SType, cu.data.CU, cu.data.CO, cu.data.Ci, FROM ins.data, cu.data ORDER BY ins.data.ID DESC');
According to to the mysql_query function reference, data should not end with a semicolon when using mysql_query in PHP... i never put the semicolon in there so I don't ever have a problem, that's what I initially noticed with your script (as I said i've never tried it so I don't know if thats the issue). Should be:
$values = mysql_query("SELECT Date, Number, Email, TID, CSW, TSW, CType, SID, SType, Cu, Co, Ci FROM ins.data NATURAL LEFT JOIN Cu.data ORDER BY ID DESC");
Also, when doing JOINS, usually you specify what column belongs to what table... like in the standard mysql example here:
<?php
// Make a MySQL Connection
// Construct our join query
$query = "SELECT family.Position, food.Meal ".
"FROM family LEFT JOIN food ".
"ON family.Position = food.Position";
$result = mysql_query($query) or die(mysql_error());
// Print out the contents of each row into a table
while($row = mysql_fetch_array($result)){
echo $row['Position']. " - ". $row['Meal'];
echo "<br />";
}
?>
I don't always use the JOIN commands either... you can use an alternative syntax like so:
mysql_query('SELECT ... FROM t1, t2, t3 WHERE t1.b = t2.b AND t2.c = t3.c AND t1.a = t3.a');
Try putting aliases on table names. It will make the query more readable, too:
SELECT
i.`Date`, i.Number, i.Email, i.TID, i.CSW, i.TSW, i.CType,
c.Cu, c.Co, c.Ci, c.SID, c.TID, c.SType
FROM
ins.data AS i
LEFT JOIN
Cu.data AS c
ON i.TID = c.TID
ORDER BY
i.ID DESC ;

AddItem function does not seem to be working

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

Categories