EDIT: The plugin in question is located here.
PHP beginner here using a JQuery Star Rating snippet and have gotten it to work perfectly. My problem is that it is currently configured to count and display the average of many ratings (for public applications). I'm trying to simplify the plugin so that it allows one to set a personal rating (as if rating your own songs in iTunes). The user may update their rating, but no partial stars would ever exist. I've broken the plugin many times trying to get it working, but to no avail. The mysql database exists as follows:
CREATE TABLE IF NOT EXISTS `pd_total_vote` (
`id` int(11) NOT NULL auto_increment,
`desc` varchar(50) NOT NULL,
`counter` int(8) NOT NULL default '0',
`value` int(8) NOT NULL default '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
If I can get it working the way I imagine, I wouldn't require both the counter and value columns, simply a single INT column that holds a value between 1 and 5. Currently counter accumulates the number of votes, while value aggregates the ratings. The stars are then displayed using (value/counter)*20 (as a percentage). The PHP is below (original):
<?php
// connect to database
$dbh=mysql_connect ("localhost", "user", "pass") or die ('Cannot connect to the database');
mysql_select_db ("thenally_pd",$dbh);
if($_GET['do']=='rate'){
rate($_GET['id']);
}else if($_GET['do']=='getrate'){
// get rating
getRating($_GET['id']);
}
// get data from table
function fetchStar(){
$sql = "select * from `pd_total_vote`";
$result=#mysql_query($sql);
while($rs = #mysql_fetch_array($result,MYSQL_ASSOC)){
$arr_data[] = $rs;
}
return $arr_data;
}
// function to retrieve
function getRating($id){
$sql= "select * from `pd_total_vote` where id='".$id."' ";
$result=#mysql_query($sql);
$rs=#mysql_fetch_array($result);
// set width of star
$rating = (#round($rs[value] / $rs[counter],1)) * 20;
echo $rating;
}
// function to set rating
function rate($id){
$text = strip_tags($_GET['rating']);
$update = "update `pd_total_vote` set counter = counter + 1, value = value + ".$_GET['rating']." where id='".$id."' ";
$result = #mysql_query($update);
}
?>
Thanks for a point in the right direction,
Mike
I am unsure as I have no access to the rating system you are using yet just glancing at what you have I guess you could keep the counter set to 1 (if removing it breaks the jQuery Rating System) and have the value updated by the person so when you fetch it they only see their value (make sure value can't go above 5). That way if the value is set to 5 then it will show 5 because it isn't finding other ratings.... (based on my understanding) You will also have to add a user id so you know which persons rating to fetch (since you want it personal). This depends on how dependent the application is a specific database design.
Related
I have a question about the update function in mysqli.
For school, I'm trying to create a click counter for my website which counts how many times a user has visited a certain page.
So far I've come up with this:
<?php
/*
* ToDo: Check why number of clicks goes back to two when completely
* refreshing page.
*
*/
include("init.php");
session_start();
//Count variable
$clicks = 0;
//Query for checking if there are any entry's in the database
$query = "SELECT * FROM `beoordelingen`.`clickcounter` WHERE `game_id`={$id}";
$result = $conn->query($query);
//If query returns false
if (!mysqli_num_rows($result)) {
//Create entry in database
$insert = "INSERT INTO `beoordelingen`.`clickcounter` (`ID`, `game_id`, `clicks`) VALUES (NULL, '1', '1');";
$createEntry = $conn->query($insert);
}
//If query returns true
else {
//Setting the number of clicks equal to $clicks
while ($data = $result->fetch_assoc()) {
$clicks = $data['clicks'];
}
//Insert new number into database
$sql="insert into `clickcounter` set `clicks`='{$clicks}', `game_id`='{$id}'
on duplicate key update
`clicks`=`clicks`+1;";
$insertInto = $conn->query($sql);
//Echo current number of clicks
echo $clicks;
}
?>
The actual problem is that my update statement doesn't seem to work properly. If anyone would be able to spot why it doesn't work I'd be very happy.
The database is as following;
Beoordelingen <- Database
clickcounter <- Table which has the following three columns:
1. ID
2. game_id
3. clicks
The scripts does add an entry into the databse with click count 2. So when I reload the page it says 2. And when refreshing it counts up, but doesn't update the table.
Thanks! If anything is unclear please ask me!
Theoretically you should be able to do all of it in one query if game_id is unique.
Given the following table structure the sql query below will insert if the relevant record does not exists and then update if it does.
create table `clickcounter` (
`id` int(10) unsigned not null auto_increment,
`game_id` int(10) unsigned not null default '0',
`clicks` int(10) unsigned not null default '0',
primary key (`id`),
unique index `game_id` (`game_id`)
)
engine=innodb;
The trick is setting the indices on your table correctly ~ initially you don't know the value of the ID and I would guess that is an auto increment primary key? So, set a unique key on game_id...I hope it helps!
/* Could even change `clicks`='{$clicks}' to `clicks`=1 in initial insert */
$sql="insert into `clickcounter` set `clicks`='{$clicks}', `game_id`='{$id}'
on duplicate key update
`clicks`=`clicks`+1;";
<?php
include("init.php");
session_start();
/* Where / how is "$id" defined? */
/* insert new record / update existing */
$sql="insert into `clickcounter` set `clicks`=1, `game_id`='{$id}'
on duplicate key update
`clicks`=`clicks`+1;";
$result = $conn->query( $sql );
/* retrieve the number of clicks */
$sql="select `clicks` from `clickcounter` where `game_id`='{$id}';";
$result = $conn->query( $sql );
while( $rs=$result->fetch_object() ) $clicks=intval( $rs->clicks );
echo 'Total clicks: '.$clicks;
?>
I'm trying to obtain the max primary key in the REDES table in order to add one but it's not working. I was also wondering if this would be the best way to do it and if it's secure.
// mysql inserting a new REDES field
//$redes_maxid = mysql_query("SELECT MAX(id_redessociales) AS id FROM REDES");
//$newmaxid = $redes_maxid + 1;
$redes_maxid = mysql_fetch_row(mysql_query("SELECT max(id_redessociales) AS id FROM REDES"));
$newmaxid = $redes_maxid[0] + 1;
mysql_query("INSERT INTO REDES(id_redessociales, facebook, twitter, linkedin, pinterest) VALUES ('$newmaxid', NULL, NULL, NULL, NULL");
Thanks!
What you're doing is very unsafe and wrong.
This is why we have auto increment fields in databases, just set the id field in your table to auto increment then when inserting a new row simply pass in NULL for the id, MySQL it will automatically do this increment for you safely.
here's a link to the documentation
You can get last id by ordering in descending order and limiting 1 row result
replace this line
$redes_maxid = mysql_fetch_row(mysql_query("SELECT max(id_redessociales) AS id FROM REDES"));
with
$redes_maxid = mysql_fetch_row(mysql_query("SELECT id_redessociales AS id FROM REDES order by id_redessociales DESC limit 1"));
exactly what A.B said
But shouldn't you be making the ID's row in the database auto incremented?
you can set it to auto increment and when you insert a record just make the inserted ID NULL, the database will automaticly number it to the last ID+1
if you are ysing mySql then you can use this SQL statement
ALTER TABLE `myTable` CHANGE `id` `id` TINYINT( 3 ) PRIMARY KEY UNSIGNED NOT NULL AUTO_INCREMENT
Problem: I want to connect two tables files and counter according to the paper_id column from files table connecting with the visitors column from counter table.
There are two pages; publicationView.php and profile.php.
When a reader clicks publicationView.php, php code should count the view of the page according to the publication id and only update using session.
When a user visits his profile.php, then he can see his publications in a table with the publications' views relatively.
There are two tables; files where all the publications are and counter where the counter are. I am trying to update using the URI of the publication and the URI is saved in counter table.
Implementation:
The publicationView.php includes
$webpage=htmlspecialchars($_SERVER["REQUEST_URI"]);
$sql = "CREATE TABLE IF NOT EXISTS counter (
id int(4) NOT NULL auto_increment,
webpage varchar(90) NOT NULL,
visitors int(11) NOT NULL default '1',
PRIMARY KEY (id)
) ENGINE=MyISAM AUTO_INCREMENT=1";
mysql_query($sql);
$result=mysql_query("SELECT * FROM counter WHERE webpage='$webpage'");
$num_rows = mysql_num_rows($result);
if ($num_rows == 0){
mysql_query("INSERT INTO counter (id, webpage, visitors)
VALUES ('','$webpage','1')");
}else{
if (!isset($_SESSION['webpage'])){$_SESSION['webpage'] = 0;
mysql_query("UPDATE counter SET visitors=visitors+'1' WHERE webpage='$webpage'");}}
The profile.php includes
The code to echo our the visitors column from counter table.
Change '1' to simply 1 in,
if (!isset($_SESSION['webpage'])){$_SESSION['webpage'] = 0;
mysql_query("UPDATE counter SET visitors=visitors+'1' WHERE webpage='$webpage'");}}
Change it to
if (!isset($_SESSION['webpage'])){$_SESSION['webpage'] = 0;
mysql_query("UPDATE counter SET visitors=visitors+1 WHERE webpage='$webpage'");}}
I have a question if anyone can answer. Please excuse my inexperience with this, but this is my first project that I have attempted and all of this is really new to me. I am in the process of trying to build an inventory system at work using php and mySQL and I have hit a bit of a wall regarding how I am going to display the items that are currently loaned out to people.
I have the items that are being provisioned to users broken down into 4 categories and records of the loans for these items are stored into 4 different tables. I also have another table for users, as well as tables for the items, and their characteristics.
What I want when my page is displayed to to have all of the items that are assigned to each user grouped together in a table. I have two ideas on how I can do this, but I'm not sure which would be the best way.
My first thought was to pull all of the users from the users table and store the information into an array, then pull all of the information from the 4 loan tables and store each table into an array. From there I would do something like
for($i=1;$i>sizeof($usersArray);$i++){
for($a=1;$a>sizeof($loanTable1Array);$a++){
if($userArray[$i][userID] == $loanTable1Array[$a][userID]{
//list items
}
}
for($b=1;$b>sizeof($loanTable2Array);$b++){
if($userArray[$i][userID] == $loanTable2Array[$b][userID]{
//list items
}
}
for($c=1;$c>sizeof($loanTable3Array);$c++){
if($userArray[$i][userID] == $loanTable3Array[$c][userID]{
//list items
}
}
for($d=1;$d>sizeof($loanTable4Array);$d++){
if($userArray[$i][userID] == $loanTable4Array[$d][userID]{
//list items
}
}
}
My concern with this though is that I will have around 100-150 users and each table will have an average of 100 different items. This would mean around 40,000 - 60,000 iterations of the loop.
My other idea was to do pull all of the entries from the user table, then use that data to query the other 4 tables using the userID in a where statement like this. But then I read that if you have a query in a loop then you're doing it wrong.
$sql = "SELECT userID FROM users";
$allUsers = runQuery($sql); //data is sanitized before running the query
for($i = 1; $i<sizeof($allUsers); $i++){
$loan1sql = "SELECT * FROM loantable1 WHERE userID = {$allUsers[$i][$userID]}'";
$loan1Items= runQuery($loan1sql);
for($a = 1; $a<sizeof($loan1Items); $a++){
//list items
}
$loan2sql = "SELECT * FROM loantable2 WHERE userID = '{$allUsers[$i][$userID]}'";
$loan2Items= runQuery($loan2sql);
for($b = 1; $b<sizeof($loan2Items); $b++){
//list items
}
$loan3sql = "SELECT * FROM loantable3 WHERE userID = '{$allUsers[$i][$userID]}'";
$loan3Items= runQuery($loan3sql);
for($c = 1; $c<sizeof($loan3Items); $c++){
//list items
}
$loan4sql = "SELECT * FROM loantable4 WHERE userID = '{$allUsers[$i][$userID]}'";
$loan4Items= runQuery($loan4sql);
for($d = 1; $d<sizeof($loan1Items); $d++){
//list items
}
}
Doing this would result in 400 - 600 calls to the database each time the page is loaded. Does anyone have any input on what my best course of action would be? Any help would be greatly appreciated.
By considering an extra category column , you could have one loantable instead of four . Then you would just use one query by JOINing the tables .
Just an example showing one way to do it :
-- Table structure for table `users`
CREATE TABLE IF NOT EXISTS `users` (
`userID` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`userID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
-- Dumping data for table `users`
INSERT INTO `users` (`userID`) VALUES
(1),
(2);
-- --------------------------------------------------------
-- Table structure for table `loantable`
CREATE TABLE IF NOT EXISTS `loantable` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`category` int(11) NOT NULL,
`userID` int(11) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
-- Dumping data for table `loantable`
INSERT INTO `loantable` (`ID`, `category`, `userID`) VALUES
(1, 1, 1),
(2, 2, 1),
(3, 3, 1),
(4, 1, 2),
(5, 3, 2);
Then you would use just one query like :
SELECT *
FROM
`users`
LEFT OUTER JOIN loantable ON loantable.userID = users.userID
WHERE 1
ORDER BY
users.userID
,category
(refer to answers above. This was too long to add as a comment, but I thought it would be helpful)
#cartalot and #Uours THANK YOU!!!! - I had considered creating one table for all of the loans early on but didn't know how to implement it. This makes perfect sense though. My whole issue was confusing the foreign key - parent key constraints in mySQL with how you can actually join tables to display information on your page.
Not to sound like a complete moron, but I think this might be constructive to someone that reads this down the road. I got confused by how you can create fk - pk relations in myPHPAdmin and what they actually do. I though that these relations were necessary to join tables (obviously wrong). I saw the visual connections and though that these tables were somehow "connected".
I know understand that when you create a foreign key parent key restraints all you are basically doing is limiting they data that you can enter into a table based on what is in another table. You can still join information from different tables without these constraints.
This function gives me an infinite loop
function getCats($parent,$level){
// retrieve all children of $parent
$result = "";
$query = "SELECT title,parent_id from t_cats where parent_id = '$parent'";
if($rs = C_DB::fetchRecordset($query)){
while($row = C_DB::fetchRow($rs)){
$result .= str_repeat($parent,$level).$row['title']."\n";
getCats($row['parent_id'],$level+1);
}
}
return $result;
}
here is my db table
CREATE TABLE `db`.`t_cats` (
`ID` int(10) unsigned NOT NULL auto_increment,
`datasource_id` int(10) unsigned default '0',
`version` char(10) character set latin1 default 'edit',
`status` char(10) character set latin1 default 'new',
`modified_date` datetime default NULL,
`modified_by` int(10) unsigned default '0',
`title` char(255) character set latin1 default NULL,
`parent_id` int(11) default NULL,
PRIMARY KEY (`ID`),
KEY `idx_datasource_id` (`datasource_id`)
) ENGINE=MyISAM AUTO_INCREMENT=50 DEFAULT CHARSET=utf8;
I just want to be able to get my list of categories recursive.
But what am i doing wrong?
EDIT:
function getCats($parent,$level){
// retrieve all children of $parent
$result ="";
$query = "SELECT title,parent_id from t_cats where parent_id = '$parent'";
if($rs = C_DB::fetchRecordset($query)){
while($row = C_DB::fetchRow($rs)){
$result.= str_repeat($parent,$level).$row['title']."\n";
getCats($row['id'],$level + 1 );
}
}
return $result;
}
This line looks wrong:
getCats($row['parent_id'],$level+1);
You should be calling it with the current child ID - at the moment you're calling it with the same ID over and over. Something like this (you need to select the id from your table):
getCats($row['id'], $level + 1);
Edit: you need to update your query to select id:
$query = "SELECT id, title, parent_id from t_cats where parent_id = '$parent' AND id != parent_id";
I've also added a bit to stop it getting into a loop if an item is its own parent.
I found this SitePoint article on "Storing Hierarchical Data in a Database" very helpful. It's all PHP examples, and it will improve the performance of what you're trying to do dramatically.
Maybe one of the items in the db has itself as parent?
I don't know C_DB, but I'd bet that the $rs returned by fetchrecordset is a reference, which means that every invocation of getCats is using the same $rs. Exactly what it will do then is unpredictable, depending on how fetchRow is implemented.
If you want to do this (and recursive closures are a pain in SQL, I know), you should open a new connection inside getCats. and be using a separate connection for each access.
correct answer provided by greg ...
2 side notes:
in the case of infinite loops, track recursion depth (you can conveniently use $level here) or overall invocation count (if you are lazy, since this is a oneliner accessing a global counter), and terminate recursion with an exception, when it reaches a maximum value (in general, 10 is already enough to see the problem, but of course that may vary) ... and then get some debug output ... for example $query or something like "calling getCats($parent,$level)" ... would've shown you the problem in no time in this case ... :)
you should minimize the amount of queries ... traversing a tree like that is quite inefficient ... especially, if the database is on another machine ...
greetz
back2dos
Erm shouldnt it be:
$query = "SELECT title,parent_id from t_cats where id = '$parent'";
And not:
$query = "SELECT title,parent_id from t_cats where parent_id = '$parent'";