Appendix B. Solutions to Assignments

Table of Contents
Backend Programming
Assignments From the section called “Assignments BE.1”
Assignments From the section called “Assignments BE.2”
Assignments From the section called “Assignments BE.3”
Assignments From the section called “Assignments BE.4”
Assignments From the section called “Assignments BE.5”
Assignments From the section called “Assignments BE.6”
Assignments From the section called “Assignments BE.7”
Assignments From the section called “Assignments BE.8”
Assignments From the section called “Assignments BE.11”
IDE, Integrated Development Environments
Assignments From the section called “Assignments Laravel II”
Laravel / JavaScript project Uge 8/2019
JavaScript
Assignments From Chapter 19
Assignments From Chapter 20
Assignments From Chapter 21
Assignments From Chapter 22
Assignments From the section called “Assignments JS.11”
Assignments From the section called “Assignments JS.8”
Node.js
Assignments From Chapter 26
Databases
Assignments From the section called “Assignments DB.1”
Assignments From the section called “Assignments DB.2”
Assignments From the section called “Assignments DB.3”
Assignments From the section called “Assignments SQL Data I”
Assignments From the section called “Assignments SQL Data II”
Assignments From the section called “Assignments SQL Data III”
Assignments From the section called “Assignments SQL Views (SQL Data)”
Assignments From the section called “Assignments SQL Stored Procedures”
Assignments From the section called “Assignments SQL Triggers”
Assignments From the section called “Assignments Stored Procedures”
Assignments From the section called “Assignments SQL Functions”
XML
Assignments From the section called “Assignments XML.1”
Data Integration
Assignments From Chapter 48
Assignments From Chapter 49
Assignments From Chapter 50
Security
Assignments From Chapter 54
Assignments From Chapter 55
Assignments From Chapter 56

Backend Programming

Solutions

Assignment BE.0.0

Write a PHP program, be00.php, that uses two loops:

  1. One loop that creates an identity matrix. An identity matrix is a two dimensianal array where the number of rows is equal to the number of columns.

    The content of an identity matrix is zeroes (0) in all cells except the diagonal, [0][0], [1][1], [2][2], ..., [n][n], where the values are one, (1).

  2. Another loop that prints the identity matrix on your page.

No styling is needed, print your name and the assignment number as a headline.

Assignment BE.0.0 Model Solution
Example B.1. Identity Matrix, be00.php
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Identity Matrix</title>
    </head>
    <body>
        <?php
            ini_set("display_errors", "On");
            ERROR_REPORTING(E_ALL);
            // create n X n matrix
            function createMatrix(&$matrix, $n) {
                for ($i = 0; $i < $n; $i++) {        // down
                    for ($j = 0; $j < $n; $j++) {    // across
                        $matrix[$i][$j] = 0;
                    }
                }
                for ($i = 0; $i < count($matrix); $i++) {
                    $matrix[$i][$i] = 1;
                }
            }
            // read the n from GET
            // print a matrix
            function printMatrix($matrix) {
                print("\n        <p>\n");
                for ($i = 0; $i < count($matrix); $i++) {        // down
                    for ($j = 0; $j < count($matrix); $j++) {    // across
                        printf("%s ", $matrix[$i][$j]);
                    }
                    print("            <br/>\n");
                }
                print("        </p>\n");
            }
            $i = isset($_GET['antal']) ? $_GET['antal'] : 3;
            $arr = array();
            createMatrix($arr, $i);
            printMatrix($arr);
        ?>
    </body>
</html>

Assignment BE.0.1

Write a PHP program, be01.php, that takes three numbers as input from an HTML5 page, be01.html, with a form. The program must print the three numbers, and print "the biggest number is: " followed by the number.

No styling is needed, print your name and the assignment number as a headline on the php page.

Assignment BE.0.1 Model Solution
Example B.2. Max from Three be01.html
<?xml version="1.0" encoding="UTF-8"?>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>TODO supply a title</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    </head>
    <body>
        <form method="post" action="be01.php">
            <h1>Enter Three Integers</h1>
            <input type="text" name="no1"/>
            <input type="text" name="no2"/>
            <input type="text" name="no3"/>
            <input type="submit" name="sub"/>
        </form>
    </body>
</html>

Example B.3. Array from Many be01.php
<?php
    foreach($_POST as $key => $val) {
        if ($key != 'sub') {
            if (! is_numeric($val)) {
                header("Location: ./be01.xhtml");
            }
            $$key = (int)$val;
        }
    }
    
    $maximal = $no1;
    if ($no2 > $maximal) $maximal = $no2;
    if ($no3 > $maximal) $maximal = $no3;
?>
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
    <head>
        <meta charset="UTF-8">
        <title>MaxOfThree</title>
    </head>
    <body>
        <?php
            printf("<p>the biggest number is: %s</p>\n", $maximal);
        ?>
        <p>
            <a href="./be01.xhtml">Get new numbers</a>
        </p>
    </body>
</html>

Try it

Assignment BE.0.2

Write a PHP program, be02.php, that takes a variable number of numbers as input from an HTML5 page, be02.html, with a form. The program must

  1. Place the numbers in an array
  2. Print the array
  3. Write "The smallest number is: " followed by the number
  4. Write "The largest number is: " followed by the number

No styling is needed, print your name and the assignment number as a headline on the php page.

Assignment BE.0.2 Model Solution
Example B.4. Array from Many be02.html
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
    <head>
        <title>TODO supply a title</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <form method="post" action="be02.php">
            <h1>Enter Several Integers</h1>
            <input type="text" name="no1"/>
            <input type="text" name="no2"/>
            <input type="text" name="no3"/>
            <input type="text" name="no4"/>
            <input type="text" name="no5"/>
            <input type="text" name="no6"/>
            <input type="text" name="no7"/>
            <input type="text" name="no8"/>
            <input type="text" name="no9"/>
            <input type="text" name="no10"/>
            <input type="text" name="no11"/>
            <input type="text" name="no12"/>
            <input type="submit" name="sub"/>
        </form>
    </body>
</html>

Example B.5. Array from Many be02.php
<?php
    $myArray = array();
    foreach($_POST as $key => $val) {
        if ($key != 'sub') {
            if (! is_numeric($val)) {
                continue;
            }
            $myArray[] = (int)$val;
        }
    }
    
    $minValue = min($myArray);
    $maxValue = max($myArray);
?>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <?php
            printf("<p>The smallest number is: %s</p>\n", $minValue);
            printf("<p>The largest number is: %s</p>\n", $maxValue);
        ?>
        <p>
            <a href="./be02.html">Get new numbers</a>
        </p>
    </body>
</html>

Try it

Assignment BE.0.3

Take a look at this page. The code may be copied from the following:

<!doctype html>
<html>
    <head>
        <meta charset='utf-8'/>
        <style>
            h3 {
                margin-bottom: 0;
            }
            .spacer {
                margin-bottom: 1em;
            }
        </style>
        <script src='./js/triangles.js'></script>
    </head>
    <body>
        <h3>Triangular Code</h3>
        <div class='spacer' id='realestate'></div>
<?php
        if (isset($_POST['subm'])) {
            foreach ($_POST as $key => $val) {
                $$key = $val;
            }
            printf("D: (%s,%s)<br/>\n", $x1, $y1);
            printf("E: (%s,%s)<br/>\n", $x2, $y2);
            printf("F: (%s,%s)<br/>\n", $x3, $y3);

            // given coordinate sets xn,yn you must
            // calculate and print the angles in degrees
            // and the area of the triangle in this div

            // your code goes here
            require_once './includes/solution.inc.php';
            
            printf("<script>drawTriangle('realestate', %s, %s, %s, %s, %s, %s);</script>\n", 
                $x1, $y1, $x2, $y2, $x3, $y3);
        }    
?>
        <div class='spacer'></div>
        <form method="post" 
              action="<?php echo $_SERVER['PHP_SELF'];?>">
            <table>
                <tr>
                    <td>x1</td><td>y1</td><td>x2</td><td>y2</td><td>x3</td><td>y3</td>
                </tr>
                <tr>
                    <td><input type='text' name='x1' size='4'/></td>
                    <td><input type='text' name='y1' size='4'/></td>
                    <td><input type='text' name='x2' size='4'/></td>
                    <td><input type='text' name='y2' size='4'/></td>
                    <td><input type='text' name='x3' size='4'/></td>
                    <td><input type='text' name='y3' size='4'/></td>
                    <td><input type='submit' name='subm' value='Go!'/></td>
                </tr>
            </table>
        </form>
    </body>
</html>

There is a JavaScript file involved, download from here: triangles.js

You must do

  1. Create index.php from the shown code
  2. Download the JavaScript file
  3. Make the two work so that the page displays triangles without errors, given reasonable input ;)
  4. Locate the comment // your code goes here in the index-file. Now write the php code for the include file, it must display:
    • Lengths of the three sides of the triangle. You may use the Pythagorean theorem to calculate the result
    • The angles, in degrees, of the three angles. You may use the cosine relations in order to calculate the angles.

      cos C = (a2 + b2 - c2) / 2ab

    • The area of the triangle may be calculated as the

      square root of s(s-a)(s-b)(s-c)

      where s is the half circumference of a triangle with sides a, b, and c

