Forums

The forums ran from 2008-2020 and are now closed and viewable here as an archive.

Home Forums Back End Display A Stored Value (1-5) As A Star?

  • This topic is empty.
Viewing 15 posts - 1 through 15 (of 21 total)
  • Author
    Posts
  • #159652
    MBM
    Participant

    I’ve used a javascript that allows images to be used instead of radio buttons to store values, from 1-5 with rating being the Int field that stores the value.

    <input id="rating" name="rating" type="radio" value="1" /><span></span>
    <input id="rating" name="rating" type="radio" value="2" /><span></span>
    <input id="rating" name="rating" type="radio" value="3" /><span></span>
    <input id="rating" name="rating" type="radio" value="4" /><span></span>
    <input id="rating" name="rating" type="radio" value="5" /><span></span>

    How do I convert the values once they have been written into the table into images e.g. stars? I’ve found several tutorials e.g.

    http://stackoverflow.com/questions/10250825/converting-numbers-to-visual-rating-stars

    <?php
    for($x=1;$x<=$starNumber;$x++) {
    echo '<img src="path/to/star.png" />';
    }
    if (strpos($starNumber,'.')) {
    echo '<img src="path/to/half/star.png" />';
    $x++;
    }
    while ($x<=5) {
    echo '<img src="path/to/blank/star.png" />';
    $x++;
    }
    ?>

    And tried to adapt it but I don’t understand how to used a stored value . I’ve tried using the $rating variable. As I want to display an average once it’s working I need to show decimal values as well e.g. If I get votes as follows :

    4 stars x 6 votes
    3 stars x 7 votes

    I would need to show 4.5 stars.

    #159658
    __
    Participant

    I don’t understand how to used a stored value.

    Where are you storing the value? You mention a “table,” but I’m not sure if you mean a Database or an HTML table.

    As I want to display an average once it’s working I need to show decimal values as well e.g. … 4.5 stars.

    Since ((4 * 6) + (3 * 7)) / 13 ≠ 4.5, I’m assuming you’re rounding things off to the nearest half.

    I’ve tried using the $rating variable

    There is no variable named $rating in the code you posted. Your form has an input named rating, which, when the form is submitted, would be available in PHP as $_GET["rating"].

    Say you have your average, for example, 4.5. Here’s how I would approach it:

    <?php
    $rating = 4.5;
    
    // round down to get number of whole stars needed
    $wholeStars = floor( $rating );
    
    // double, round, take modulo.
    // this will be 1 if you have a half-rating, 0 if not.
    $halfStar = round( $rating * 2 ) % 2;
    
    // this will hold your html markup
    $HTML = "";
    
    // write img tags for each whole star
    for( $i=0; $i<$wholeStars; $i++ ){
        $HTML .= "<img src=http://example.com/path/to/star.png alt='Whole Star'>";
    }
    // write img tag for half star if needed
    if( $halfStar ){
        $HTML .= "<img src=http://example.com/path/to/half.png alt='Half Star'>";
    }
    
    // all done
    print $HTML;
    
    #159659
    MBM
    Participant

    There is no variable named $rating in the code you posted. Your form has an input named rating, which, when the form is submitted, would be available in PHP as $_GET[“rating”].

    Thanks. So instead of :

    $rating = 4.5;

    I would use? :

    $_GET["rating"]

    The value is stored in a database table. The field name is rating.

    Since ((4 * 6) + (3 * 7)) / 13 ≠ 4.5, I’m assuming you’re rounding things off to the nearest half.

    Yes though if it’s easier to leave the numbers without rounding up that’s fine as well.

    Parse error: syntax error, unexpected ')', expecting ';' in rating/commentsboard.php on line 69

    Line 69 :

    for( $i=0; $i<$wholeStars,$i++ ){

    #159660
    __
    Participant

    for( $i=0; $i<$wholeStars,$i++ ){

    I edited and fixed that, but I guess you copied it before I caught it. The comma should be a semicolon (the current version in my post is correct).

    I would use? : $_GET["rating"]

    If you were getting the value from the html form, yes. However…

    The value is stored in a database table. The field name is rating.

    In this case, you would need to query the database to get the value. How to do this depends on what kind of database, what API you’re using, and how the table is structured.

    If you’re using MySQL, I would recommend using MySQLi or PDO. If you can share your table schema (structure), then we can talk about what the query would need to look like.

    #159664
    MBM
    Participant

    Thank you it worked! It’s a bog standard table. I’ve exported it. You can view everything here.

    https://gist.github.com/gyprosetti/1b12683660b868218fe0

    Here’s the structure without any content.

    CREATE TABLE IF NOT EXISTS comments ( id int(4) NOT NULL AUTO_INCREMENT, username varchar(30) DEFAULT NULL, subject varchar(30) DEFAULT NULL, dateofcomment timestamp NULL DEFAULT CURRENT_TIMESTAMP, usercomments text, rating int(1) DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=94 ;

    What does this code do?

    $halfStar = round( $rating * 2 ) % 2;

    Round to 2 decimal places?

    #159665
    __
    Participant

    What does this code do?

    $halfStar = round( $rating * 2 ) % 2;

    It’s doing three things at once. First, double the rating. I’m doing this so I have “halves”: For example, instead of 4.5 wholes, I have 9 halves.

    Next, I round that value. 9 rounds to 9, of course, but say the original rating was 4.3: doubling it give us 8.6 halves, which will round off to 9 halves (4.5 wholes).

    Last, I take the modulo of the doubled number. The modulo operator (% in most languages) gives you the remainder after division. So, 9 % 2 is 1, while 10 % 2 would be 0.

    ~~~~~~~~~~~~~~~~~~~~~~~~~~

    Here’s the structure …

    CREATE TABLE IF NOT EXISTS `comments` (
      `id` int(4) NOT NULL AUTO_INCREMENT,
      `username` varchar(30) DEFAULT NULL,
      `subject` varchar(30) DEFAULT NULL,
      `dateofcomment` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
      `usercomments` text,
      `rating` int(1) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=94 ;
    

    How do you want to sort these? I’m assuming you want all of the ratings for a particular subject?

    SELECT AVG( `rating` ) AS `avg_rating`
        FROM `comments`
        WHERE `subject` = ?
    

    …where ? is the subject you want to get ratings for.

    #159666
    MBM
    Participant

    The subject is irrelevant to the ratings. At the moment the comments are sorted by descending date order :

    //query the database and display the comments by descending order with the latest comment first
    $result = mysql_query(“SELECT * FROM comments ORDER BY dateofcomment DESC”);

    Think of it like an item review on amazon. The ratings will be for products (though I haven’t added a product the field as there are only a handful of entries) but each product will have it’s own separate page so the user will only ever see ratings and comments for ONE product on each page. I could create a separate table for the products and use a join to run queries (SQL code I understand it’s php I don’t get) but at the moment as there will only be 10 products I’ll dump everything in one table.

    For sake of argument product 1 is snickers, product 2 is mars. The sort would be :

    SELECT AVG( rating ) AS avg_rating
    FROM comments
    WHERE product = snickers

    That would be the sort for the snickers product page.

    And this for mars :

    SELECT AVG( rating ) AS avg_rating
    FROM comments
    WHERE product = mars

    The problem here is that by default the comments are displayed by date order so I would need to execute the above sort via a link e.g. click to view by average rating.

    Hope that makes sense. I want to learn the basics – storing and retrieving data, running queries and finally editing and deleting data then I’ll move onto MySQLi as you suggested. I would prefer to work with the code I have as I understand it and can do almost everything I want to do.

    #159679
    MBM
    Participant

    I’ve added a product field. On this page snickers is the default product.

    $Query = "INSERT INTO $Table_3 VALUES ('0', '".mysql_escape_string($formValue["username"])."','".mysql_escape_string($formValue["subject"])."',NOW(),'".mysql_escape_string($usercomments)."','".mysql_escape_string($formValue["rating"])."','snickers')";
    
    #159699
    __
    Participant

    (SQL code I understand it’s php I don’t get)

    If that’s the case, I will say that you should stop using the mysql_* functions. They have been outdated since 2004 and are now deprecated – they will be removed from PHP in future versions. By learning to use ext/mysql in this day and age, you are only learning bad habits and making extra work for yourself (now and in the future).

    I want to learn the basics – storing and retrieving data, running queries and finally editing and deleting data then I’ll move onto MySQLi as you suggested.

    I understand that, but it’s not a matter of “basic” vs. “advanced.” It’s “outdated, complicated and unmaintained” vs. “streamlined, fully featured, secure and under active development.”

    The problem here is that by default the comments are displayed by date order so I would need to execute the above sort via a link e.g. click to view by average rating.

    I don’t think I understand this correctly. You want to display the individual comments for the product? How can you sort individual items by their combined average?

    To me, “click to view by average rating” implies that there are multiple products on the page. Perhaps you mean “click to view by rating”?

    If that’s the case, you can just add an ORDER BY clause to your query.

    #159702
    MBM
    Participant

    If that’s the case, I will say that you should stop using the mysql_* functions. They have been outdated since 2004 and are now deprecated – they will be removed from PHP in future versions.

    I know but this isn’t for commercial use and I have no intention of learning php for commercial use. I’m building on something I did a few years ago for recreational use, for my own websites. Once I can perform all the functions I need to perform I’ll look at the code again. I don’t see the point in taking 6 months to learn something from scratch when I can complete what I need to do in a few weeks. php isn’t like HTML5 or CSS, there are many different ways to perform the same functions. You’ve suggest mysqli and pdo other says use frameworks e.g. cakePHP, ruby on rails etc, etc. It’s confusing. I spent hours trying to put escapes before the query, because I have mine after which is bad practise, but couldn’t get it working. I would have the same headaches picking apart the rest of my code and what’s the point in that when I only need to add two functions and I’m done? I want to work with the code I have not rip it up and start again.

    I want to filter the comments by the ratings. So for example if I have 10 comments for a product and 3 users have rated it 5 other visitors should have the option of clicking 5 star ratings and only seeing those 3 comments. As you would on amazon.

    http://mbmitservices.co.uk/ratingsort.png

    #159715
    __
    Participant

    I hope I’m not coming across as pushy with my suggestions. I am sincere when I say that ext/mysql should be given the boot if at all possible. If it’s not possible, I understand; that’s the way it is sometimes. What I would not want is for you to make the decision based on bad information. MySQLi/PDO are not frameworks, they are part of the PHP core. cakePHP is a framework, and I believe its database class is built on top of PDO. I won’t bring it up again if you’re not interested.

    I want to filter the comments by the ratings. So for example if I have 10 comments for a product and 3 users have rated it 5 other visitors should have the option of clicking 5 star ratings and only seeing those 3 comments. As you would on amazon.

    Alright, so you’re filtering them. This doesn’t involve averaging, at all.

    SELECT * FROM `comments`
        WHERE `product` = ?
        AND `rating` = ?
    

    Where the first ? is the product name (say, “snickers”), and the second is the desired rating (say, “5”).

    If you wanted all of the ratings (e.g., to create that chart you showed), you could select all of the comments:

    SELECT * FROM `comments`
        WHERE `product` = ?
    

    and sort them afterwards:

    <?php
    
    foreach( $rows as $row ){
        $sortedRows[$row['rating']][] = $row;
    }
    

    This would result in something like:

    array(
        [5] => array(
            // row with rating=5
            // row with rating=5
            // row with rating=5
        ),
        [3] => array(
            // row with rating=3
            // row with rating=3
        ),
        [2] => array(
            // row with rating=2
            // row with rating=2
            // row with rating=2
            // row with rating=2
        )
    )
    
    #159717
    MBM
    Participant

    I know it’s good advice but I would prefer to work with the code I have because I understand it, bad practice or not, I can connect to a database, store and retrieve data and now I can edit stored comments as well – having just followed a 4 year old tutorial written in basic php – a language I sort of understand. Had I followed a tutorial written in mysqli for example I would have been scratching my head all day because it’s all new to me.

    I’m not concerned about the averages at the moment as that’s more SQL related and I understand SQL, what I need to know now is how to display my stored ratings using the images. In the code you wrote you displayed a rating based on a value you specified in the php itself i.e. 4.5. That code works. Here’s a screenshot showing how the value 3.4 is displayed (ignore the size of the images, it’s just for demo purposes).

    http://mbmitservices.co.uk/rateanddisplayrating2.png

    If you look at this screenshot here you will see my form with the rating input (using a javascript to replace radio buttons with an image). If the user clicks on 3 pieces a value of 3 is stored, if they click 5, 5 is stored etc, etc. If you look down in the comments box you’ll see this rating displayed an integer. I want these ratings displayed as images – how your code works but using the stored ratings and not a value specified in the php itself.

    http://mbmitservices.co.uk/rateanddisplayrating1.png

    In my php this is how I display entries from the database :

    <?php //fetch results and convert into an array
    
    WHILE($board = mysql_fetch_array($result)):
    
    $cmtusername = $board['username'];
    $cmtsubject = $board['subject'];
    $usercomments = $board['usercomments'];
    $rating = $board['rating'];
    $cmtdate = $board['dateofcomment'];
    $timestamp = strtotime($cmtdate); 
    $new_date = date('j F Y, g:i a', $timestamp);
    
    echo '
    
    <br style="clear:left;"/>
    
    <div class="cmtform">
    <h2>Subject : '.$cmtsubject.'. Posted by '.$cmtusername.' on '.$new_date.'</h2><br />
    '.$usercomments.'<br />
    <div class="rating">'.$rating.'</div>
    </div>';
    
    #159718
    __
    Participant

    If you look down in the comments box you’ll see this rating displayed an integer. I want these ratings displayed as images – how your code works but using the stored ratings and not a value specified in the php itself.

    The rating you display comes from this line, correct?

    <div class="rating">'.$rating.'</div>
    

    If so, then you have already retrieved the rating from the database: it’s in the variable $rating. If the code I posted works as you desire, you can simply plug it in there:

    WHILE($board = mysql_fetch_array($result)):
    
    $cmtusername = $board['username'];
    $cmtsubject = $board['subject'];
    $usercomments = $board['usercomments'];
    $rating = $board['rating'];
    $cmtdate = $board['dateofcomment'];
    $timestamp = strtotime($cmtdate); 
    $new_date = date('j F Y, g:i a', $timestamp);
    
    // generate img tags
    $HTML = $wholeStars = $halfStar = null;
    $wholeStars = floor( $rating );
    $halfStar = round( $rating * 2 ) % 2;
    for( $i=0; $i<$wholeStars; $i++ ){
        $HTML .= "<img src=http://example.com/path/to/star.png alt='Whole Star'>";
    }
    if( $halfStar ){
        $HTML .= "<img src=http://example.com/path/to/half.png alt='Half Star'>";
    }
    
    // then echo $HTML instead of $rating
    echo '
    <br style="clear:left;"/>
    
    <div class="cmtform">
    <h2>Subject : '.$cmtsubject.'. Posted by '.$cmtusername.' on '.$new_date.'</h2><br />
    '.$usercomments.'<br />
    <div class="rating">'.$HTML.'</div>
    </div>';
    

    If you’re not using averages here (and $rating will always be an integer), then you can safely remove all of the parts where you calculate $halfStar.

    #159726
    MBM
    Participant

    Thanks. I haven’t tried it yet. I’ve removed DBConnect(); from my files as it was causing connection problems with tutorials I have been working through.

    At the moment I have two username fields in two tables (one in users and one in comments), they run independently. What I would like to do is once a user has logged in have their username stored or passed into the comments table automatically. At the moment they enter it manually through the comments form and there’s no correlation with the name they registered with, they can enter anything which is of course stupid! If I was doing this in SQL I would have :

    users table – username (Primary Key) comments table – username (Foreign Key from users table)

    How do I do this in php? How do I pass (not sure of the term) a field (username) from one table and link that to data (in this case comments) in another table when inserting data through the php pages of my website? Or is that not the best practice? Sorry if I haven’t explained this correctly.

    #159729
    __
    Participant

    users table – username (Primary Key) comments table – username (Foreign Key from users table)

    How do I do this in php?

    Don’t do it in php – do it in mysql. If PHP tries to do something wrong (like give a comment a user that doesn’t exist), you’ll get an error, and then you can handle it.

    (Note you’ll need to use the InnoDB engine, however. MyIsam does not support foreign keys.)

    What I would like to do is once a user has logged in have their username stored or passed into the comments table automatically…

    When a user logs in successfully, store their username in the session (remember to remove it when they log out, and set a hard expiry for your sessions).

Viewing 15 posts - 1 through 15 (of 21 total)
  • The forum ‘Back End’ is closed to new topics and replies.