Shopping cart (MVC): the time when an item is added

Hi,

I am using MVC concept to create a basic shopping cart for learning purposes, I have no problem adding/ deleting/ updating items in my cart, but I want to add the timestamp when an item is created into my cart, I still cannot think of a proper method I can achieve this…

It would be wonderful if you have any ideas!

Below is the codes.

This is the code call the cart controller,

#includes the configuration
require_once('inc/global.inc.php');

#includes classes into the application
require ('class_lib.php');

#starts the session
session_start();

$cart_controller = new __cart_controller();
$cart_controller -> invoke_cart($template = 'view.php');

This is the classes of cart, product (model, controller, entity),

/**
 * this file handles the retrieval and serving of page
 */ 
class __cart_controller 
{
	private $cart_model;
	
	public function __construct()  
    {  
        $this -> cart_model = new __cart_model();
    } 
	
	public function invoke_cart($template)
	{	
		#presets the variables
		$action = null;

		if(isset($_GET['action'])) $action = $_GET['action'];
		
		#invoke the __cart_model class, assigning the object to a session variable
		if (!isset($_SESSION[CART]))
		{
			$cart =  $this -> cart_model;
		}
		else 
		{
			$cart = unserialize($_SESSION[CART]);
		}
		
		#proccessing the item in the cart
		if($action == 'update')
		{
			foreach ($_POST as $key => $value) 
			{
				#updates the qunatity of an item
				$cart -> update_quantity($key,$value);	
			}
			
			#always place this line below the method of add_item, of delete_item, and update_quantity
			$_SESSION[CART] = serialize($cart);	
				
			#get the main template
			include $template;
		}
		
		elseif($action == 'delete')
		{
			#removes a product from the cart
			$cart -> delete_item($_REQUEST['pro_id']);
			
			#always place this line below the method of add_item, of delete_item, and update_quantity
			$_SESSION[CART] = serialize($cart);	
			
			#get the main template
			include $template;
		}
		
		else
		{
			#adds a product to the cart
			$cart -> add_item($_REQUEST['pro_id']);
			//$cart -> add_item($_REQUEST['pro_id'],$time = time());
			
			#always place this line below the method of add_item, of delete_item, and update_quantity
			$_SESSION[CART] = serialize($cart);	
			
			print_r($cart);
			
			#get the main template
			include $template;
			
			/*
			* for checking purposes only :-
			*
			*
			
			#make the cart an array to store multiple items.
			$cart2 = array();

			#make the cart store the session.
			$cart2 = $_SESSION['cart_1'];

			#store the item in array.
			$cart2[] = $_GET['pro_id'];

			#make the designated session remember previous items otherwise each new session will replace the previous one.
			$_SESSION['cart_1'] = $cart2;

			#for instance, Array ( [0] => 2 [1] => 3 [2] => 4 ) .
			print_r($cart2);
			
			#put the cart into condiction.
			if (!isset($_SESSION['cart2']))
				{
				$cart2 = array();
				}
			else
				{
				$cart2 = $_SESSION['cart2'];
				}
			
			$cart2[$_REQUEST['pro_id']] = array();			
			$cart2[$_REQUEST['pro_id']]['id'] = $_REQUEST['pro_id'];
			$cart2[$_REQUEST['pro_id']]['created'] = time();
			$_SESSION['cart2'] = $cart2;

			print_r($cart2);
			*
			*
			*/
		}
	}
}

/**
* The store model.
*
*/
class __store_model 
{ 
    /**
	 * holds instance of database connection
	 */
	protected $database;
		
	public function __construct()
	{
		$this -> database = new __database(DB_HOST,DB_USER,DB_PASS,DB_NAME);
	} 

    public function get_store() 
    { 
        #prepare the query
		$sql = "
		SELECT * FROM root_products
		
		LEFT JOIN root_pages
		ON root_products.pg_id = root_pages.pg_id
			
		ORDER BY root_pages.pg_created
		";
	   
		#execute the query	and store the array in the variale
		$product = $this->database->fetch_all($sql);	

		#return the result
		return $product;
    } 
}

/**
* The product model.
*
*/
class __product_model extends __store_model
{ 
    public function get_product($pro_id) 
    { 
        #prepare the query
		$sql = "
		SELECT * FROM root_products
		
		LEFT JOIN root_pages
		ON root_products.pg_id = root_pages.pg_id
			
		WHERE root_products.pro_id = '".$pro_id."'
		";
	   
		#execute the query	and store the array in the variale
		$product = $this->database->fetch_assoc($sql);
		
		#send it to the entity class and instantiate an object from it
		$product = new __product_entity($product);
		
		#return the result
		return $product;
    } 
}

/**
* The product entity.
*
*/
class __product_entity 
{
	public $pro_id = null;
	public $pro_title = null;
	public $pro_price = null;
	
