MongoDB Tutorial Part 8: Deleting Items

Here One Day, Gone The Next

 

Practically every application that lets you add items to a database is also going to need a way to remove them. A dealership just sold a car and needs it removed from their inventory database. An employee quit and needs to be removed from the staff database. Or in our case, a player has sold or lost one of his treasures and wants to remove it from his Treasure Bag.

 

Deleting data is important!

 

Fortunately, this tutorial on removing items from a MongoDB database is going to be really short and simple. If you remember back to tutorial 3 the syntax for finding items and deleting items is almost identical. Which means that if you know how to find a specific item you also know how to delete a specific item. And we already covered finding one specific item back in tutorial 6 with “viewItem.php”.

 

With that in mind, let’s review “viewItem.php” really quickly. Remember the steps we used to find a specific item based off of it’s id?

 

$itemID = $_GET['id'];
$criteria['_id'] = new MongoId($itemID);

$c = new Mongo();

$itemAttributes=$c->treasurebag->treasure->findOne($criteria);

 

delete.php

 

The code for “delete.php” is going to look very similar to the item viewing code we just reviewed. Open your editor, create a file named something like “delete.php” and type in the following code:

 

$itemID = $_GET['id'];
$criteria['_id'] = new MongoId($itemID);

$c = new Mongo();

$c->treasurebag->treasure->remove($criteria);

 

It’s identical to our item viewing code except for that last line. Instead of using findOne, like we did for item viewing, we’re using the remove function. You just give remove a set of key/value pairs and it will remove any items in the collection that match.

 

In our case, we’re passing it a unique match between _id and a specific MongoID, so it should only ever delete one item. But you can also use this function to delete multiple items all at once. For example, you could delete all Weapon type items with a call like:

 

//Deletes all weapons. Do not include in delete.php!!
$newCriteria['type']='Weapon';
$c->treasurebag->treasure->remove($newCriteria);

 

So when writing code that will use remove always double check what information you’re passing it. It’s not fun to accidentally wipe out half a collection when you actually only wanted to remove three items.

 

Finishing Up delete.php

 

Calling remove deletes the item… but now what do we do with the user? Well, if you check back to our design document we decided that after deleting an item the user should be returned to the main index. So at the very end of “delete.php” we should include this line:

 

header('Location:index.php');

 

That’s it! We’re done with delete.php.

 

Getting To Delete.php

 

You can now delete any item by visiting “delete.php?id=mongoID_of_item_to_delete”. But manually finding and typing in MongoIDs would be a nightmare. It would be much better to automatically generate delete URLs for the user.

 

Actually, if you look at the design document we originally planned on having a delete link at the bottom of every item’s detailed view. So let’s open up “itemView.php” and put it in there! All you have to do is go down near the bottom of the code, after the switch statement that prints the item but before the call to include(‘footer.php’). Then add this simple link generator:

 

echo "<br/><a href='delete.php?id=$itemID'>DELETE</a><br/>";

 

This code takes the $itemID we used to generate the detailed item view and creates a new link for deleting that item. Now deleting an item is as simple as finding on the main page, clicking its name for a detailed view and then clicking the delete link at the bottom.

 

Testing

 

Testing this is pretty straightforward. Find or create a treasure that you want to delete. Click on it’s name in the index to see the detailed view. Click on delete and make sure you get automatically returned to the index. Double check the index and make sure the treasure is gone.

 

Complete Code

 

Updated “viewItem.php”

<?php
include('header.php');
$itemID = $_GET['id'];
$criteria['_id'] = new MongoId($itemID);

$c = new Mongo();

$itemAttributes=$c->treasurebag->treasure->findOne($criteria);

echo '<b>Name:</b> '.$itemAttributes['Name'].'<br/>';
echo '<b>Type:</b> '.$itemAttributes['Type'].'<br/>';
echo '<b>Price:</b> '.$itemAttributes['Price'].'<br/>';

switch($itemAttributes['Type']){
    case 'Ring':
        echo '<b>Special Attribute:</b> '.$itemAttributes['Special Attribute'].'<br/>';
        break;
    case 'Weapon':
        echo '<b>Bonus:</b> '.$itemAttributes['Bonus'].'<br/>';
        if( !empty($itemAttributes['Special Attributes']) ){
            echo '<b>Special Attributes:</b>';
            echo '<ul>';
                foreach($itemAttributes['Special Attributes'] as $specialAttribute){
                    echo "<li>$specialAttribute</li>";
                }
            echo '</ul>';
        }
        break;
    case 'Wand':
        echo '<b>Charges:</b> '.$itemAttributes['Charges'].'<br/>';
        echo '<b>Spell:</b> '.$itemAttributes['Spell'].'<br/>';
        break;
    case 'Staff':
        echo '<b>Charges:</b> '.$itemAttributes['Charges'].'<br/>';
        echo '<b>Spells:</b>';
        echo '<ul>';
            foreach($itemAttributes['Spells'] as $spell){
                echo "<li>$spell</li>";
            }
        echo '</ul>';
        break;
}

echo "<br/><a href='delete.php?id=$itemID'>DELETE</a><br/>";

include('footer.php');
?>

“delete.php”

<?php
$itemID = $_GET['id'];
$criteria['_id'] = new MongoId($itemID);

$c = new Mongo();

$c->treasurebag->treasure->remove($criteria);

header('Location:index.php');

?>

Conclusion

 

Treasure Bag is starting to feel like a real piece of software. We can add treasures, delete them, sort them and examine them. The only thing left is to build a useful search tool. So join me next time as we tackle our final challenge.

 

BONUS!

 

If you’ve been diligently doing the bonus challenges you should have a character system that lets you create and view various heroes and villains. Now create a “deleteCharacter.php” script so you can clean out unused characters in the same way you delete unneeded treasures.