Hints:

Here are a couple of hints. Remember all angle references in programming, nearly all, consider angles to be expressed in radians. 360 ° = 2π

  • The cosine function in PHP is cos($angleInRad)
  • The inverse of cosine in PHP acos($cosOfAngle)
  • PHP has a rad2deg($angleInRad) to convert radians to degrees
  • The inverse of rad2deg($angleInRad) is deg2rad($angleInDeg)
  • And the PHP square root is sqrt($somenumber)

No further styling is needed, print your name and the assignment number as a headline.

Assignment BE.0.3 Model Solution
Example B.6. Calculating Triangle Data index.php
<!doctype html>
<html>
    <head>
        <meta charset='utf-8'/>
        <style>
            h3 {
                margin-bottom: 0;
            }
            .spacer {
                margin-bottom: 1em;
            }
        </style>
        <script src='./js/triangles.js'></script>
    </head>
    <body>
        <h3>Triangular Code</h3>
        <div class='spacer' id='realestate'></div>
<?php
        if (isset($_POST['subm'])) {
            foreach ($_POST as $key => $val) {
                $$key = $val;
            }
            printf("D: (%s,%s)<br/>\n", $x1, $y1);
            printf("E: (%s,%s)<br/>\n", $x2, $y2);
            printf("F: (%s,%s)<br/>\n", $x3, $y3);

            // given coordinate sets xn,yn you must
            // calculate and print the angles in degrees
            // and the area of the triangle in this div

            // your code goes here
            require_once './includes/solution.inc.php';
            
            printf("<script>drawTriangle('realestate', %s, %s, %s, %s, %s, %s);</script>\n", 
                $x1, $y1, $x2, $y2, $x3, $y3);
        }    
?>
        <div class='spacer'></div>
        <form method="post" 
              action="<?php echo $_SERVER['PHP_SELF'];?>">
            <table>
                <tr>
                    <td>x1</td><td>y1</td><td>x2</td><td>y2</td><td>x3</td><td>y3</td>
                </tr>
                <tr>
                    <td><input type='text' name='x1' size='4'/></td>
                    <td><input type='text' name='y1' size='4'/></td>
                    <td><input type='text' name='x2' size='4'/></td>
                    <td><input type='text' name='y2' size='4'/></td>
                    <td><input type='text' name='x3' size='4'/></td>
                    <td><input type='text' name='y3' size='4'/></td>
                    <td><input type='submit' name='subm' value='Go!'/></td>
                </tr>
            </table>
        </form>
    </body>
</html>

Example B.7. Calculating Triangle Data solution.inc.php
<?php

function side($xa, $ya, $xb, $yb) {
    return sqrt(($xa-$xb)*($xa-$xb) + ($ya-$yb)*($ya-$yb));
}
function angle($a, $b, $c) {
    return rad2deg(acos(($a*$a + $b*$b - $c*$c) / (2 * $a * $b)));
}

$de = side($x1, $y1, $x2, $y2);
$ef = side($x2, $y2, $x3, $y3);
$fd = side($x1, $y1, $x3, $y3);

printf("<p>DE: %s<br/>\n", $de);
printf("EF: %s<br/>\n", $ef);
printf("FD: %s</p>\n", $fd);

printf("<p>D: %s<br/>\n", angle($de, $fd, $ef));
printf("E: %s<br/>\n", angle($de, $ef, $fd));
printf("F: %s</p>\n", angle($ef, $fd, $de));

$s = ($de + $ef + $fd) / 2;
printf("Area: %s\n", sqrt($s * ($s - $de) * ($s - $ef) * ($s - $fd)) );

Try it

Assignment BE.1.0

Code and test the parts of todays lessons that are not implemented in the lesson. You should draw heavy parallels from the code in the lesson. Do it in groups and discuss your work.

Let me repeat the class diagram, and remind you, that you may copy today's lesson's code for the Country class and it's test program.

Figure B.1. The First Class Diagram

Assignment BE.1.0 Model Solution
Example B.8. Country
<?php
/**
 * Description of Country
 *
 * @author nml
 */
class Country {
    private $iso;
    private $name;
    private $printable_name;
    private $iso3;
    private $numcode;
    
    public function __construct($iso, $name, $namep, $iso3, $numcode) {
        $this->iso = $iso;
        $this->name = $name;
        $this->printable_name = $namep;
        $this->iso3 = $iso3;
        $this->numcode = $numcode;        
    }
    
    public function getIso() {
        return $this->iso;
    }
    
    public function getIso3() {
        return $this->iso3;
    }
    
    public function getName() {
        return $this->printable_name;
    }
    
    public function getNumcode() {
        return $this->numcode;
    }
    
    public function setNumcode($numcode) {
        $this->numcode = $numcode;
    }
    
    public function __toString() {
        $s = sprintf("<p>Country: %s<br/>No: %s<br/>Name: %s</p>\n"
                , $this->getIso(), $this->getNumcode(), $this->getName());
        return $s;
    }
}
<?php
    require_once './includes/Country.inc.php';
?>
<!doctype html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>Skeleton Class Test 2</title>
    </head>
    <body>
<?php
        $denmark = new Country('DK', 'Danmark',
                               'Danmark', 'DNK', 1);
        $sweden = new Country('SE', 'Sverige',
                               'Sverige', 'SWE', 2);
        print($denmark);
        print($sweden);
        
        print_r($denmark);
        print_r($sweden);
        
        $denmark->setNumcode(65535);
        print($denmark);
?>
    </body>
</html>

Try it


Example B.9. Area
<?php
/**
 * Description of Area
 *
 * @author nml
 */
class Area {
    private $country;
    private $zipcode;
    private $population;
    private $name;
    
    public function __construct($country, $zipcode, $population, $name) {
        $this->country = $country;
        $this->zipcode = $zipcode;
        $this->population = $population;
        $this->name = $name;
    }
    
    public function getPopulation() {
        return $this->population;
    }
    
    public function getName() {
        return $this->name;
    }
    
    public function __toString() {
        return sprintf("<td>%s</td><td>%s</td><td>%s</td>"
                . "<td>%s</td>\n"
                , $this->getName(), $this->country->getName()
                , $this->zipcode, $this->getPopulation());
    }
}
<?php
    require_once 'includes/Country.inc.php';
    require_once 'includes/Area.inc.php';
?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Area testprogram</title>
        <style>
            table, td {
                border: 1px solid blue;
            }
        </style>
    </head>
    <body>
        <?php
        $denmark = new Country('DK', 'Danmark',
                               'Danmark', 'DNK', 1);
        
        $ar1 = new Area($denmark, 8000, 60000, 'Aarhus');
        $ar2 = new Area($denmark, 6000, 290000, 'Kolding');
        $ar3 = new Area($denmark, 9000, 150000, 'Aalborg');
        printf("<h3>%s</h3>\n", $denmark->getName());
        print("<table>\n");
        printf("<tr>%s</tr>\n", $ar1);
        printf("<tr>%s</tr>\n", $ar2);
        printf("<tr>%s</tr>\n", $ar3);
        print("</table>\n");
        ?>
    </body>
</html>

Try it


Example B.10. Inhabitant
<?php
/**
 * Description of Inhabitant
 *
 * @author nml
 */
class Inhabitant {
    private $ssn;
    private $firstname;
    private $surname;
    private $zipcode;
    private $country;
    private $taxpct;
    
    public function __construct($ssn, $firstname, $surname
                              , $zipcode, $country, $taxpct) {
        $this->ssn = $ssn;
        $this->firstname = $firstname;
        $this->surname = $surname;
        $this->zipcode = $zipcode;
        $this->country = $country;
        $this->taxpct = $taxpct;
    }
    
    public function getSsn() {
        return $this->ssn;
    }
    
    public function getTaxPct() {
        return $this->taxpct;
    }
    
    public function setTaxPct($tax) {
        $this->taxpct = $tax;
    }
    
    public function __toString() {
        return sprintf("<td>%s</td><td>%s</td><td>%s</td>"
                . "<td>%s</td><td>%s</td><td>%s</td>\n"
                , $this->getSsn(), $this->firstname, $this->surname
                , $this->zipcode, $this->country->getName(), $this->getTaxPct());
    }
}
<?php
    require_once 'includes/Country.inc.php';
    require_once 'includes/Inhabitant.inc.php';
?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Inhabitant testprogram</title>
        <style>
            table, td {
                border: 1px solid blue;
            }
        </style>
    </head>
    <body>
        <?php
        $denmark = new Country('DK', 'Danmark',
                               'Danmark', 'DNK', 1);
        
        $pers1 = new Inhabitant(123, 'Niels', 'Larsen',
                8270, $denmark, 38);
        $pers2 = new Inhabitant(456, 'Peter', 'Müller',
                8660, $denmark, 33);
        $pers3 = new Inhabitant(789, 'Marlene', 'Mikkelsen',
                6000, $denmark, 27);
        printf("<h3>%s</h3>\n", $denmark->getName());
        print("<table>\n");
        printf("<tr>%s</tr>\n", $pers1);
        printf("<tr>%s</tr>\n", $pers2);
        printf("<tr>%s</tr>\n", $pers3);
        print("</table>\n");
        
        printf("<p>Who: %s: tax %s</p>\n", $pers3->getSsn(), $pers3->getTaxPct());
        $pers3->setTaxPct(49);
        printf("<p>Who: %s: tax %s</p>\n", $pers3->getSsn(), $pers3->getTaxPct());
        
        print_r($pers3->getSsn());
        echo '<br/>';
        var_dump($pers3->getSsn());
        ?>
    </body>
