0

I am trying to create a button that when clicked will add a record to that database, and when clicked again, will delete this record from that database (it's a 'favourite' button).

I would like it to work as follows;

User clicks 'fav' button > button state changes to success > record added

User clicks 'fav' button again > state changes to default > record removed from db

So far my code is as follows (updated code thanks to @Peter);

books_model.php

class BooksModel
{
 public function checkFav($bookid,$userid)
 {
    $book_id=$_REQUEST['book_id'];
    $user_id=$_SESSION['user_id'];

    $sql = "SELECT * FROM favourite WHERE user_id=? AND book_id=?";
    $query = $this->db->prepare($sql);
    $query->bind_param('ii', $userid,$bookid);
    $query->execute();
    $query->store_result();
    $rows_found = $query->num_rows();
     if(empty($rows_found)) {
        $sql = "INSERT INTO favourite (user_id, book_id)
                VALUES (?, ?)";
        $query = $this->db->prepare($sql);
        $query->bind_param('ii',$userid,$bookid);
        $query->execute();

    } else { 
        $sql = "DELETE FROM favourite WHERE user_id=? AND book_id =?";
        $query = $this->db->prepare($sql);
        $query->bind_param('ii',$userid,$bookid);
        $query->execute();
    }
 }
}

books_controller.php

class Books extends Controller
{
 function checkFav()
 {
    $checkFav_model = $this->loadModel('Books');
 }
}

itemView.php

$(document).ready(function(){
$( "#fav" ).click(function(){  
$( this ).toggleClass( "btn-success" );   
book_id = $(fav).val(); // set the value of the button (book_id)

    $.ajax({
         type: 'POST',
         url: '<?php echo URL; ?>books/checkFav', //location of query
         data: {book_id:book_id}, //taken from value of button

         success: function () { 
             $( "div.addtofavs" ).slideToggle( "slow" ); //show div below button
            }//end success        
        });//end ajax   
    });
});

button html

<button id="fav" value="'.$book->id.'" type="button" class="btn btn-default"></button>

Currently when I click the button and look in the console I can see the post, however nothing is being sent to my db.

Any advice or direction is appreciated as I am quite new to MVC and JS.

jonboy
  • 2,729
  • 6
  • 37
  • 77
  • 1
    Not detailed enough for an answer so I'll add as a comment. I did a social networking site which had a 'recommend' button. with that the button had a 'recommended' class on click (removed when clicked again) I just set a flag in the jquery ajax depending on .hasClass('recommended') – atmd Jan 07 '15 at 11:55
  • have only one function to check and insert or delete –  Jan 07 '15 at 12:22

4 Answers4

1

You can simply do a check: SELECT * FROM favourite WHERE user_id = :user_id AND book_id = :book_id

if it returns something, execute the DELETE FROM favourite WHERE user_id = :user_id AND book_id = :book_id

else do the insert.

If you want to show the book is already added as favourite to the user, then you have to execute another call on page load which gives the button an attribute, which tells you AND the user it's already a favourite or not.

In the last case you don't have to do the check anymore. Just execute the DELETE query if it contains the attribute, else do the INSERT

// try to get the attribute of the button
var attr = $(".favoriteButton").attr('data-favorite');
// check the button has the attribute
if (typeof attr !== typeof undefined && attr !== false) {
   //delete query
   $.ajax({
         type: 'POST',
         url: '<?php echo URL; ?>books/deleteFav', //location of query
         data: {book_id:book_id}, //taken from value of button

         success: function () { 
             $( "div.addtofavs" ).slideToggle( "slow" ); //show div below button
            }//end success        
        });//end ajax   
    });
}

Something like that

Erik van de Ven
  • 4,747
  • 6
  • 38
  • 80
  • 1
    Glad to help ;) About your problem: If I take a look at your code... Isn't it a bit strange to call the function checkFav inside the checkFav function? The rest of your code looks just fine to me. You can add ```error_reporting(E_ALL); ini_set('display_errors', 1);``` to the top of your PHP file. This might return some errors when you check the Ajax call in the network tab of the Chrome console. And maybe (guess you are using mysqli?): http://php.net/manual/en/mysqli.error.php – Erik van de Ven Jan 07 '15 at 19:13
  • 1
    Sure it's not bindParam? and not bind_param? – Erik van de Ven Jan 08 '15 at 12:36
  • I meant, according to the PDOStatement documentation: http://php.net/manual/en/pdostatement.bindparam.php you should use the bindParam() function (camelcase) and not bind_param. And you should possibly check for database errors. for example use try and catch: http://php.net/pdo.error-handling If anything goes wrong at the database, PDO should throw an error in the catch statement. – Erik van de Ven Jan 08 '15 at 13:21
