Categories
HTML

Improving your Views

So far, we have user very minimalistic views to prove that our application works. However, if we ever want to roll out a product that will be used by anyone, it has to provide a feeling of being well-built. And if it looks bad, it does not feel well-built.

Let’s start using Bootstrap to make our views look better.

Using Bootstrap

We will start by proposing a base template for views. When you create a new view, it should automatically contain this material in order to provide the wanted look and feel:

  1. <!doctype html>
  2. <html lang="en">
  3.   <head>
  4.     <!-- Required meta tags -->
  5.     <meta charset="utf-8">
  6.     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  7.  
  8.     <!-- Bootstrap CSS -->
  9.     <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
  10.  
  11.     <title>TITLE</title>
  12.   </head>
  13.   <body>
  14.     <div class='container'>
  15.       <h1>HEADING</h1>
  16.  
  17.       <!-- Optional JavaScript -->
  18.       <!-- jQuery first, then Popper.js, then Bootstrap JS -->
  19.       <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
  20.       <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
  21.       <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
  22.     </div>
  23.   </body>
  24. </html>

Buttons, submit inputs and hyperlinks

All we need to do now in integrate the proper classes on the proper elements to make them look better. The first category is that of buttons (see https://getbootstrap.com/docs/4.0/components/buttons/):

  1. <button type="button" class="btn btn-primary">Primary</button>
  2. <button type="button" class="btn btn-secondary">Secondary</button>
  3. <button type="button" class="btn btn-success">Success</button>
  4. <button type="button" class="btn btn-danger">Danger</button>
  5. <button type="button" class="btn btn-warning">Warning</button>
  6. <button type="button" class="btn btn-info">Info</button>
  7. <button type="button" class="btn btn-light">Light</button>
  8. <button type="button" class="btn btn-dark">Dark</button>
  9.  
  10. <button type="button" class="btn btn-link">Link</button>

The class='btn btn-BUTTONTYPE' attribute definition is what will give the button appearance to any submit input, button, or hyperlink that you want. Therefore, the following all have a button appearance:

  1. <a href="CSTutoring.ca" class="btn btn-primary">CSTutoring.ca</a>
  2. <button type="button" class="btn btn-secondary">Secondary</button>
  3. <input type="submit" class="btn btn-success" value="Submit" />

Form Inputs

For forms to look adequate for a serious application, there are few modifications to make (see https://getbootstrap.com/docs/4.0/components/forms/):

  1. <div class="form-group">
  2.     <label for="exampleInputEmail1">Email address</label>
  3.     <input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Enter email">
  4.     <small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
  5.   </div>

Two changes are essential: 1) apply class="form-group" to a div element containing the label and input elements and 2) apply class="form-control" to the input elements (except type submit that you will format as a button, as above).

Tables

Bootstrap can really help with the appearance of tables (see https://getbootstrap.com/docs/4.4/content/tables/). My preferred type is the striped table as below:

  1. <table class="table table-striped">
  2. ...
  3. </table>

Custom CSS and JS

In the PHP MVC application structure proposed and used in this series of posts, it is possible to use custom CSS and JS, referred through script and link elements of your views. You can simply create css and js folders under the Web server document root. The current .htaccess configuration is made to allow access to all the contained resources.

  • htdocs: contains index.php and the folders below
    • app: contains all models, views and controllers as well as core files.
    • css: add your custom CSS
    • js: add your custom JavaScript

Conclusion

For data-centric applications, it doesn’t take that much to make the application look acceptable. If anything, at least take the time to apply a Bootstrap theme on your application.

Categories
MVC PHP

An Introduction to Models

To complete the PHP MVC trio, we must take a look at Model classes. Model classes provide data access and modification functionality to MVC applications, regardless of what the data source is. In other words, the way that the Model classes are used should not reveal to the Controller classes what type of data storage medium is being used. All we wish to provide to the Controller classes is an interface to create, read, delete, and update information. And, by default, our Model classes will perform these CRUD operations in databases.

A Model Base Class

As was done with the Controller base class to provide core functionality to Controller classes, we wish to provide the base functionality to Model classes through a Model base class. In our case, this base functionality will be to connect to a MySQL-compatible database. So, to /app/core, we add Model.php:

class Model{
  protected static $_connection = null;
  public function __construct(){
    if(self::$_connection == null){
      $user = 'root';
      $password = '';
      $host = 'localhost';
      $DBName = 'test';
      self::$_connection =  new PDO("mysql:host=$host;dbname=$DBName", $user, $password);
    }
  }
}

In the above, we declare and initialize a static attribute $_connection. Static attributes are attributes of the class; only one instance of this attribute exists for the entire set of all objects in this class, i.e., one $_connection for all objects deriving from class Model. Then, one the first run of the constructor for the class, when $_connection is null, it is set to a PDO object connected to a MySQL database, called test, hosted on localhost (the same computer as the one running the PHP, which is your computer if you are running XAMPP locally). The connection is done through the ‘root’ user which has no password, by default, in the XAMPP MySQL installation. You should definitely change these settings!

Let’s not forget to adjust dependencies… modify your app/init.php file to add the new Model class:

<?php
  require_once 'core/App.php';
  require_once 'core/Controller.php';
  require_once 'core/Model.php';
?>

Building a Model Subclass

For each table in our database, we will wish to build one Model class. We say that these are Model classes, and this is semantically true. In this specific example, they are effectively subclasses of our Model class. To continue our example, we build a model for Item in the Item.php file in the /app/models folder:

class Item extends Model{
  var $name;
  public function get(){
    $SQL = 'SELECT * FROM ITEM';
    $stmt = self::$_connection->prepare($SQL);
    $stmt->execute();
    $stmt->setFetchMode(PDO::FETCH_CLASS, 'Item');
    return $stmt->fetchAll();
  }
}

In the Item model, we define a $name attribute, such that all objects of this class have this property. Then, the get() method is declared to run a SELECT * FROM ITEM query in the database. The query is defined, then prepared (this will become more useful further along as you read), to then be executed. Then, since SELECT is a read command, there will be records to fetch, we set the fetch mode to return objects of the Item class (this class). Finally, we return an array of Item objects, each representing the records read from the database.

The Database to Match

To complete this example, we must create an Item table in our test database, and have the records have item_id (for instance) and name fields. To accomplish this, go back to your xampp control panel, if this is what you are using, and on the MySQL line, click Start and, once MySQL is highlighted green, click Admin; this will open an instance of phMyAdmin.

If you have a test database in the left menu, click on it (otherwise, you certainly know how to add one). You should be prompted to add a table, if not, expand the test database in the left structure and click on New table.

At the top left, name the table Item. Let’s add the item_id field first by typing that name in the Name column and selecting the checkbox in the A_I colunm (if anything pops up, just click OK). Now let’s add the name of the item by adding name on the following line’s Name column, in the type column, select VARCHAR, in the Size colunm, enter the value 50. Click Save at the bottom right.

Now let’s add test data to the table. Click the Insert tab in the top tabs row. For example, insert ‘milk’ and ‘cookies’ in the Value column for the name field. Click one of the execute buttons on the right.

Making it Work

If you followed along with the posts and implemented the HomeController class as in Controller Classes and An Introduction to Views, all script elements can be called through your browser at http://localhost/ and display your items from the database Item table.