</html>

Try it


Solutions

Assignment BE.2.0

For this and the following assignment: Please refer to the section called “A Test Database” and do what it says. Then return here.

Code and test selecting from the database country table. The number of columns is up to you. You should draw heavy parallels from the code we did in the lesson today. Do it in groups and discuss your work.

Assignment BE.2.0 Model Solution
Example B.11. Country.inc.php
<?php
/**
 * Description of Country from the world database
 *
 * @author nml
 */
class Country {
    private $code;
    private $name;
    private $continent;
    private $region;
    private $surfacearea;
    private $indepyear;
    private $population;
    private $lifeexpectancy;
    private $gnp;
    private $governmentform;
    private $headofstate;
    private $capital;   // a city object
    private $code2;
    
    public function __construct($code, 
                                $name, 
                                $continent, 
                                $region,
                                $population,
                                $headofstate,
                                $governmentform,
                                $capital
                                ) {
        $this->code = $code;
        $this->name = $name;
        $this->continent = $continent;
        $this->region = $region;
        $this->population = $population;
        $this->governmentform = $governmentform;
        $this->headofstate = $headofstate;
        $this->capital = $capital;
    }
    
    public function __toString() {
        $s = sprintf("<p>%s: %s (%s), %d", $this->getCode(), 
                                     $this->getName(), 
                                     $this->getContinent(), 
                                     $this->getPopulation());
        if($this->capital != null) {
            $s .= sprintf(", %s %d", $this->capital->getName(),
                                  $this->capital->getPopulation());
        }
        $s .= "</p><n";
        return $s;
    }
    
    public function getCode() { 
        return $this->code;
    }
    
    public function getName() { 
        return $this->name;
    }
    
    public function getContinent() { 
        return $this->continent;
    }
    
    public function getPopulation() { 
        return $this->population;
    }
}

Example B.12. City.inc.php
<?php
/**
 * Description of City
 *
 * @author nml
 */
class City {
    private $id;
    private $name;
    private $countrycode;
    private $district;
    private $population;
    
    public function __construct($id, $name, $countrycode,
                                $district, $population) {
        $this->id = $id;
        $this->name = $name;
        $this->district = $district;
        $this->countrycode = $countrycode;
        $this->population = $population;
    }
    
    public function getCountrycode() {
        return $this->countrycode;
    }
    
    public function getName() {
        return $this->name;
    }
    
    public function getPopulation() {
        return $this->population;
    }
    
    public function __toString() {
        $s = sprintf("%s: %s %d", $this->getCountrycode(),
                                  $this->getName(),
                                  $this->getPopulation());
        return $s;
    }
}

Example B.13. index.php
<?php
    require_once 'includes/dbparams.inc.php';
    require_once 'includes/dbconnect.inc.php';
    require_once 'includes/Country.inc.php';
    require_once 'includes/City.inc.php';
    $title = 'Read and Display Countries, IBA WebDev';
    $lo = isset($_GET['lo']) ? $_GET['lo'] : 'U';
    $hi = isset($_GET['hi']) ? $_GET['hi'] : 'V';
    $countries = array();
?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title><?php echo $title;?></title>
    </head>
    <body>
<?php
    printf("        <h1>%s</h1>\n", $title);
    
    $sql = "select code, co.name coname, continent, region, co.population copop";
    $sql .= ", cap.id, cap.name capname, cap.population cappop";
    $sql .= " from country co";
    $sql .= " join city cap on id = capital";
    $sql .= " where code between :lo and :hi";
    try {
        $q = $dbh->prepare($sql);
        $q->bindValue(':lo', $lo);
        $q->bindValue(':hi', $hi);
        $q->execute();
        while ($row = $q->fetch()) {
            $c = new Country($row['code'], 
                             $row['coname'],
                             $row['continent'],
                             $row['region'],
                             $row['copop'],
                    '','', new City($row['id'], 
                                    $row['capname'],
                                    $row['code'],
                                    '', $row['cappop']));
            $countries[] = $c;
        }
    } catch(PDOException $e) {
        printf("<p>%s</p>\n", $e->getMessage());
    }
    
    if (count($countries) > 0) {
        print("        <div>\n");
        foreach ($countries as $country) {
            printf($country);
        print("        </div>\n");
        }
    } else {
        print("        <p>no countries</p>\n");
    }
?>
    </body>
</html>

Try it


Assignment BE.2.1

Code and test selecting from the database countrylanguage table. You choose what columns. You should draw heavy parallels from the code we did in the lesson today. Do it in groups and discuss your work.

Assignment BE.2.1 Model Solution
Example B.14. Country.inc.php
<?php
/**
 * Description of Country from the world database
 *
 * @author nml
 */
class Country {
    private $code;
    private $name;
    private $continent;
    private $region;
    private $surfacearea;
    private $indepyear;
    private $population;
    private $lifeexpectancy;
    private $gnp;
    private $governmentform;
    private $headofstate;
    private $capital;   // a city object
    private $code2;
    
    public function __construct($code, 
                                $name, 
                                $continent, 
                                $region,
                                $population,
                                $headofstate,
                                $governmentform,
                                $capital
                                ) {
        $this->code = $code;
        $this->name = $name;
        $this->continent = $continent;
        $this->region = $region;
        $this->population = $population;
        $this->governmentform = $governmentform;
        $this->headofstate = $headofstate;
        $this->capital = $capital;
    }
    
    public function __toString() {
        $s = sprintf("<p>%s: %s (%s), %d", $this->getCode(), 
                                     $this->getName(), 
                                     $this->getContinent(), 
                                     $this->getPopulation());
        if($this->capital != null) {
            $s .= sprintf(", %s %d", $this->capital->getName(),
                                  $this->capital->getPopulation());
        }
        $s .= "</p><n";
        return $s;
    }
    
    public function getCode() { 
        return $this->code;
    }
    
    public function getName() { 
        return $this->name;
    }
    
    public function getContinent() { 
        return $this->continent;
    }
    
    public function getPopulation() { 
        return $this->population;
    }
}

Example B.15. CountryLanguage.inc.php
<?php
/**
 * Description of CountryLanguage
 *
 * @author nml
 */
class CountryLanguage {
    private $country;   // a country object
    private $language;
    private $isOfficial;
    private $percentage;
    
    public function __construct($language, 
                                $isOfficial, 
                                $percentage,
                                $code, 
                                $coname, 
                                $continent, 
                                $region, 
                                $population) {
        $this->country = new Country($code, 
                                     $coname, 
                                     $continent,
                                     $region, 
                                     $population, 
                                     '', '', '');
        $this->language = $language;
        $this->isOfficial = $isOfficial == 'T' ? true : false;
        $this->percentage = $percentage;
    }
    
    public function getLanguage() { return $this->language; }
    public function getIsOfficial() { return $this->isOfficial; }
    public function getPercentage() { return $this->percentage; }
    
    public function __toString() {
        $s = sprintf("%s: %s %s %d (%f)\n", 
                $this->getLanguage(),
                $this->country->getName(),
                $this->isOfficial ? 'Off' : ' ',
                $this->country->getPopulation() * $this->getPercentage() / 100,
                $this->getPercentage()
                );
        return $s;
    }
}

Example B.16. index.php
<?php
    require_once 'includes/dbparams.inc.php';
    require_once 'includes/dbconnect.inc.php';
    require_once 'includes/Country.inc.php';
    require_once 'includes/CountryLanguage.inc.php';
    $title = 'Read and Display Countries, IBA WebDev';
    $lo = isset($_GET['lo']) ? $_GET['lo'] : 'U';
    $hi = isset($_GET['hi']) ? $_GET['hi'] : 'V';
    $countries = array();
?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title><?php echo $title;?></title>
    </head>
    <body>
<?php
    printf("        <h1>%s</h1>\n", $title);
    
    $sql = "select language, isOfficial, percentage, code";
    $sql .= ", name, continent, region, population";
    $sql .= " from countrylanguage cl";
    $sql .= " join country co on code = countrycode";
    $sql .= " where language between :lo and :hi";
    $sql .= " order by language, name";
    try {
        $q = $dbh->prepare($sql);
        $q->bindValue(':lo', $lo);
        $q->bindValue(':hi', $hi);
        $q->execute();
        while ($row = $q->fetch()) {
            $l = new CountryLanguage($row['language'], 
                             $row['isOfficial'],
                             $row['percentage'],
                             $row['code'],
                             $row['name'],
                             $row['continent'],
                             $row['region'],
                             $row['population']);
            $languages[] = $l;
        }
    } catch(PDOException $e) {
        printf("<p>%s</p>\n", $e->getMessage());
    }
    
    if (count($languages) > 0) {
        print("        <p>\n");
        foreach ($languages as $lang) {
            printf("%s<br/>", $lang);
        print("        </p>\n");
        }
    } else {
        print("        <p>no languages(?)</p>\n");
    }
