Building a Website with PHP, MySQL and jQuery Mobile, Part 2

This is the second part of a two-part tutorial, in which we use PHP, MySQL and jQuery mobile to build a simple computer web store. In the previous part we created the models and the controllers, and this time we will be writing our views.

jQuery mobile

First, lets say a few words about the library we will be using. jQuery mobile is a user interface library that sits on top of jQuery and provides support for a wide array of devices in the form of ready to use widgets and a touch-friendly development environment. It is still in beta, but upgrading to the official 1.0 release will be as simple as swapping a CDN URL.

The library is built around progressive enhancement. You, as the developer, only need to concern yourself with outputting the correct HTML, and the library will take care of the rest. jQuery mobile makes use of the HTML5 data- attributes and by adding them, you instruct the library how it should render your markup.

In this tutorial we will be using some of the interface components that this library gives us – listsheaderand footer bars and buttons, all of which are defined using the data-role attributes, which you will see in use in the next section.

Rendering Views

The views are PHP files, or templates, that generate HTML code. They are printed by the controllers using the render() helper function. We have 7 views in use for this website – _category.php_product.php,_header.php_footer.phpcategory.phphome.php and error.php, which are discussed later on. First, here is render() function:

includes/helpers.php

01 /* These are helper functions */
02
03 function render($template,$vars array()){
04
05     // This function takes the name of a template and
06     // a list of variables, and renders it.
07
08     // This will create variables from the array:
09     extract($vars);
10
11     // It can also take an array of objects
12     // instead of a template name.
13     if(is_array($template)){
14
15         // If an array was passed, it will loop
16         // through it, and include a partial view
17         foreach($template as $k){
18
19             // This will create a local variable
20             // with the name of the object's class
21
22             $cl strtolower(get_class($k));
23             $$cl $k;
24
25             include "views/_$cl.php";
26         }
27
28     }
29     else {
30         include "views/$template.php";
31     }
32 }

The first argument of this function is the name of the template file in the views/ folder (without the .phpextension). The next is an array with arguments. These are extracted and form real variables which you can use in your template.

There is one more way this function can be called – instead of a template name, you can pass an array with objects. If you recall from last time, this is what is returned by using the find() method. So basically if you pass the result of Category::find() to render, the function will loop through the array, get the class names of the objects inside it, and automatically include the _category.php template for each one. Some frameworks (Rails for example) call these partials.

Computer Store with PHP, MySQL and jQuery Mobile

Computer Store with PHP, MySQL and jQuery Mobile

The Views

Lets start off with the first view – the header. You can see that this template is simply the top part of a regular HTML5 page with interleaved PHP code. This view is used in home.php and category.php to promote code reuse.

includes/views/_header.php

01 <!DOCTYPE html>
02 <html>
03     <head>
04     <title><?php echo formatTitle($title)?></title>
05
06     <meta name="viewport" content="width=device-width, initial-scale=1" />
07
08     <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0b2/jquery.mobile-1.0b2.min.css" />
09     <link rel="stylesheet" href="assets/css/styles.css" />
10     <script type="text/javascript" src="http://code.jquery.com/jquery-1.6.2.min.js"></script>
11     <script type="text/javascript" src="http://code.jquery.com/mobile/1.0b2/jquery.mobile-1.0b2.min.js"></script>
12 </head>
13 <body>
14
15 <div data-role="page">
16
17     <div data-role="header" data-theme="b">
18         <a href="./" data-icon="home" data-iconpos="notext" data-transition="fade">Home</a>
19         <h1><?php echo $title?></h1>
20     </div>
21
22     <div data-role="content">

In the head section we include jQuery and jQuery mobile from jQuery’s CDN, and two stylesheets. The body section is where it gets interesting. We define a div with the data-role=”page” attribute. This, along with the data-role=”content” div, are the two elements required by the library to be present on every page.

The data-role=”header” div is transformed into a header bar. The data-theme attribute chooses one of the 5 standard themes. Inside it, we have a link that is assigned a home icon, and has its text hidden. jQuery Mobile comes with a set of icons you can choose from.

