Products and Categories [ 78 ] private $metakeywords; private $metadescription; private $metarobots; private $active; private $secure; private $activeProduct = false; // Our constructor takes two arguments: the registry, so it can use // it, and the product path, so it can try and lookup the product // in question. The first thing the constructor does, is check if // the path is set to something, and try and perform a lookup. public function __construct( PHPEcommerceFrameworkRegistry $registry, $productPath ) { $this->registry = $registry; if( $productPath != '' ) { $productPath = $this->registry->getObject('db')-> sanitizeData( $productPath ); // The lookup query is quite long because there are quite a few // tables involved relating the content, versions, products and // content type tables. $productQuery = "SELECT v.name AS product_name, c.ID AS product_id, p.image AS product_image, p.stock AS product_stock, p.weight AS product_weight, p.price AS product_price, p.SKU AS product_sku, p.featured AS product_featured, v.heading AS product_heading, v.content AS product_description, v.metakeywords AS metakeywords, v.metarobots AS metarobots, v.metadescription AS metadescription FROM content_versions v, content c, content_types t, content_types_products p WHERE c.active=1 AND c.secure=0 c.type=t.ID AND t.reference='product' AND p.content_version=v.ID AND v.ID=c.current_revision AND c.path='{$productPath}'"; //echo $productQuery; $this->registry->getObject('db')-> executeQuery( $productQuery ); // The query is then executed, and if there is a record, // appropriate object variables are set. if( $this->registry->getObject('db')->numRows() == 1 ) { // tells the controller we have a product! $this->activeProduct = true; This material is copyright and is licensed for the sole use by jackie tracey on 23rd February 2010 953 Quincy Drive, , Brick, , 08724 Chapter 3 [ 79 ] // grab the product data, and associate it with the relevant // fields for this object $data = $this->registry->getObject('db')->getRows(); $this->ID = $data['product_id']; $this->name = $data['product_name']; $this->price = $data['product_price']; $this->weight = $data['product_weight']; $this->image = $data['product_image']; $this->heading = $data['product_heading']; $this->description = $data['product_description']; $this->SKU = $data['product_sku']; $this->stock = $data['product_stock']; // secure and active were set in the query, we will probably // want to change this later $this->secure = 0; $this->active = 1; $this->metakeywords = $data['metakeywords']; $this->metadescription = $data['metadescription']; $this->metarobots = $data['metarobots']; } } else { // here we may want to do something else } } So far, we only need two simple methods: one for the controller to check the product is valid, and one to return the data from the model. This works by returning any object variable that isn't an object itself, in a single array. public function isValid() { return $this->activeProduct; } public function getData() { $data = array(); foreach( $this as $field => $fdata ) { if( ! is_object( $fdata ) ) { $data[ $field ] = $fdata; } } return $data; } This material is copyright and is licensed for the sole use by jackie tracey on 23rd February 2010 953 Quincy Drive, , Brick, , 08724 Products and Categories [ 80 ] /* Also useful: getters and setters for various fields, as well as a save method, to update a database entry */ } ?> View We can build the view using the following snippet: <h2>{product_name}</h2> {product_description} <p>Cost: £{product_price}, number in stock {product_stock} . Weight: {product_weight}Kg.</p> <p> <img src="product_images/{product_image}" alt="{product_name} image" /> </p> If we were to create records in the database for a product, to view the product we would need to visit http://localhost/path/to/our/framework/products/view/ product-path. This material is copyright and is licensed for the sole use by jackie tracey on 23rd February 2010 953 Quincy Drive, , Brick, , 08724 Chapter 3 [ 81 ] Controller The controller needs to include our product model, pass the URL path (with the exception of products/view/, which is used by the controller to determine what operation we are performing) to it, and if a valid product is represented by the model, display it; if not, then it needs to display a "Product not found" page. The following code handles this nicely for us, and as with our product model, will be extended quite a lot as we progress with our framework. Both this and the model take the framework's registry as a parameter in the constructor; this ensures the objects know of the registry, and allows them to store a reference to it themselves. The controller's constructor also has a directCall parameter, to indicate if the controller is being accessed directly by the framework, or from another controller, to embed or extend functionality. <?php /** * Products Controller * * @author Michael Peacock * @version 1.0 */ class Productscontroller{ /** * Registry object reference */ private $registry; /** * Product model object reference */ private $model; /** * Controller constructor - direct call to false when being embedded * via another controller * @param PHPEcommerceFrameworkRegistry $registry our registry * @param bool $directCall - are we calling it directly via the * framework (true), or via another controller (false) */ public function __construct( PHPEcommerceFrameworkRegistry $registry, $directCall ) { $this->registry = $registry; This material is copyright and is licensed for the sole use by jackie tracey on 23rd February 2010 953 Quincy Drive, , Brick, , 08724 Products and Categories [ 82 ] if( $directCall == true ) { $this->viewProduct(); } } /** * View a product * @return void */ private function viewProduct() { When viewing a product, the URL path is taken, and the controller-specic part of that (products/view/, which instructs the controller that the user wishes to view a product) is removed, leaving us with the product's path. This path is then passed in the constructor to the product model, which looks up the appropriate data. $pathToRemove = 'products/view/'; $productPath = str_replace( $pathToRemove, '', $this-> registry->getURLPath() ); require_once( FRAMEWORK_PATH . 'models/products/model.php'); $this->model = new Product( $this->registry, $productPath ); if( $this->model->isValid() ) { // Assuming the model is valid, the controller builds the view, // and populates the view with data. $productData = $this->model->getData(); $this->registry->getObject('template')-> dataToTags( $productData, 'product_' ); $this->registry->getObject('template')->getPage()-> addTag( 'metakeywords', $productData['metakeywords'] ); $this->registry->getObject('template')->getPage()-> addTag( 'metadescription', $productData['metadescription'] ); $this->registry->getObject('template')->getPage()-> addTag( 'metarobots', $productData['metarobots'] ); $this->registry->getObject('template')-> buildFromTemplates('header.tpl.php', 'product.tpl.php', 'footer.tpl.php'); $this->registry->getObject('template')->getPage()-> setTitle('Viewing product' . $productData['name'] ); } This material is copyright and is licensed for the sole use by jackie tracey on 23rd February 2010 953 Quincy Drive, , Brick, , 08724 . $this->registry->getObject('template')-> buildFromTemplates('header.tpl .php& apos;, 'product.tpl .php& apos;, 'footer.tpl .php& apos;); $this->registry->getObject('template')->getPage()->. material is copyright and is licensed for the sole use by jackie tracey on 23rd February 2010 953 Quincy Drive, , Brick, , 08724 Chapter 3 [ 79 ] // grab the product data, and associate it with. material is copyright and is licensed for the sole use by jackie tracey on 23rd February 2010 953 Quincy Drive, , Brick, , 08724 Products and Categories [ 80 ] /* Also useful: getters and setters