	/**
	 * fetch the array and keep the data in varibales
	 * @param string $page
	 */
	public function __construct($product)  
    {  
       
		$this->pro_id = $product['pro_id'];
		$this->pro_title = $product['pg_title'];
		$this->pro_price = $product['pro_price_primary'];
		
		//print_r($product);
    } 
}

/**
* The shopping cart.
*
*/
class __cart_model
{
	 private $content = array();
	 private $created;
	 /**
	  * The class constructor
	  *
	  */
	 public function __construct() 
	 {
         $this->created = time();
	 }
	 
	 /**
	  * Add a product to the cart
	  * @access public
	  * @param $pro_id integer
	  *
	  */
	//public function add_item($pro_id,$time) 
	public function add_item($pro_id) 
	{
	 	if (isset($this->content[$pro_id])) 
		{
	 	    $this->content[$pro_id]++;
			
			/*$this->content[$pro_id] = array();
			$this->content[$pro_id]['q'] = $this->content[$pro_id]['q'] + 1;
			$this->content[$pro_id]['t'] = $time;
			*/
	 	} 
		else 
		{
	 		$this->content[$pro_id] = 1;
			
			/*
			$this->content[$pro_id] = array();
			$this->content[$pro_id]['q'] = 1;
			$this->content[$pro_id]['t'] = $time;
			echo $time;
			*/
			
	 	}
		//print_r($this->content);
	}
	 
	 /**
	  * Remove product from cart
	  * @access public
	  * @param $pro_id integer
	  *
	  */
	public function delete_item($pro_id) 
	{	
 		if (isset($this->content[$pro_id])) 
		{
 			unset($this->content[$pro_id]);
 		} 		
	}
	 
	 /**
	  * Change the quantity of a particular item held in the shopping cart
	  *
	  * @access public
	  * @param integer $pro_id
	  * @param integer $quantity
	  */
	public function update_quantity($pro_id, $quantity) 
	{
	 	$this->content[$pro_id] = $quantity;
	}
	 
	 /**
	  * Get all items currently in cart
	  *
	  * @access public
	  * @return unknown
	  */
	public function get_items() 
	{
	 	return $this->content;
	}
	 
	 /**
	  * How many items are in the user's cart?
	  * 
	  * @access public
	  * @return INTEGER
	  *
	  */
	public function count_items() 
	{
	 	return array_sum($this->content);
	}

	 /**
	  * Calculate the cost of all items in the cart
	  * @access public
	  * @return float
	  *
	  */
	public function calculate_cost() 
	{ 	
	 	$cost = 0.00;
	 	
	 	foreach($this->content AS $pro_id => $quantity) 
		{	
	 		//$cost = $cost + ($product -> price * $quantity);
			
			# Instantiate the object from the class.
			$product = new __product_model();

			# Pass the parameter and access the method in the class.
			$product = $product->get_product($pro_id);
			
			# Calculate the total cost.
			$cost = $cost + ($product -> pro_price * $quantity);
	 	}
	 	
	 	return number_format($cost, 2);
		//return $cost_float; 	
	}	 
}

I have tried to create a multidimensional array to pass the function of time() into the class method of add_item(), as below, but it generate an error message when an previous item is already set in the session/ array.

public function add_item($pro_id,$time) 
	{
	 	if (isset($this->content[$pro_id])) 
		{
	 	    
			//$this->content[$pro_id]++;
			$this->content[$pro_id] = array();
			$this->content[$pro_id]['q'] = $this->content[$pro_id]['q'] + 1;
			$this->content[$pro_id]['t'] = $time;
	 	} 
		else 
		{
	 		//$this->content[$pro_id] = 1;
			
			$this->content[$pro_id] = array();
			$this->content[$pro_id]['q'] = 1;
			$this->content[$pro_id]['t'] = $time;
			
	 	}
		//print_r($this->content);
	}

result:

Notice: Undefined index: q in C:\wamp\www\…

This is the live test site (without the error above) to show u what I intend to achieve,
http://lauthiamkok.net/tmp/php/cart/cart.php?pro_id=1

(note: you need to add the item by changing the value of pro_id from 1 to 4 so that u can see the shopping cart. bcos the index page won’t work on this live site for some reason, with this line of code,

$store = $object_store -> get_store();

but it works perfectly on my localhost!

this is the code to get the list of the items on the index page,

<?php
$object_store = new __store_model();

$store = $object_store -> get_store();

foreach ($store as $product)
{
	$product = new __product_entity($product);
?>
	<li><?php echo $product -> pro_title;?> by <?php //echo $product -> pro_author;?>: &pound;<?php echo $product -> pro_price;?><br />
		<a href="cart.php?pro_id=<?php echo $product -> pro_id;?>">Add to cart</a>
	</li>

<?php
}

?>

)

