Intro to Web Development

Code examples from class

github repo for CS401

Senior Seminar Presentation

ss2016.ppt

ss2014.ppt

Web Design Considerations

Web Development Best Practices & Tips

Writing Code:

Performance:

Security:

Web Typography

Video: Jason Santa Maria - On Web Typography

PHP configuration information

<?php phpinfo(); ?>

PHP array tips

<?php 

// PHP arrays can contain almost any data type 
$stuff = array("Hello world!"'C', new Thing(), array(123), 3.14);>   

// can be numerically indexed or associative (indexed with strings)
$fruit = array("red" => array("cherry""strawberry""raspberry"),
               
"purple" => array("grape""eggplant"),
               
"yellow" => array("banana""lemon""pineapple"));

// can be treated like an array, hashmap, linked list, stack, etc
array_pop($fruit); // removes and returns the "yellow" element

// There are like a bajillion built-in array functions.
// For example: sorts an array, maintaining key association.
asort($fruit); 
// checks if the given key or index exists
array_key_exists("blue"$fruit);

// Shorthand for adding an element onto the end of an array.
// I use this ALL THE TIME, especially in loops.
$stuff[] = "more stuff";



Read from a file and output to an HTML table

conrad|32|rocky road
robby|29|chocolate fudge
adam|23|vanilla
clayton|25|red bean
ben|12|phish food

<html>
  <head>HTML table example</head>
  <body>
  <?php 
    $data 
file("data.txt"); // read file lines into an array ?>
    <table border="1"> <!-- add a border using a style sheet instead -->
    <?php 
      