1
public function checkFav($bookid,$userid)

{

$sql = "SELECT * FROM favourite WHERE user_id=:userid AND book_id=:bookid";
$query = $this->db->prepare($sql);
$query->bindParam(':userid', $userid);
$query->bindParam(':bookid', $bookid);
$query->execute();
$rows_found = $query->countRows();
 if(empty($rows_found)) {
    $sql = "INSERT INTO favourite (user_id, book_id) VALUES (:userid, :bookid)";
    $query = $this->db->prepare($sql);
    $query->bindParam(':userid', $userid);
    $query->bindParam(':bookid', $bookid);
    $query->execute();

} else { 
    $sql = "DELETE FROM favourite WHERE user_id=:userid AND book_id =:bookid";
    $query = $this->db->prepare($sql);
    $query->bindParam(':userid', $userid);
    $query->bindParam(':bookid', $bookid);
    $query->execute();
}
}
$book_id=$_REQUEST['book_id'];
$user_id=$_SESSION['user_id'];
checkFav($book_id,$user_id);
  • is this function called inside a class? if yes then use $this->checkFav($book_id,$user_id) or if it belongs to classed called in your code like this $myclass= new MyClass();... use $myclass->checkFav($book_id,$user_id)... –  Jan 07 '15 at 13:41
  • I edited your code can you check it please? I haven't seen the MVC structure of your application but i think this is it. –  Jan 07 '15 at 18:18
  • @PeterDarmis Please don't change the code in the question in order to solve something. Update your answer instead. – Tom Jan 07 '15 at 18:56
  • 1
    May i ask if you use PDO or mysqli statements regarding database? bindParam is for PDO, bind_param is for mysqli. It is essential to determine which you use in order for the db commands to work. it is also good that you uploaded the whole code with the class. –  Jan 08 '15 at 13:17
  • please check the updated code there is no need for store_result i thought you used mysqli –  Jan 08 '15 at 14:57
  • Excellent! I just had to change `$rows_found = $query->countRows();` to `$rows_found = $query->fetchColumn();` in order to get it working! Not sure why though? – jonboy Jan 08 '15 at 15:13
  • sorry my mistake there you are right fetchcolumn is the proper usage also listed here http://stackoverflow.com/questions/883365/row-count-with-pdo –  Jan 08 '15 at 15:25
0

Use generic vars: var IsDeleted; var IsAdded; then IsDeleted = 0; IsAdded =1; (your book is added). Change the values again when you delete book IsDeleted = 1; IsAdded =0; when you execute $( "#fav" ).click(function() check those values and do what action you want (add, delete).

ares777
  • 3,590
  • 1
  • 22
  • 23
0
<button class="fvrt" data-item-id="11" data-current-state="0"> Like <button>   // 0 = normal, 1 = liked

$(document).on('click', '.fvrt', function(){

    if($(this).attr('data-current-state') == 0){

         like_item($(this).attr('data-item-id'));   // send ajax request
         $(this).attr('data-current-state', '1');
         $(this).val('Liked');  

    }else{

         dislike_item($(this).attr('data-item-id'));   // send ajax request
         $(this).attr('data-current-state', '0');
         $(this).val('Like');  

    } // checking state 

}); // on clicked
Tiger
  • 404
  • 1
  • 4
  • 13
  • You have to create 2 functions one :- like_item(book_id){ // send ajax request for normal to favourate } and another is :- dislike_item(book_id) { // send ajax request to favourate to normal } – Tiger Jan 07 '15 at 13:31
  • Actually like = Favourate :p, and ajax ondone event change the label of those buttons, and here you will have to add the book id something like this :- – Tiger Jan 07 '15 at 13:34