?>
    </body>
</html>

Try it


Assignments BE.3

Assignment BE.3.0

Code and test the Car class from the following diagram.

Figure B.2. The Vehicle Class Diagram

Solution BE.3.0
Example B.17. Car.inc.php
<?php
/**
 * Description of Car
 *
 * @author nml
 */
class Car extends Vehicle {
    private $doors;
    private $trailer;
    
    public function __construct($brand, $color, $name, $doors, $trailer) {
        parent::__construct($brand, $color, $name);
        $this->doors = $doors;
        $this->trailer = $trailer;
        $this->setType('car');
    }
    
    public function getDoors() {
        return $this->doors;
    }
    
    public function getTrailer() {
        $tr = FALSE;
        if ($this->trailer) {
            $tr = TRUE;
        }
        return $tr;
    }
    
    public function __toString() {
        $t = "no trailer";
        if ($this->getTrailer()) {
            $t = "takes trailer";
        }
        return sprintf("%s, %s, %s\n"
                , parent::__toString()
                , $this->getDoors()
                , $t);
    }
}

Example B.18. index.php
<?php
    require_once './includes/Vehicle.inc.php';
    require_once './includes/Truck.inc.php';
    require_once './includes/Bicycle.inc.php';
    require_once './includes/Car.inc.php';
?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Inheritance</title>
        <link rel="stylesheet" href="./css/styles.css"/>
    </head>
    <body>
<?php
    $v1 = new Vehicle('Suzuki', 'Silver', 'Alice');
    printf("<p>%s</p>\n", $v1);
    
    $v2 = new Truck('Scania', 'Red', 'Otto', 18);
    printf("<p>%s</p>\n", $v2);
    
    $v3 = new Bicycle('Moser', 'Blue', 'Francesco');
    printf("<p>%s</p>\n", $v3);
    
    $v4 = new Car('Tesla', 'Black', 'Batman', 4, FALSE);
    printf("<p>%s</p>\n", $v4);
?>
    </body>
</html>

See?


Assignment BE.3.1

Code and test the LiveLecture class from the following diagram.

Figure B.3. The Product Class Diagram

Solution BE.3.1
Example B.19. LiveLecture.inc.php
<?php
/**
 * Description of LiveLecture
 *
 * @author nml
 */
class LiveLecture extends Product {
    protected $duration;
    protected $lecturer;
    protected $topic;
    
    public function __construct($title, $duration
            , $lecturer, $topic) {
        $this->title = $title;
        $this->duration = $duration;
        $this->lecturer = $lecturer;
        $this->topic = $topic;
        $this->type = 'LiveLecture';
    }
    
    public function getDuration() {
        return $this->duration;
    }
    
    public function display() {
        printf("<p>Lecture: %s (%s), %s speaks about %s\n"
                , $this->getTitle()
                , $this->getDuration()
                , $this->lecturer
                , $this->topic);
    }
            
}

Example B.20. index.php
<?php
    require_once './includes/Product.inc.php';
    require_once './includes/Book.inc.php';
    require_once './includes/DVD.inc.php';
    require_once './includes/LiveLecture.inc.php';
?>
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
<?php
    $book = new Book('IT Kommunikation', 172);
    $film = new DVD('@Adactio at AEA', '1 h 5 m');
    $ll = new LiveLecture('@Adactio at AEA'
            , '1 h 5 m'
            , 'Jeremy Keith'
            , 'Web Design Principles');
    $book->display();
    $film->display();
    $ll->display();
?>
    </body>
</html>

See?


Solutions BE.4

Assignment BE.4.0

With reference to todays lesson create a class GolfBall with three properties, color, noinstock, indents. The class must be Sellable.

Test the new class by adding some code to the lesson's index.php.

Solution BE.4.0
Example B.21. GolfBall.inc.php
<?php
/**
 * Description of TennisBall
 * @author nml
 * example from textbook, Doyle, 2010
 */
class GolfBall implements Sellable {
    private $color;
    private $noinstock;
    private $indents;

    public function getColor() {
        return $this->_color;
    }
    
    public function setColor( $color ) {
        $this->_color = $color;
    }

    public function getIndents() {
        return $this->indents;
    }
    
    public function setIndents( $no ) {
        $this->indents = $no;
    }
    
    public function addStock( $numItems ) {
        $this->noinstock += $numItems;
    }
    
    public function sellItem() {
        $returnVal = false;
        if ( $this->noinstock > 0 ) {
            $this->noinstock--;
            $returnVal = true;
        }
        return $returnVal;
    }
    
    public function getStockLevel() {
        return $this->noinstock;
    }
}

Example B.22. indexM.php
<?php
/**
 * @author nml
 * example from textbook, Doyle, 2010
 */
    require_once './includes/Sellable.inc.php';
    require_once './includes/Television.inc.php';
    require_once './includes/TennisBall.inc.php';
    require_once './includes/GolfBall.inc.php';
    require_once './includes/StoreManager.inc.php';
?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Testing Interface, OO PHP</title>
    </head>
    <body>
<?php
    $tv = new Television();
    $tv->setScreenSize(42);
    
    $ball = new TennisBall();
    $ball->setColor('yellow');
    
    $gball = new GolfBall();
    $gball->setColor('pink');
    $gball->setIndents(450);
    
    $manager = new StoreManager();
    $manager->addProduct($tv);
    $manager->addProduct($ball);
    $manager->addProduct($gball);
    $manager->stockUp();
    
    printf("<p>There are %s %s-inch televisions and %s "
            . "%s tennis balls in stock.</p>\n"
            , $tv->getStockLevel()
            , $tv->getScreenSize()
            , $ball->getStockLevel()
            , $ball->getColor());
    printf("Golfballs stock: %s, color: %s, indents: %d"
            , $gball->getStockLevel()
            , $gball->getColor()
            , $gball->getIndents());

    print("<p>Selling a television ...</p>\n");
    $tv->sellItem();
    print("<p>Selling two tennis balls...</p>\n");
    $ball->sellItem();
    $ball->sellItem();
    print("<p>Selling three golf balls...</p>\n");
    $gball->sellItem();
    $gball->sellItem();
    $gball->sellItem();
    
    printf("<p>There are now %s %s-inch televisions and %s "
            . "%s tennis balls in stock.</p>\n"
            , $tv->getStockLevel()
            , $tv->getScreenSize()
            , $ball->getStockLevel()
            , $ball->getColor());
    printf("Golfballs stock: %s, color: %s, indents: %d"
            , $gball->getStockLevel()
            , $gball->getColor()
            , $gball->getIndents());
?>
    </body>
</html>

Assignment BE.4.1

With reference to todays lesson create a database from the following diagram. Augment the diagram with a table for GolfBalls.

Figure B.4. Database SportsShop

Populate the database with a few rows in each table. Check for presence with relevant select declarations.

For your convenience, here is some database creating code you may use for creating your database. Start your XAMPP Apache Server, and the MySQL server. Go to your browser and enter this url: http://localhost/phpmyadmin, create a database, go to the SQL entry form and copy/paste the following into it, and click go.

create database sportsshop;
use sportsshop;

create table golfballs (
    color varchar(16) not null,
    noinstock int not null,
    dimples int not null,
    primary key (color, dimples)
);

create table tennisballs (
    color varchar(16) not null,
    ballsleft int not null,
    primary key(color)
);

create table tvs (
    inch int not null primary key,
    stocklevel int not null
);

insert into golfballs values ('pink', 200, 450);
insert into golfballs values ('white', 0, 375);

insert into tennisballs values('yellow', 250);
insert into tennisballs values('magenta', 12);

insert into tvs values(42, 17);
insert into tvs values(54, 23);
insert into tvs values(88, 5);
Solution BE.4.1
Figure B.5. Database SportsShop Augmented

Example B.23. Interface Demo ER2RM Output
create database if not exists db5;
use db5;

create table tvs (
  inch int not null,
  stocklevel int not null,
  primary key(inch)
);

create table tennisballs (
  color varchar(16) not null,
  ballsleft int not null,
  primary key(color)
);

create table golfballs (
  color varchar(16) not null,
  noinstock int not null,
  dimples int not null,
  primary key(color, dimples)
);

create table image (
  color varchar(16) not null,
  dimples int not null,
  mimetype varchar(32) not null,
  imageitself blob not null,
  primary key(color, dimples),
  foreign key(color, dimples) references golfballs(color, dimples)
);

insert into tvs values(42, 100);
insert into tvs values(52, 100);
insert into tvs values(58, 100);

insert into tennisballs values('white', 300);
insert into tennisballs values('yellow', 300);
insert into tennisballs values('pink', 300);
insert into tennisballs values('lime', 300);

