This task is also very easy to accomplish with the new cart
library. We will need a controller and a view. Just go to application/controllers/shop.php
, and add a new function to it; show_cart
would be a good name:
function show_cart() { $this->load->helper('form'); $this->load->view('cart'); }
Nothing much happening there, we only load the form
helper and the cart
view. We will do most of the work in application/views/cart.php
:
<h1>This is our cart</h1> <?php //Open the form and point it to the update function echo form_open('shop/update'); ?> <table border="2"> <tr> <th>Product</th> <th>Quantity</th> <th style="text-align:right">Price</th> <th style="text-align:right">Total</th> </tr> <?php $i = 1; ?> <?php //Then loop through the cart contents foreach($this->cart->contents() as $items): ?> <?php //Create a hidden input field for each element, adding the rowid //value to it echo form_hidden($i.'rowid', $items['rowid']); ?> <tr> <td> <?php //Also create an input field for the quantity value, this will //allow us to modify this value echo form_input(array('name' => $i.'qty', 'value' => items['qty'], 'maxlength' => '3', 'size' => '5')); ?> </td> <td> <?php //show the product name echo $items['name']; ?> </td> <td> <?php //show the product price echo $this->cart->format_number($items['price']); ?> </td> <td> $<?php //show the total price echo $this->cart->format_number($items['subtotal']); ?> </td> </tr> <?php $i++; ?> <?php endforeach; ?> <tr> <td colspan="2"> </td> <td><strong>Total</strong></td> <td>$<?php echo $this->cart->format_number($this->cart->total()); ?></td> </tr> </table> <p> <?php //Send the form echo form_submit('submit', 'Update cart'); ?> </p> <p> <?php //Or go back to the index echo anchor('shop/index', 'Continue shopping'); ?> </p>
Let's see what we are doing in this piece of code. This works pretty much the same way as other edit forms we have seen in the previous chapters. We start by opening the form, and pointing it to the edit
function.
The next step is to loop through the contents in our cart. In order to retrieve our cart contents we need to call the following function:
foreach($this->cart->contents() as $items):
The cart->contents()
function returns all that is in our cart, and using the foreach
loop we put each result into an $items
array. In each loop we create the fields necessary to modify the elements in our cart. For example, first we create a hidden field:
echo form_hidden($i.'rowid', $items['rowid']);
This hidden field contains the rowid
of the element. To understand what the rowid
is, we can take a look at the source code this field generates:
<input type="hidden" name="1rowid" value="c4ca4238a0b923820dcc509a6f75849b" />
The name is not important, we can name it the way we want; the $i
variable helps us to name it and give a different name for each field. The rowid
is the value for this product.
Note
Why not use the product ID to identify it? Sometimes, for products that have options, we can have cart products with the same ID, but with different options. Thus we need a way of distinguishing different products; the rowid
is used to identify them.
Next we create an input field to show and let us change the quantities, using the following line:
<?php echo form_input(array('name' => $i.'qty', 'value' => $items['qty'], 'maxlength' => '3', 'size' => '5')); ?>
This works in much the same way as the previous field. Again, the name is formed with the $i
variable and a string, qty
in this case—using the $items['qty']
array—which contains the quantity of items for this product. The name of the product is also inside the $items
array:
<?php echo $items['name']; ?>
Other values that we can find inside the $items
array are:
$items['price']
is the singular price for this element$items['subtotal']
is the subtotal price, meaning the price of the product multiplied by the number of products of this type
Once we have run across all the elements we have in the cart, we can show the total price for the cart, which is contained in:
$this->cart->total()
Then we create two things:
echo form_submit('submit', 'Update cart')
;This creates the button that will submit the form, with all the changes we have made to the quantities
echo anchor('shop/index', 'Continue shopping')
;This creates a link to go back to the index page
Let's check what we have done; go to http://localhost/codeigniterc/index.php/shop/index
and "Buy" something. Now if you go to http://localhost/codeigniterc/index.php/shop/show_cart
, you will see a screen that more or less resembles the following:
Don't click on the Update Cart button for now, remember that we need to prepare our controller; we need an update
function:
function update() { //create the array variable $data = array(); //create a loop that runs as many times as items we have in the //cart for($i=1;$i<=$this->cart->total_items();$i++) { //add an array for each item, with the posted rowid and the new //quantity $data[] = array('rowid' => $_POST[$i.'rowid'], 'qty' => $_POST[$i.'qty']); } //execute the cart update method $this->cart->update($data); //return to the show_cart function to show the user the changes we //have made redirect('shop/show_cart/', 'refresh'); }
To update the items in our cart, we use one of the library's update
methods. This method receives values that we want to change, in the form of an array.
We use a loop, which goes to all the items we have in the cart. This is not a problem, because even if we change only one element in the cart, the others are sent too, maintaining their quantity value. For each of the loops we put an array into the main array:
$data[] = array('rowid' => $_POST[$i.'rowid'], 'qty' => $_POST[$i.'qty']);
Here we find the rowid
, with the value sent by the form in the $_POST
global variable, which will be used to determine which product to update, and the quantity value, which will update the product's quantity. Then we execute the update method:
$this->cart->update($data);
That's all; you can check it at http://localhost/codeigniterc/index.php/shop/show_cart
. So go ahead and give it a try.
We can also add, in the application/views/home.php
, a link to the show_cart
screen:
<p><?php echo anchor('shop/show_cart', 'See cart'); ?></p>
So we can access the show_cart
screen every time we want. One more thing I would like to share with you is one detail of the cart
library; maybe you have noticed it before. When you go to http://localhost/codeigniterc/index.php/shop/index
, and add a product to the cart and then go to http://localhost/codeigniterc/index.php/shop/show_cart
, you will see that the product is added. Now, if you return to the shop index and add two products what will happen? You will see that there are two products on the show_cart
page.
By default the cart
library places the last quantity added to it. So, if we have one product added to the cart, and after that if we try to add two of the same product, then there will be two items of that product. But sometimes it would be desirable to sum products as we add them, so we would have three products of the same type in the cart.
If we want to have this functionality, we can achieve it in a very easy way. Let's modify the add
function in our shop
controller:
function add() { //First we get all the contents in the cart $data = $this->cart->contents(); //then we loop through the contents foreach($data as $row) { //If we are in the array of the element we want to modify if($row['id'] == $_POST['id'] && $_POST['qty'] != 0) { //we get the current quantity and sum the quantity we have just //added $qty = ($row['qty']) + ($_POST['qty']); } } $data = array( 'id' => $_POST['id'], 'qty' => (empty($qty) ? $_POST['qty'] : $qty), 'price' => $_POST['price'], 'name' => $_POST['name'] ); //we use a short hand if to check if the $qty variable is empty, //and if it is we get the value of the $_POST array //And then we insert the data $this->cart->insert($data); redirect('shop/index/', 'refresh'); }
With these little modifications we are able to make the cart
library behave as we want. Another thing that won't work as expected is the cart->total_items()
method, as this one will not return the total of all elements in the cart; instead it will return the total of distinct product types. As before, this is very easy to solve. We can create a new method in our shop
controller:
function total_items() { $data = $this->cart->contents(); $qty = 0; foreach($data as $row) { $qty += $row['qty']; } return $qty; }
Pretty much the same as before, we can now call this method in any of our controller's methods:
$data['qty'] = $this->total_items();
So, if we send this variable to the view, we will be able to output the correct quantity of elements in the cart:
Total elements in cart <?php echo $qty; ?>
Note
These two problems have been commented on in the forums, and some solutions have been given for them on:
http://codeigniter.com/forums/viewthread/129037/
But it is preferable not to modify the cart
library directly, as it could be changed in the next CI update, causing us to lose all of our changes.
At this time we may have a basic cart, but one that works. However, there's much more in the cart
library. We have only seen the basics; if you want to learn more, you can check this page:
http://codeigniter.com/user_guide/helpers/cart.html
Don't forget to check the options in products; that can be very useful in some projects, also this basic example can be easily modified to support that feature.