foreach ($data as $student) { // loop over lines ?>
        <tr> <!-- begin table row -->
        <?php 
          $line 
explode("|"$student); // split line into array
          
foreach ($line as $item) { // loop over items found in each line ?>
          <td><?php echo $item?></td> <!-- column containing data -->
        <?php ?>
      </tr> <!-- end table row -->
    <?php ?>
    </table>
  </body>
</html>

PHP default function arguments

<?php

  
function student ($name$major "Computer Science") {
    echo 
"$name\n";
    echo 
"$major\n"// will echo 'Computer Science'
  
}

  
student("Conrad Kennington");

PHP class example with static variables shared between instances

<?php

class Lockbox {
  
  private 
$key false;
  static private 
$available true;
  static private 
$locked false;

  public function 
__construct () {
    
// no-op
  
}

  public function 
getKey () {
    if (
self::$available) {
      
$this->key true
      
self::$available false
      echo 
"I now have the key!\n";
    } else {
      echo 
"Sombody else already has the key!\n";
    }
  }

  public function 
unlock () {
    if (
$this->key) {
      
self::$locked false;
      echo 
"I unlocked it!\n";
    } else {
      echo 
"I can't inlock it, I don't have the key!\n";
    }
  }

  public function 
lock () {
    if (
$this->key) {
      
self::$locked true;
      echo 
"I locked it!\n";
    } else {
      echo 
"I can't unlock it, I need the key!\n";
    }
  }

// end Lockbox

// sample usage
$alice = new Lockbox();
$bob = new Lockbox();

$alice->getKey(); // I now have the key!
$bob->getKey(); // Sombody else already has the key!
$bob->lock(); // I can't lock it, I need the key!
$alice->lock(); // I locked it!
$bob->unlock(); // I can't unlock it. I don't have the key!
$alice->unlock(); // I unlocked it!

PHP - check user permissions on a "members only" page using serialized User object from a file

O:4:"User":4:{s:10:"^@User^@name";s:6:"Conrad";s:11:"^@User^@email";s:31:"conradkennington@boisestate.edu";s:17:"^@User^@permissions";a:2:{i:0;s:6:"MEMBER";i:1;s:5:"GUEST";}s:8:"^@User^@id";N;}
O:4:"User":4:{s:10:"^@User^@name";s:7:"Gandalf";s:11:"^@User^@email";s:23:"thegray@middleearth.edu";s:17:"^@User^@permissions";a:3:{i:0;s:6:"MEMBER";i:1;s:5:"GUEST";i:2;s:5:"ADMIN";}s:8:"^@User^@id";N;}
O:4:"User":4:{s:10:"^@User^@name";s:6:"Sauron";s:11:"^@User^@email";s:17:"theeye@mordor.net";s:17:"^@User^@permissions";a:1:{i:0;s:5:"GUEST";}s:8:"^@User^@id";N;}

<?php
class User {

  const 
GUEST "GUEST";
  const 
MEMBER "MEMBER";
  const 
ADMIN "ADMIN";

  private 
$name;
  private 
$email;
  private 
$permissions;

  public function 
__construct ($name$email$permissions = array()) {
    
$this->name $name;
    
$this->email $email;
    
$this->permissions $permissions;
  }

  public function 
getEmail() {
    return 
$this->email;
  }

  public function 
hasPermission ($permission){
    
// return true if permission is found
    
return in_array($permission$this->permissions);
  }

// end User

<?php

require_once "User.php";

class 
Dao {

  
// file containing serialized User objects
  
private $usersFile "users.txt";

  public function 
getUser ($email) {
    
$users file($this->usersFile);

    foreach (
$users as $user) {
      
// recreate User object
      
$user unserialize($user);
      if (
$email == trim($user->getEmail())) {
        
// user email found, return the object
        
return $user;
      }
    }
    throw new 
Exception("User not found");
  }

// end Dao

<?php
// this page requires a user with the MEMBER permission to view
require_once "Dao.php";

$dao = new Dao();
try {
  
// get the user object from the data store
  
$user $dao->getUser("theeye@mordor.net");
  if (
$user->hasPermission(User::MEMBER)) {
    echo 
"User has the permission";
  } else {
    echo 
"User does NOT have the permission";
  }

} catch (
Exception $e) {
  echo 
$e->getMessage();
}

?>

<html>
  <head></head>
  <body>
    <!-- page content for members only-->
  </body>
</html>

Superhero Database

create table person (id int not null auto_increment primary key, name varchar(32) not null, 
  gender varchar(1), alter_ego varchar(32), good BIT, date_entered date);
create table power (id int not null auto_increment primary key, power varchar(16) not null);
create table person_power (person_id int not null, power_id int not null, primary key (person_id, power_id);
insert into person (name, gender, alter_ego, good) values ('Ironman', 'M', 'Tony Stark', 1);
insert into person (name, gender, alter_ego, good) values ('Hulk', 'M', 'Bruce Banner', 1);
insert into person (name, gender, alter_ego, good) values ('Storm', 'F', 'Ororo Munroe', 1);
insert into power (power) values ('Fly');
insert into power (power) values ('Strength');
insert into power (power) values ('Laser Vision');
select * from person where gender = 'M';
update person set gender = 'F', name = 'She-Hulk' where name = 'Hulk';
delete from person where name = 'She-Hulk';
insert into person_power (person_id, power_id) values (1, 1);
insert into person_power (person_id, power_id) values (1, 2);
insert into person_power (person_id, power_id) values (2, 2);
select name from person join person_power on person.id = 
  person_power.person_id join power on power.id = person_power.power_id where power.power = 'Strength';

PHP/MySQL save and display comments

<?php
  
// index.php
  // This page has a comment form for posting, and a list of comments from MySQL
  
require_once "Dao.php";
  
$dao = new Dao();
?>

<html>
  <head>
    <title>List of Products</title>
    <link rel="stylesheet" type="text/css" href="comment.css">
  </head>
  <body>
    <form name="commentForm" action="handler.php" method="POST">
      <div>
        Leave a comment: <input type="text" name="comment">
      </div>
      <div>
        <input type="submit" name="commentButton" value="Submit">
      </div>
      <input type="hidden" name="form" value="comment">
    </form>
    <?php
    $comments 
$dao->getComments();
    echo 
"<table>";
    foreach (
$comments as $comment) {
      echo 
"<tr>";
      echo 
"<td>" $comment["comment"] . "</td>";
      echo 
"<td>" $comment["created"] . "</td>";
      echo 
"</tr>";
    }
    echo 
"</table>";
    
?>
  </body>
</html>


<?php
// handler.php
// handle comment posts, saving to MySQL and redirecting back to the list
require_once "Dao.php";

  if (isset(
$_POST["commentButton"])) {
    
$comment $_POST["comment"];

    try {
      
$dao = new Dao();
      
$dao->saveComment($comment);
    } catch (
Exception $e) {
      
var_dump($e);
      die;
    }
   }
  
header("Location:index.php");

<?php
// Dao.php
// class for saving and getting comments from MySQL
class Dao {

  private 
$host "localhost";
  private 
$db "ckenning";
  private 
$user "ckenning";
  private 
$pass "password";

  public function 
getConnection () {
    return
      new 
PDO("mysql:host={$this->host};dbname={$this->db}"$this->user,
          
$this->pass);
  }

  public function 
saveComment ($comment) {
    
$conn $this->getConnection();
    
$saveQuery =
        
"INSERT INTO comment
        (comment)
        VALUES
        (:comment)"
;
    
$q $conn->prepare($saveQuery);
    
$q->bindParam(":comment"$comment);
    
$q->execute();
  }

  public function 
getComments () {
    
$conn $this->getConnection();
    return 
$conn->query("SELECT * FROM comment");
  }
// end Dao

PHP/MySQL upload an image, and generate links to details

<?php
// products.php
// This page lists products and generates links with an id in the query string
require_once "Dao.php";
$dao = new Dao();
$products $dao->getProducts();

?>

<html>
  <body>
    <ul>
    <?php foreach ($products as $product) {
      echo 
"<li><a href='product/details.php?id=" $product["id"] . "'>" .
        
$product["name"] . "</a></li>";
    } 
?>
    </ul>
    <a href="/product/add.html">Add a product</a>
  </body>
</html>

<!-- product/add.html -->
<html>
  <head><title>Add a product</title></head>
  <body>
     <form action="upload.php" method="POST" enctype="multipart/form-data">
        <div>
          <label for="name">Product Name:</label>
          <input type="text" name="name"/>
        </div>
        <div>
        <label for="name">Product Description:</label>
        <input type="text" name="description"/>
        </div>
        <div>
          <label for="file">Image:</label>
          <input type="file" name="file" id="file"><br>
          <input type="submit" name="submit" value="Submit">
        </div>
     </form>
  </body>
</html>

<?php
  
// product/upload.php
  
require_once "../Dao.php";
  
$dao = new Dao();

  
// save a product, including name, description, and an image path
  
$name = (isset($_POST["name"])) ? $_POST["name"] : "";
  
$description = (isset($_POST["description"])) ? $_POST["description"] : "";

  
$imagePath "";
  if (
count($_FILES) > 0) {
    if (
$_FILES["file"]["error"] > 0) {
      throw new 
Exception("Error: " $_FILES["file"]["error"]);
    } else {
      
$basePath "/Users/crk/projects/cs497/src/www";
      
$imagePath "/product/images/" $_FILES["file"]["name"];
      if (!
move_uploaded_file($_FILES["file"]["tmp_name"], $basePath $imagePath)) {
        throw new 
Exception("File move failed");
      }
    }
  }
  
$dao->saveProduct($name$description$imagePath);
  
header("location:http://cs497/products.php");

<?php
  
// products/detail.php
  // Gets an id from the query string to look up the product in MySQL
  
require_once "../Dao.php";
  
$dao = new Dao();

  
$id $_GET["id"];
  
$product $dao->getProduct($id);

  echo 
"<h2>Details for " $product["name"] . ": " $product["description"] .
    
"</h2>";?>
    <img src="<?php echo $product["image_path"]; ?>" />
    <div>
      <a href="/products.php">Back to Product List</a>
    </div>

<?php
// Dao.php
// class for getting products in MySQL
class Dao {

  private 
$host "localhost";
  private 
$db "ckenning";
  private 
$user "ckenning";
  private 
$pass "password";

  public function 
getConnection () {
    return
      new 
PDO("mysql:host={$this->host};dbname={$this->db}"$this->user,
          
$this->pass);
  }

  public function 
getProducts () {
    
$conn $this->getConnection();
    return 
$conn->query("SELECT id, name FROM product");
  }

  public function 
getProduct ($id) {
    
$conn $this->getConnection();
    
$getQuery "SELECT id, name, description, image_path FROM product WHERE id = :id";
    
$q $conn->prepare($getQuery);
    
$q->bindParam(":id"$id);
    
$q->execute();
    return 
reset($q->fetchAll());
  }

  public function 
saveProduct ($name$description$imagePath) {
    
$conn $this->getConnection();
    
$saveQuery =
        
"INSERT INTO product
        (name, description, image_path)
        VALUES
        (:name, :description, :imagePath)"
;
    
$q $conn->prepare($saveQuery);
    
$q->bindParam(":name"$name);
    
$q->bindParam(":description"$description);
    
$q->bindParam(":imagePath"$imagePath);
    
$q->execute();
  }

// end Dao

PHP login session, form preset, and status

<?php
// login.php
session_start();

  if (isset(
$_SESSION["access_granted"]) && $_SESSION["access_granted"]) {
    
header("Location:granted.php");
  }

  
$email "";
  if (isset(
$_SESSION["email_preset"])) {
    
$email $_SESSION["email_preset"];
  }
?>

<html>
  <head></head>
  <body>
    <h3>Login to my Secret System</h3>
    <?php
    
if (isset($_SESSION["status"])) {
      echo 
"<div id="status">" .  $_SESSION["status"] . "</div>";
      unset(
$_SESSION["status"]);
    }
    
?>
    <form action="login_handler.php" method="POST">
      <div>
        <label for="email">Email</label>
        <input type="text" name="email" id="email" value="<?php echo $email?>"/>
      </div>
      <div>
       <label for="password">Password</label>
        <input type="password" name="password" id="password" value=""/>
      </div>
      <div>
        <input type="submit" name="submit" id="login" value="Login"/>
      </div>
    </form>
  </body>
</html>

<?php
// login_handler.php
session_start();

// For simplification Lets pretend I got these login credentials from an SQL table.
if ("ckennington@gmail.com" == $_POST["email"] &&
    
"lollipop" == $_POST["password"]) {
  
$_SESSION["access_granted"] = true;
  
header("Location:granted.php");

} else {
  
$status "Invalid username or password";
  
$_SESSION["status"] = $status;
  
$_SESSION["email_preset"] = $_POST["email"];
  
$_SESSION["access_granted"] = false;

  
header("Location:login.php");
}
?>

<?php
// granted.php
session_start();

if (isset(
$_SESSION["access_granted"]) && !$_SESSION["access_granted"] ||
   !isset(
$_SESSION["access_granted"])) {
  
$_SESSION["status"] = "You need to log in first";
  
header("Location:login.php");
}

echo 
"ACCESS GRANTED";
?>
  
<a href="logout.php">Logout</a>

<?php
// logout.php
session_start();
session_destroy();
header("Location:login.php");
?>

AJAX using jQuery

// ajax.js file
$(function() {
$("#form").submit(function(){
    var values = $("form").serialize();
    var comment = $("#comment").val();
    console.log(values);
    $.ajax({
      type: "POST",
      url: "handlerAjax.php",
      data: values,
      success: function() {
        $("#comments tbody").prepend("<tr><td>" +
          comment + "</td><td>Just now</td></tr>");
        $("#comment").val("");
        $("#email").val("");
        $("#age").val("");
      },
      error: function () {
        alert("FAILURE");
      }
    });
    return false;
  });

});

<?php
// ajax.php file
session_start();
require_once 
"Dao.php";

$dao = new Dao();
$comments $dao->getComments();
?>

<html>
  <head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js" type="text/javascript"></script>
    <script src="js/ajax.js" type="text/javascript"></script>
    <link href="style.css" rel="stylesheet" type="text/css">
  </head>
  <body>
    <img src="moon.jpg" />
    <form id="form" method="POST"> <!-- notice that the form has no action -->
      <div class="pair">
        <label for="email">Enter your email:</label>
        <input type="text" id="email"
        <?php if (isset($_SESSION["email"])) {
          echo 
"value='{$_SESSION['email']}'";
        } 
?>
        name="email"/>
      </div>
      <div class="pair">
        <label for="comment">Leave a comment:</label>
        <input type="text" id="comment"
        <?php if (isset($_SESSION["comment"])) {
          echo 
"value='{$_SESSION['comment']}'";
        } 
?>
        name="comment"/>
      </div>
      <div class="pair">
        <label for="age">Enter your age:</label>
        <input type="text" id="age"
        <?php if (isset($_SESSION['age'])) {
          echo 
"value='{$_SESSION['age']}'";
        } 
?>
        name="age"/>
      </div>
      <div class="pair">
        <label for="age"></label>
        <input id="submit" type="submit"/><small>(You must be 18 to post)</small>
      </div>
    </form>
    </div>

    <table id="comments">
    <?php
    
foreach ($comments as $comment) {
      echo 
"<tr>";
      echo 
"<td>" $comment["comment"] . "</td>";
      echo 
"<td>" $comment["created"] . "</td>";
      echo 
"</tr>";
    }
    
?>
    </table>
  </body>
</html>

<?php
  
// handlerAjax.php file
  
require_once "Dao.php";

  
$dao = new Dao();
  
$dao->saveComment($_POST['comment'], $_POST['email']);
?>

Hashing passwords with a SHA256 + salt

<?php echo hash("sha256""password" "fKd93Vmz!k*dAv5029Vkf9$3Aa");