insert into golfballs values('white', 200, 330);
insert into golfballs values('white', 200, 500);
insert into golfballs values('yellow', 200, 330);
insert into golfballs values('yellow', 200, 500);
insert into golfballs values('pink', 200, 380);
insert into golfballs values('pink', 200, 432);

MariaDB [db5]> select * from tvs;
+------+------------+
| inch | stocklevel |
+------+------------+
|   42 |        100 |
|   52 |        100 |
|   58 |        100 |
+------+------------+
3 rows in set (0.00 sec)

MariaDB [db5]> select * from tennisballs;
+--------+-----------+
| color  | ballsleft |
+--------+-----------+
| lime   |       300 |
| pink   |       300 |
| white  |       300 |
| yellow |       300 |
+--------+-----------+
4 rows in set (0.00 sec)

MariaDB [db5]> select * from golfballs;
+--------+-----------+---------+
| color  | noinstock | dimples |
+--------+-----------+---------+
| pink   |       200 |     380 |
| pink   |       200 |     432 |
| white  |       200 |     330 |
| white  |       200 |     500 |
| yellow |       200 |     330 |
| yellow |       200 |     500 |
+--------+-----------+---------+
6 rows in set (0.00 sec)

Assignment BE.4.2

Write a PHP page with a form where you can key in a sale for each of the three products, televisions, tennisballs, and golfballs. The action attribute of your form element must look like this action="http://x15.dk/hitme.php".

We will continue work with these assignments next week.

Solution BE.4.2
Example B.24. myform.php
<?php
    $title = "Form for Sellables";
?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title><?php echo $title;?></title>
        <link rel="stylesheet" href="./css/ifdemo.css"/>
    </head>
    <body>
        <?php
            printf("<header><h1>%s</h1></header>\n", $title);            // put your code here
        ?>
        <form action="http://localhost/hitme.php" method="post">
            <table>
                <tr><td>Televisions</td>
                    <td>
                    <select name="tvs">
                        <option>42</option>
                        <option>52</option>
                        <option>58</option>
                    </select>
                </td>
                <td><input type="text" name="tvno"/></td></tr>
                <tr><td>Golf Balls</td>
                    <td>
                    <select name="gcolor">
                        <option>Lime</option>
                        <option>Yellow</option>
                        <option>Pink</option>
                        <option>White</option>
                    </select>
                </td>
                <td><input type="text" name="gno"/></td></tr>
                
                <tr><td>Tennisballs</td>
                    <td>
                    <select name="tcolor">
                        <option>Lime</option>
                        <option>Yellow</option>
                        <option>Pink</option>
                        <option>White</option>
                    </select>
                </td>
                <td><input type="text" name="tno"/></td></tr>
                
                <tr><td></td><td><input type="submit"/></td></tr>
            </table>
        </form>
    </body>
</html>

Teacher's solution, teacher's server


Solutions BE.5

Assignment BE.5.0

Create a form for, and databasehandler for inserting a new television into the database. Use the sales page as a model for the form, and the current myDbMod.php as a model for the handler.

Assignment BE.5.0
Example B.25. addP.php
<?php
    session_start();
    require_once './includes/DbP.inc.php';
    require_once './includes/DbH.inc.php';
    $dbh = DbH::getDbH();
?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Shop Add Product</title>
        <link rel='stylesheet' href='css/styles.css'/>
    </head>
    <body>
<?php
    include './includes/menu.inc.php';
?>
        <h2>Add Product</h2>
        <main id="mydiv">
          <form action="./myDbMod1.php" method="post">
            <table id="login">
                <caption>New Television?</caption>
                <tr>
                  <td>Inch:</td><td><input type="text" name="inch"/></td>
                </tr>
                <tr>
                  <td>How many: </td><td><input type="text" name="tvno"/></td>
                </tr>
                <tr>
                  <td></td>
                  <td>
                    <input type="submit" value="OK"/>
                  </td>
                </tr>
            </table>
          </form>
        </main>
<?php
    include './includes/footer.inc.php';
?>
  </body>
</html>

Example B.26. myDbMod1.php
<?php
    require_once './includes/DbP.inc.php';
    require_once './includes/DbH.inc.php';
    require_once './includes/Sellable.inc.php';
    require_once './includes/Television.inc.php';
    $dbh = DbH::getDbH();
    
    foreach($_POST as $key => $value) {
        $$key = trim($value);  // vars with names as in form
    }
    $tv = new Television($inch, $tvno);
    
    $sql = 'insert into tvs values(:inch, :number);';
    try {
      $q = $dbh->prepare($sql);
      $q->bindValue(':number', $tv->getStockLevel());
      $q->bindValue(':inch', $tv->getScreenSize());
      $q->execute();
    } catch(PDOException $e) {
      die("Posting failed. Call a friend.<br/>".$e->getMessage());
    }
    header('Location: ./index.php?inserted');

Testing (teachers computer only).

Assignment BE.5.1

Create a new solution for the previous assignment. In this solution the datababase parameters and the database connection module must be changed into objects, and both must be singletons.

Assignment BE.5.1
Example B.27. DbP.inc.php
<?php
abstract class DbP {
    const DBHOST = 'localhost';
    const DBUSER = 'nobody';
    const USERPWD = 'test';
    const DB = 'db5';
    const DSN = "mysql:host=".self::DBHOST.";dbname=".self::DB;
}

Example B.28. DbH.inc.php
<?php
/**
 * Project Agnostic DbH.inc.php with PDO
 * @author nml
 * @copyright (c) 2018, nml
 * @license http://www.fsf.org/licensing/ GPLv3
 */
require_once 'DbP.inc.php';

class DbH extends DbP {
    private static $instance = FALSE;
    private static $dbh;

    private function __construct() {
        try {
            self::$dbh = new PDO(DbP::DSN, DbP::DBUSER, DbP::USERPWD);
            self::$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        } catch (PDOException $e) {
            printf("<p>Connect failed for following reason: <br/>%s</p>\n",
              $e->getMessage());
        }
    }

    public static function getDbH() {
        if (! self::$instance) {
            self::$instance = new DbH();
        }
        return self::$dbh;
    }
}

Testing (teachers computer only).

Solutions BE.6

Assignment BE.6.0

In the assignments following chapters 4 and 5 you make a model web shop selling tv sets, tennis, and golfballs. Based on this, you must now augment your code in such a way the the store manager's role can only be done if he's logged in to the system.

In other words you must secure all other functionality in the shop than sales, with authentication.

Summarily this means:

  • Add a user table to your database.
  • Create a user registration page.
  • Create some users.
  • Change the page from assignment 5.0 so that you must be logged in to use it.
  • Make sure that the page from assignment 4.2 still works without login.