The closing tags (and the footer bar) reside in the _footer.php view:

includes/views/_footer.php

1     </div>
2
3     <div data-role="footer" id="pageFooter">
4         <h4><?php echo $GLOBALS['defaultFooter']?></h4>
5     </div>
6 </div>
7
8 </body>
9 </html>

Nothing too fancy here. We only have a div with the data-role=”footer” attribute, and inside it we print the globally accessible $defaultFooter variable, defined in includes/config.php.

Neither of the above views are printed directly by our controllers. They are instead used bycategory.php and home.php:

includes/views/home.php

01 <?php render('_header',array('title'=>$title))?>
02
03 <p>Welcome! This is a demo for a ...</p>
04 <p>Remember to try browsing this ...</p>
05
06 <ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b">
07     <li data-role="list-divider">Choose a product category</li>
08     <?php render($content) ?>
09 </ul>
10
11 <?php render('_footer')?>

If you may recall, the home view was rendered in the home controller. There we passed an array with all the categories, which is available here as $content. So what this view does, is to print the header, and footer, define a jQuery mobile listview (using the data-role attribute), and generate the markup of the categories passed by the controller, using this template (used implicitly by render()):

index.php/views/_category.php

1 <li <?php echo ($active == $category->id ? 'data-theme="a"' '') ?>>
2 <a href="?category=<?php echo $category->id?>" data-transition="fade">
3     <?php echo $category->name ?>
4     <span class="ui-li-count"><?php echo $category->contains?></span></a>
5 </li>

Notice that we have a $category PHP variable that points to the actual object this view is being generated for. This is done in lines 24/25 of the render function. When the user clicks one of the links generated by the above fragment, he will be taken to the /?category=someid url, which will show thecategory.php view, given below.

01 <?php render('_header',array('title'=>$title))?>
02
03 <div class="rightColumn">
04     <ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="c">
05         <?php render($products) ?>
06     </ul>
07 </div>
08
09 <div class="leftColumn">
10     <ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b">
11         <li data-role="list-divider">Categories</li>
12         <?php render($categories,array('active'=>$_GET['category'])) ?>
13     </ul>
14 </div>
15
16 <?php render('_footer')?>

This file also uses the header, footer and _category views, but it also presents a column with products (passed by the category controller). The products are rendered using the _product.php partial:

1 <li class="product">
2     <img src="assets/img/<?php echo $product->id ?>.jpg" alt="<?php echo $product->name ?>" />
3     <?php echo $product->name ?> <i><?php echo $product->manufacturer?></i>
4     <b>$<?php echo $product->price?></b>
5 </li>

As we have an image as the first child of the li elements, it is automatically displayed as an 80px thumbnail by jQuery mobile.

One of the advantages to using the interface components defined in the library is that they are automatically scaled to the width of the device. But what about the columns we defined above? We will need to style them ourselves with some CSS3 magic:

assets/css/styles.css

01 media all and (min-width650px){
02
03     .rightColumn{
04         width:56%;
05         float:right;
06         margin-left:4%;
07     }
08
09     .leftColumn{
10         width:40%;
11         float:left;
12     }
13
14 }
15
16 .product i{
17     display:block;
18     font-size:0.8em;
19     font-weight:normal;
20     font-style:normal;
21 }
22
23 .product img{
24     margin:10px;
25 }
26
27 .product b{
28     positionabsolute;
29     right15px;
30     top15px;
31     font-size0.9em;
32 }
33
34 .product{
35     height80px;
36 }

Using a media query, we tell the browser that if the view area is wider than 650px, it should display the columns side by side. If it is not (or if the browser does not support media queries) they will be displayed one on top of the other, the regular “block” behavior.

Reference : http://tutorialzine.com/2011/08/jquery-mobile-mvc-website-part-2/

Advertisements

2 thoughts on “Building a Website with PHP, MySQL and jQuery Mobile, Part 2

  1. Pingback: Best PHP and Mysql Video tutorials and More? « asKingMile

  2. Pingback: Building a Website with PHP, MySQL and jQuery Mobile, Part 1 « Chandara

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s