Many thanks!

Lau

thank you. at least now I know it’s nothing wrong with my script! :rofl:

thanks!:slight_smile:

I put the code above at the top of your script in my index.php but no error reporting is shown on the page.

My live server is running php version 5.2.8 while my localhost is on 5.3

does it make any different??

yes found the error with the line of code above!

it says,

Fatal error: Call to undefined method mysqli_result::fetch_all() in /home/sites/www.lauthiamkok.net/html/tmp/php/cart/class_lib.php  on line 26

but why is that? my localhost doesnt display that error at all!??

what’s wrong with this method in my database class?

#fetches all result rows as an associative array, a numeric array, or both
	public function fetch_all($query) 
	{
		$result = $this -> connection -> query($query);
		if($result) 
		{
			return $result -> fetch_all(MYSQLI_ASSOC);
		} 
		else
		{
			$this -> error = $this -> connection -> error;
			return false;
		}
	}

this the entire code of database class,

#connects the database and handling the result
class __database {
	
	protected $connection = null;
	protected $error = null;

	#make a connection
	public function __construct($hostname,$username,$password,$database)
	{
		$this -> connection = new mysqli($hostname,$username,$password,$database);
		
		if (mysqli_connect_errno()) 
		{
			printf("Connect failed: %s\
", mysqli_connect_error());
			exit();
		}
	}
        
	#fetches all result rows as an associative array, a numeric array, or both
	public function fetch_all($query) 
	{
		$result = $this -> connection -> query($query);
		if($result) 
		{
			return $result -> fetch_all(MYSQLI_ASSOC);
		} 
		else
		{
			$this -> error = $this -> connection -> error;
			return false;
		}
	}
	
	#fetches a result row as an associative array, a numeric array, or both
	public function fetch_assoc_while($query)
	{
		$result = $this -> connection -> query($query);
		if($result) 
		{
			while($row = $result -> fetch_assoc())
			{
				$return_this[] = $row;
			}

			if (isset($return_this))
			{
				return $return_this;
			}
			else
			{
				return false;
			}
		}
		else
		{
			$this -> error = $this -> connection -> error;
			return false;
		}
	}
		
	#fetch a result row as an associative array
	public function fetch_assoc($query)
	{
		$result = $this -> connection -> query($query);
		if($result) 
		{
			return $result -> fetch_assoc();
		} 
		else
		{
			$this -> error = $this -> connection -> error;
			return false;
		}
	}
		
	#get a result row as an enumerated array
	public function fetch_row($query)
	{
		$result = $this -> connection -> query($query);
		if($result) 
		{
			return $result -> fetch_row();
		} 
		else
		{
			$this -> error = $this -> connection -> error;
			return false;
		}
	}
	
	#get the number of rows in a result
	public function num_rows($query)
	{
		$result = $this -> connection -> query($query);
		if($result) 
		{
			return $result -> num_rows;
		} 
		else
		{
			$this -> error = $this -> connection -> error;
			return false;
		}
	}
	
	#performs a query on the database
	public function query($query)
	{
		$result = $this -> connection -> query($query);	
		if($result) 
		{
			return $result;
		} 
		else
		{
			$this -> error = $this -> connection -> error;
			return false;
		}

	}
	
	#escapes special characters in a string for use in a SQL statement, taking into account the current charset of the connection
	public function real_escape_string($string)
	{
		$result = $this -> connection -> real_escape_string($string);	
		if($result) 
		{
			return $result;
		} 
		else
		{
			$this -> error = $this -> connection -> error;
			return false;
		}

	}
         
	#display error
	public function get_error() 
	{
		return $this -> error;
	}
	
	#closes the database connection when object is destroyed.
    public function __destruct()
    {
        $this -> connection -> close();
    }
}

many thanks!

not sure if I know to do that but I do some research! :smiley:

thanks!

thanks for the hint! will do that! :slight_smile:

and i thought that it would make the classes look a bit different by prefixing them with two underscores… I’m probably wrong! :stuck_out_tongue:


...
$this->content[$pro_id] = array(); 
$this->content[$pro_id]['q'] = $this->content[$pro_id]['q'] + 1; 
...

Here, you are reading an index that clearly can’t exist. The difference between you test environment and the production server is probably how your error reporting is configured. Stick this at the top of your script:


error_reporting(E_ALL);

By the way - Why are you prefixing your class names with two underscores? That’s a very peculiar and quite non-standard thing to do.

You might want to create an extension of __database which overrides the database functions to use normal MySQL functions, and switch to it in your application if mysqlnd isn’t available.

How about adding this too, right after the error_reporting(E_ALL)?

ini_set('display_errors', 2);

Looks like you don’t have the mysqlnd driver installed. If you don’t have server access, try contacting your host.