Solution BE.6.0
  • Add a user table to your database.
    Example B.29. The User Table
     create table user (
        id int unsigned not null auto_increment,
        firstname varchar(32) not null,
        lastname varchar(32) not null,
        email varchar(64) not null,
        uid varchar(8) not null,
        password blob not null,
        activated boolean default false,
        primary key(id),
        unique(uid),
        unique(email)
    );

  • Create a user registration page.
    Example B.30. Enter User Data, registerNewUser.php
    <?php
        session_start();
        require_once './includes/DbP.inc.php';
        require_once './includes/DbH.inc.php';
        require_once './includes/Authentication.inc.php';
        $dbh = DbH::getDbH();
    ?>
    <!doctype html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title>Register New User</title>
            <link rel='stylesheet' href='css/styles.css'/>
            <script>
                'use strict';
                var check = function (e) {
                    if (document.forms.formalia.pwd1.value !== 
                                       document.forms.formalia.pwd2.value) {
                        window.alert("Two password entries differ");
                        document.forms.formalia.pwd1.focus();
                        e.preventDefault();
                        return false;
                    }
                }
                var init = function () {
                    document.forms.formalia.addEventListener('submit', check);
                }
                window.addEventListener('load', init);
            </script>
        </head>
        <body>
    <?php
        include './includes/menu.inc.php';
    ?>
            <main id="mydiv">
              <form id='formalia' action="./registerNewUserDb.php" method="post">
                <table id="register">
                    <caption>New User</caption>
                    <tr>
                      <td class='l'>First name:</td>
                      <td><input type="text" name="fname" required/>*</td>
                    </tr>
                    <tr>
                      <td class='l'>Last name:</td>
                      <td><input type="text" name="lname" required/>*</td>
                    </tr>
                    <tr>
                      <td class='l'>Desired User Id/Initials:</td>
                      <td><input type="text" name="uid" required/>*</td>
                    </tr>
                    <tr>
                      <td class='l'>Email address:</td>
                      <td><input type="email" name="email" required/>*</td>
                    </tr>
                    <tr>
                      <td class='l'>Password:</td>
                      <td><input type="password" name="pwd1" required/>*</td>
                    </tr>
                    <tr>
                      <td class='l'>Repeat password:</td>
                      <td><input type="password" name="pwd2" required/>*</td>
                    </tr>
                    <tr>
                      <td></td>
                      <td>
                        <input type="submit" value="OK"/>
                      </td>
                    </tr>
                </table>
              </form>
            </main>
    <?php
        include './includes/footer.inc.php';
    ?>
      </body>
    </html>
    

    Example B.31. New User to Database, registerNewUserDb.php
    <?php
        require_once './includes/DbP.inc.php';
        require_once './includes/DbH.inc.php';
        $dbh = DbH::getDbH();
        
        foreach($_POST as $key => $value) {
            $$key = trim($value);  // vars with names as in form
        }
        
        $sql = 'insert into user (firstname, lastname, uid, email, password)';
        $sql .= ' values(:fname, :lname, :uid, :mail, :pwd);';
        try {
          $q = $dbh->prepare($sql);
          $q->bindValue(':fname', $fname);
          $q->bindValue(':lname', $lname);
          $q->bindValue(':uid', $uid);
          $q->bindValue(':mail', $email);
          $q->bindValue(':pwd', password_hash($pwd1, PASSWORD_DEFAULT));
          $q->execute();
        } catch(PDOException $e) {
          die("Posting failed. Call a friend.<br/>".$e->getMessage());
        }
        header('Location: ./index.php?userinserted');

  • Create some users.
    Example B.32. 
    MariaDB [db5]> select id, email, uid, password, activated from user; 
    +----+-------------+-------+--------------------------------------------------------------+-----------+
    | id | email       | uid   | password                                                     | activated |
    +----+-------------+-------+--------------------------------------------------------------+-----------+
    |  1 | nmla@iba.dk | nml   | $2y$10$J/APq33Tt6h75d0BA6xDYu.0U6029j74L6Zp2PTvaAuwRLOZoTvqq |         1 |
    |  2 | jd@x15.dk   | doess | $2y$10$PFYzY.zr2k1cdiCPJ40gv.82kmmH6QOghYuTLrFOQvvzagctX6YGa |         1 |
    |  3 | jdm@x15.dk  | doe   | $2y$10$9odS.yiNWdRdfF7b6MerPu7X9vCaC1sMEYetmBqVO/wiZP4XuQfdi |         0 |
    |  5 | anat@x15.dk | anat  | $2y$10$GWP0NJC84caQ3KlLQrJZCumZ7R6D/5f0McLPfy3/9dagf.fA4YGDW |         0 |
    |  6 | avi@x15.dk  | avi   | $2y$10$tOLarB.et6vSx5YzwhyuC.ovNdV11Lx95a3Q3CKd86jRMaMjnzfp. |         0 |
    +----+-------------+-------+--------------------------------------------------------------+-----------+
    5 rows in set (0.00 sec)

  • Change the page from assignment 5.0 so that you must be logged in to use it.
    Example B.33. Add Product, addP.php
    <?php
        session_start();
        require_once './includes/DbP.inc.php';
        require_once './includes/DbH.inc.php';
        require_once './includes/Authentication.inc.php';
        $dbh = DbH::getDbH();
    
        if (!Authentication::isAuthenticated()) {  // am I logged on?
            header("Location: ./index.php"); // if not, go away!
        }                               
    ?>
    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title>Shop Add Product</title>
            <link rel='stylesheet' href='css/styles.css'/>
        </head>
        <body>
    <?php
        include './includes/menu.inc.php';
    ?>
            <h2>Add Product</h2>
            <main id="mydiv">
              <form action="./myDbMod1.php" method="post">
                <table id="login">
                    <caption>New Television?</caption>
                    <tr>
                      <td>Inch:</td><td><input type="text" name="inch"/></td>
                    </tr>
                    <tr>
                      <td>How many: </td><td><input type="text" name="tvno"/></td>
                    </tr>
                    <tr>
                      <td></td>
                      <td>
                        <input type="submit" value="OK"/>
                      </td>
                    </tr>
                </table>
              </form>
            </main>
    <?php
        include './includes/footer.inc.php';
    ?>
      </body>
    </html>
    

  • Make sure that the page from assignment 4.2 still works without login.
    Example B.34. Sell Product, sales.php
    <?php
        session_start();
        require_once './includes/DbP.inc.php';
        require_once './includes/DbH.inc.php';
        require_once './includes/Sellable.inc.php';
        require_once './includes/Television.inc.php';
        require_once './includes/Authentication.inc.php';
        $dbh = DbH::getDbH();
        
        $sql = "select inch, stocklevel";
        $sql .= " from tvs";
        $sql .= " order by inch";
            
        try {
            $rows = $dbh->query($sql);
            foreach ($rows as $row) {
                $tvs[] = new Television($row['inch'], $row['stocklevel']);
            }
        } catch(PDOException $e) {
            printf("<p>%s</p>\n", $e->getMessage());
        }
    ?>
    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title>Shop Sales Page</title>
            <link rel='stylesheet' href='css/styles.css'/>
        </head>
        <body>
    <?php
        include './includes/menu.inc.php';
    ?>
            <main>
                <form action="myDbMod.php" method="post">
                    <table>
                        <caption>Sales</caption>
                        <tr>
                            <td><select name='tvs'>
    <?php
        foreach ($tvs as $tv) {
            printf("<option value='%s'>%s inch, in stock: %s</option>\n"
                    , $tv->getScreenSize()
                    , $tv->getScreenSize()
                    , $tv->getStockLevel());
        }
    ?>
                            </select></td>
                            <td><input type='text' name='tvno'/></td>
                        </tr>
                        <tr>
                            <td></td>
                            <td><input type="submit" value="Go"/></td>
                        </tr>
                    </table>
                </form>
            </main>
    <?php
        include './includes/footer.inc.php';
    ?>
        </body>
    </html>
    

    Live from your's truly's localhost.


Solution(s) BE.7

Assignment BE.7.0 MVC

Implements the code from todays lesson in your favorite IDE/editor, and reiterate until it works. Once it works commit it to your bitbucket/gitlab/github git server. We will continue to work on this project in the following lessons.

Solution BE.7.0

Nothing to add. See Lesson 7.

Solutions BE.8

Assignment BE.8.0

Copy the code from todays chapter, and change to model to include audio clips in addition to the demonstrated video clips. There must of course be some changes to the class diagram, find it here. In addition you must create a database with the shown media table. The table will easily accommodate audio clips as their mimetype is different such as audio/mp3.

The view must be adapted to display audio elements when the channel numbers are between 11 and 20.

Hand in a zip file with all the code, the class diagram, plus an export file with the database table(s).

Solution BE.8.0
The Model
Example B.35. TelevisionI.inc.php, Television.inc.php, Video.inc.php, and DbH.inc.php
<?php
/*
 * This is the MODEL
 */
require_once './includes/DbP.inc.php';
require_once './includes/DbH.inc.php';
require_once './includes/Media.inc.php';

class Television implements TelevisionI {
    private static $audioLo = 11; // lo audio channel
    private static $audioHi = 20; // hi audio channel
    private $on;      // true if on, otherwise false
    private $channel; // integer with current channel number
    private $volume;  // integer with current volume level 
    private $mute;    // false if not muted, otherwise true
    private $videos = array();
    
    /*
     * get state from session array
     * normally you'd read input params
     * or a database
     */
    public function __construct() {
        $this->on = isset($_SESSION['on']) ? $_SESSION['on'] : TRUE;
        $this->channel = isset($_SESSION['channel']) ? $_SESSION['channel'] : 1;
        $this->volume = isset($_SESSION['volume']) ? $_SESSION['volume'] : 10;
        $this->mute = isset($_SESSION['mute']) ? $_SESSION['mute'] : FALSE;
        $this->populateMedia($this->getChannel(), DbH::getDbH());
    }

    public function getTvOnOff() {
      return $this->on;
    }

    public function tvOnOff() {
      $this->on = $this->on ? FALSE : TRUE;
      $this->saveState();
    }

    public function getAudioChLo() {
      return self::$audioLo;
    }

    public function getAudioChHi() {
      return self::$audioHi;
    }

    public function getChannel() {
      return $this->channel;
    }

    public function chUp() {
      $this->channel += 1;
      $this->saveState();
      $this->populateMedia($this->getChannel(), DbH::getDbH());
    }

    public function chDown() {
      if ($this->channel > 1) {
          $this->channel -= 1;
      } else {
          $this->channel = 1;
      }
      $this->saveState();
      $this->populateMedia($this->getChannel(), DbH::getDbH());
    }

    public function getVolume() {
      return $this->volume;
    }

    public function volUp() {
      $this->volume += 1;
      $this->saveState();
    }

    public function volDown() {
      $this->volume -= 1;
      $this->saveState();
    }

    public function getMute() {
      return $this->mute;
    }

    public function mute() {
      $this->mute = $this->mute ? FALSE : TRUE;
      $this->saveState();
    }

    public function getMedia() {
      return $this->videos;
    }

    private function populateMedia($ch, $dbh) {
      $this->videos = array();
      $this->videos = Media::setMedia($ch, $dbh);
    }

    private function saveState() {
      $_SESSION['on'] = $this->getTvOnOff();
      $_SESSION['channel'] = $this->getChannel();
      $_SESSION['volume'] = $this->getVolume();
      $_SESSION['mute'] = $this->getMute();
    }
}
<?php
/*
 * Video
 * part of the Television model
 */
class Media {
    private $mediaurl;
    private $mimeType;

    public function __construct($url, $type) {
        $this->mediaurl = $url;
        $this->mimeType = $type;
    }

    public function getUrl() {
        return $this->mediaurl;
    }

    public function getMimeType() {
        return $this->mimeType;
    }

    public static function setMedia($channel, $dbh) {
        $media = array();

        $sql = "select mediaurl, mimetype";
        $sql .= " from media";
        $sql .= " where channel = :channel";
        try {
          $q = $dbh->prepare($sql);
          $q->bindValue(':channel', $channel);
          $q->execute();
          while ($row = $q->fetch()) {
              $videourl = $row['mediaurl'];
              $mimetype = $row['mimetype'];
              $medio = new Media($videourl, $mimetype);
              array_push($media, $medio);
          }
        } catch(PDOException $e) {
          printf("<p>Query failed: <br/>%s</p>\n",
            $e->getMessage());
        } finally {
          return $media;
        }
    }
}
<?php
/**
 * Project Agnostic DbH.inc.php with PDO
 * @author nml
 * @copyright (c) 2018, nml
 * @license http://www.fsf.org/licensing/ GPLv3
 */
require_once 'DbP.inc.php';

class DbH extends DbP {
    private static $instance = FALSE;
    private static $dbh;

    private function __construct() {
        try {
            self::$dbh = new PDO(DbP::DSN, DbP::DBUSER, DbP::USERPWD);
            self::$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        } catch (PDOException $e) {
            printf("<p>Connect failed for following reason: <br/>%s</p>\n",
              $e->getMessage());
        }
    }

    public static function getDbH() {
        if (! self::$instance) {
            self::$instance = new DbH();
        }
        return self::$dbh;
    }
}

The View
Example B.36. The Model, TelevisionV1.inc.php
<?php
/*
 * This is a VIEW
 */
require_once './includes/TelevisionI.inc.php';
require_once './includes/Television.inc.php';

class TelevisionV1 {
    private $model;

    public function __construct(Television $model) {
        $this->model = $model;
    }

    private function remote() {
        $s = sprintf("<div class='remote'>\n
                      <form action='%s' method='post'>
                        <p>
                        <button type='submit' name='on'>On/Off</button>
                        </p>
                        <p>
                        <button type='submit' name='volup'>Volume Up</button>
                        <button type='submit' name='chup'>Channel Up</button>
                        </p>
                        <p>
                        <button type='submit' name='voldown'>Volume Down</button>
                        <button type='submit' name='chdown'>Channel Down</button>
                        </p>
                        <p>
                        <button type='submit' name='mute'>Mute</button>
                        </p>
                      </form>
                      </div>
                      \n"
                    , $_SERVER['PHP_SELF']);
        return $s;
    }

    private function osd() {
        $ooState = $this->model->getTvOnOff() ? 'On' : 'Off';
        $muted = $this->model->getMute() ? 'True' : 'False';
        $s = sprintf("<div class='state'>
                        <p>On/Off: %s
                          <br/>Channel: %s
                          <br/>Volume: %s
                          <br/>Muted: %s
                        </p>
                      </div>\n"
                   , $ooState
                   , $this->model->getChannel()
                   , $this->model->getVolume()
                   , $muted);
        return $s;
    }

    private function mainElm() {
        $media = 'video';
        if ($this->model->getAudioChLo() <= $this->model->getChannel()
            && $this->model->getChannel() <= $this->model->getAudioChHi()) {
            $media = 'audio';
        }
        $s = sprintf("<%s controls>\n", $media);
        foreach ($this->model->getMedia() as $medio) {
            $s .= sprintf("    <source src='./media/%s' type='%s'/>\n"
                      , $medio->getUrl(), $medio->getMimeType());
        }
        $s .= sprintf("</%s>\n", $media);
        return $s;
    }

    public function display() {
        printf("<nav class='nav'>\n%s\n%s\n</nav>\n"
          , $this->osd(), $this->remote());
        printf("<main class='main'>\n%s\n</main>\n"
          , $this->mainElm());
    }
}

Usage: The Application
Example B.37. index.php
<?php
    /*
     * This is the application
     */
    session_start();
    require_once './includes/TelevisionRC.inc.php'; // a controller
    $title = 'Television MVC II';
    include_once './includes/top.inc.php';          // top html

    $rc = new TelevisionRC();   // init a controller
    $rc->action($_POST);        // let it work

    include_once './includes/feet.inc.php';         // bottom html

Live from teachers localhost.


Assignment BE.8.1

In this assignment you must create a shop/consultancy site with the following: The diagram may be downloaded from here. You may have some code from Chapter 4 that might be reusable.

Figure B.6. The Mixed Shop

You must make a front page view with some menu items leading to displaying books, dvds, or lectures either together or separately, as you decide.

You may recall that the original classes had display methods. They, in the name of MVC, have deen delegated to views. Now you must

  • Complete the diagram and consult with your supervisor.
  • Create the database, and put in a couple of rows in each table.
  • Create the site that, invoked by menu choice, displays the content of the database.
  • It might be useful to work in pairs.
Solution BE.8.1
The Model
Example B.38. The Model Layer Classes, Product, Book, DVD, LiveLecture
<?php
/**
 * Description of Product
 * Model Layer
 *
 * @author nml
 */
abstract class Product {
    protected $id;
    protected $type;
    protected $title;

    public function __construct($id, $type, $title) {
        $this->id = $id;
        $this->type = $type;
        $this->title = $title;
    }
    public function getProductType() {
        return $this->type;
    }

    public function getTitle() {
        return $this->title;
    }

    public function getId() {
        return $this->id;
    }

}
<?php
/**
 * Description of Book
 * Model Layer
 * @author nml
 */
class Book extends Product {
    protected $pageCount;
    protected $dbh;
    protected static $books = array();

    public function __construct($id, $title, $pageCount) {
        parent::__construct($id, 'book', $title);
        $this->pageCount = $pageCount;
    }

    public function getPageCount() {
        return $this->pageCount;
    }

    public static function getBooks() {
        return self::$books;
    }

    public static function setBooks() {
        $dbh = DbH::getDbH();
        $sql = "select p.id, title, pagecount";
        $sql .= " from book b";
        $sql .= " join product p";
        $sql .= " on b.id = p.id";
        $sql .= " order by title";
        try {
          $q = $dbh->prepare($sql);
          $q->execute();
          while ($row = $q->fetch()) {
              $book = new Book($row['id'], $row['title'], $row['pagecount']);
              array_push(self::$books, $book);
          }
        } catch(PDOException $e) {
          printf("<p>Query failed: <br/>%s</p>\n",
            $e->getMessage());
        }
    }
}
<?php
/**
 * Description of DVD
 * Model Layer
 * @author nml
 */
class DVD extends Product {
    protected $duration;

    public function __construct($title, $duration) {
        parent::__construct('DVD', $title);
        $this->pageCount = $pageCount;
    }

    public function getDuration() {
        return $this->duration;
    }

    public static function getDVDs(&$arr) {
        // read dvds
        // loop them into objects and put them into arr
    }

}
<?php
/**
 * Description of LiveLecture
 * Model Layer
 * @author nml
 */
class LiveLecture extends Product {
    protected $duration;
    protected $lecturer;
    protected $topic;

    public function __construct($title, $duration, $lecturer, $topic) {
        parent::__construct('LiveLecture', $title);
        $this->duration = $duration;
        $this->lecturer = $lecturer;
        $this->topic = $topic;
    }

    public function getDuration() {
        return $this->duration;
    }

    public static function getLectures(&$arr) {
        // read lectures
        // loop them into objects and put them into arr
    }
}

The View
Example B.39. The View Layer Classes, ProductView, BookView, DVDView, LectView
<?php
/**
 * Description of Product View
 *
 * @author nml
 */
class ProductView {
    private $model;
    private $title = 'Product MVC';

    public function __construct($model) {
        $this->model = $model;
    }

    private function top() {
        $s = "<!doctype html>
<html>
%4s<head>
%8s<meta charset='utf-8'/>
%8s<title>%s</title>
%8s<link rel='stylesheet' href='./css/styles.css'/>
%4s</head>
%4s<body>\n";
        return sprintf($s, ' ', ' ', ' ', $this->title, ' ', ' ', ' ');
    }

    private function header() {
        $s = "%8s<header>
%12s<h1>Shop Front Page</h1>
%12s<ul id='menu'>
%16s<li><a href='index.php'>Home</a></li>
%16s<li><a href='index.php?p=b1'>Books</a></li>
%16s<li><a href='index.php?p=d1'>DVDs</a></li>
%16s<li><a href='index.php?p=l1'>Live Lectures</a></li>
%12s</ul>
%8s</header>\n";
         return sprintf($s, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ');
    }

    private function footer() {
        $s = "%8s<footer>
%12s<small>&copy; NML, %d</small>
%8s</footer>
%4s</body>
</html>\n";
        return sprintf($s, ' ', ' ', strftime("%Y", time()), ' ', ' ');
    }

    public function displayHead() {
        print($this->top());
        print($this->header());
    }

    public function displayFoot() {
        print($this->footer());
    }

    private function displayEmptyMain() {
        printf("%8s<main>\n%8s</main>\n", ' ', ' ');
    }

    public function display() {
        $this->displayHead();
        $this->displayEmptyMain();
        $this->displayFoot();
    }
}
<?php
/**
 * Description of BookView
 *
 * @author nml
 */
class BookView extends ProductView {

    public function __construct() {
        // do something
    }

    public function display() {
        parent::displayHead();
        $this->rollOut();
        parent::displayFoot();
    }

    private function rollOut() {
        $arr = Book::getBooks();
        print("<table>\n");
        print("<caption>Books</caption>\n");
        foreach ($arr as $book) {
            $s = "<tr><td><a href='index.php?p=b2&amp;id=%s'>%s</a></td><td>%s</td><td class='r'>%4d</td></tr>\n";
            printf($s, $book->getId(), $book->getId(), $book->getTitle(), $book->getPageCount());
        }
        print("</table>\n");
    }
}
<?php
/**
 * Description of DVD View
 *
 * @author nml
 */
class DVDView extends ProductView {
    protected $duration;

    public function __construct($title, $duration) {
        $this->title = $title;
        $this->duration = $duration;
        $this->type = 'DVD';
    }

    public function getDuration() {
        return $this->duration;
    }

    public function display() {
        printf("<p>DVD: %s (%s pages)\n"
                , $this->getTitle()
                , $this->getDuration());
    }

}
<?php
/**
 * Description of LiveLecture view
 *
 * @author nml
 */
class LiveLectureView extends Product {
    protected $duration;
    protected $lecturer;
    protected $topic;

    public function __construct($title, $duration
            , $lecturer, $topic) {
        $this->title = $title;
        $this->duration = $duration;
        $this->lecturer = $lecturer;
        $this->topic = $topic;
        $this->type = 'LiveLecture';
    }

    public function getDuration() {
        return $this->duration;
    }

    public function display() {
        printf("<p>Lecture: %s (%s), %s speaks about %s\n"
                , $this->getTitle()
                , $this->getDuration()
                , $this->lecturer
                , $this->topic);
    }

}

The Controller
Example B.40. ProductC.inc.php
<?php
/*
 * This is the CONTROLLER
 */
require_once './model/DbP.inc.php';                 // model layer
require_once './model/DbH.inc.php';                 // model layer
require_once './model/Product.inc.php';             // model layer
require_once './model/Book.inc.php';                // model layer
require_once './model/DVD.inc.php';                 // model layer
require_once './model/LiveLecture.inc.php';         // model layer

require_once './view/ProductView.inc.php';         // view layer
require_once './view/BookView.inc.php';            // view layer
require_once './view/DVDView.inc.php';             // view layer
require_once './view/LectView.inc.php';            // view layer

class ProductC {
    private $model;

    public function __construct() {
        //
    }

    public function action($get) {
        foreach ($get as $key => $value) {
            $$key = $value;
        }

        if (isset($p) && $p == 'b1') {              // list all books
            Book::setBooks();                       // read all books
            $v = new BookView();                    // create view
            $v->display();                          // send them to view
        } elseif (isset($p) && $p == 'd1') {
            // read data from Model
            // create relevant view
            // send them to view
        } elseif (isset($p) && $p == 'l1') {
            // read data from Model
            // create relevant view
            // send them to view
        } else {
            $v = new ProductView($this->model);     // create view front page
            $v->display();                          // show it
        }
    }
}

Usage: The Application
Example B.41. index.php
<?php
    require_once './controller/ProductC.inc.php';

    $rc = new ProductC();                           // init a controller
    $rc->action($_GET);                             // let it work

Live from teachers localhost.


Solutions BE.11

Assignment BE.110.0

N-factorial is

n! = n * n-1 * n-2 * ... * 2 * 1
// or equivalently
n! = n * (n-1)!
// the recursive definition

Perhaps needless to say, where n ∈ ℕ.

Write and test a function fact($n) that recursively calculates factorials. Test fact(3), fact(4), ..., fact(20). Hand in code and a textfile with output from the tests.

Solutions BE.110.0
Example B.42. recursFact.php
<?php
function fact($n) {
    if ($n <= 1) {
        return 1;
    } else {
        return $n * fact($n - 1);
    }
}

print ("3! = " . fact(3) . "\n");
print ("4! = " . fact(4) . "\n");
print ("5! = " . fact(5) . "\n");
print ("6! = " . fact(6) . "\n");
print ("7! = " . fact(7) . "\n");
print ("8! = " . fact(8) . "\n");
print ("9! = " . fact(9) . "\n");
print ("10! = " . fact(10) . "\n");
print ("11! = " . fact(11) . "\n");
print ("12! = " . fact(12) . "\n");
print ("13! = " . fact(13) . "\n");
print ("14! = " . fact(14) . "\n");
print ("15! = " . fact(15) . "\n");
print ("16! = " . fact(16) . "\n");
print ("17! = " . fact(17) . "\n");
print ("18! = " . fact(18) . "\n");
print ("19! = " . fact(19) . "\n");
print ("20! = " . fact(20) . "\n");

Assignment BE.110.1

The Fibonacci series is defined by

F0 = 0
F1 = 1
Fn = Fn-1 + Fn-2

Write and test a function fibo($n) that recursively calculates the nth fibonacci number. Test and print fibo(0), fibo(1), ..., fibo(20). Hand in code and a textfile with output from the tests.

Solutions BE.110.1
Example B.43. recursFibo.php
<?php
function fibo($n) {
    if ($n == 0 || $n == 1) {
        return $n;
    } else {
        return fibo($n - 1) + fibo($n - 2);
    }
}

print ("0 = " . fibo(0) . "\n");
print ("1 = " . fibo(1) . "\n");
print ("2 = " . fibo(2) . "\n");
print ("3 = " . fibo(3) . "\n");
print ("4 = " . fibo(4) . "\n");
print ("5 = " . fibo(5) . "\n");
print ("6 = " . fibo(6) . "\n");
print ("7 = " . fibo(7) . "\n");
print ("8 = " . fibo(8) . "\n");
print ("9 = " . fibo(9) . "\n");
print ("10 = " . fibo(10) . "\n");
print ("11 = " . fibo(11) . "\n");
print ("12 = " . fibo(12) . "\n");
print ("13 = " . fibo(13) . "\n");
print ("14 = " . fibo(14) . "\n");
print ("15 = " . fibo(15) . "\n");
print ("16 = " . fibo(16) . "\n");
print ("17 = " . fibo(17) . "\n");
print ("18 = " . fibo(18) . "\n");
print ("19 = " . fibo(19) . "\n");
print ("20 = " . fibo(20) . "\n");

Assignment BE.110.2

We need to test a string for being a palindrome. according to Wikipedia A palindrome is a word, phrase, number, or other sequence of characters which reads the same backward as forward, such as madam or racecar.

You could transform the above definition into "A string is a palindrome if its first and last characters are the same and the middle is a palidrome."

Now create three functions first($str), last($str), and middle($str). They must return the first character, the last character, and the middle characters of the string respectively. Then, with the use of those three functions, build a recursive function isPalindrome($s) that returns true if $str is a palindrome, and false otherwise.

Hand in code and testoutput for several tests.

Solutions BE.110.2
Example B.44. recursPalin.php
<?php
    function clean($s) {
        return preg_replace("/\W/", "", $s);
    }

    function first($s) {
        return substr($s, 0, 1);
    }

    function last($s) {
        return substr($s, -1, 1);
    }

    function middle($s) {
        return substr($s, 1, strlen($s) - 2);
    }

    function isPalindrome($s) {
        $s = clean($s);
        $s = strtolower($s);
        switch (strlen($s)) {
            case 1: return true;
            case 2: return first($s) == last($s);
            default: print("\n" . first($s) .
                    " - " . middle($s) . " - " . last($s));
            return first($s) == last($s) && isPalindrome(middle($s));
        }
    }

    function test($st) {
        
        if (isPalindrome($st)) {
            print("\n".$st." is a palindrome");
        } else {
            print("\n".$st." is not a palindrome");
        }
        print("\n");
    }

    test('regninger');
    test('abc');
    test('rEgNin  ger');
    test('abe,eb a');

print("\n");

Assignment BE.110.3

Write a recursive function that raises a positive integer to its n-th power rn, r ∧ n ∈ ℕ.

When it works, make a variant that works on all integers, r ∈ ℕ and n ∈ ℤ.

Hand in code and testoutput for several tests.

Solutions BE.110.3
Example B.45. recursPower.php
<?php
function power($n, $p) {
    $r = 1;
    IF ($p == 0) {
        return 1;
    } else {
        return $n * power($n, $p - 1);
    }
}

print ("2^7 = " . power(2, 7) . "\n");
print ("-3^3 = " . power(-3, 3) . "\n");
print ("-7^2 = " . power(-7, 2) . "\n");
print ("2^32 = " . power(2, 32) . "\n");
print ("2^0 = " . power(2, 0) . "\n");
print ("12^0 = " . power(12, 0) . "\n");