# Session 13 - Server-Side, Part 1

Harvard Extension School
Fall 2023

Course Web Site: https://cscie12.dce.harvard.edu/

### Topics

1. Announcements
2. "Back end" (Server-Side) Web Development
3. Server Side Rendering of Content (SSR)
4. PHP Example with Courses Database
5. Separation of Concerns
6. {{Mustache}} Templates
7. Improving the Hello! Greeting
8. Sending Email
9. CSR (Client Side Rendering)
10. Next Time

Session 13 - Server-Side, Part 1, slide1
Announcements, slide2
Final Project Notes and Observations, slide3
"Back end" (Server-Side) Web Development, slide4
CSR or SSR or SSG, slide5
Server Side Rendering of Content (SSR), slide6
A Personal Greeting, slide7
A Personal Greeting, slide8
PHP Example with Courses Database, slide9
Harvard Extension Course Data, slide10
Data Table in a Relational Database, slide11
PHP Script to Connect to Database and Get List of Departments, slide12
Turn this into HTML Output, slide13
The entire "departments-simple.php", slide14
Adding another view - Department Course Listings, slide15
courses.php, slide16
Separation of Concerns, slide17
{{Mustache}} Templates, slide18
Mustache Departments, slide19
Mustache Courses, slide20
Improving the Hello! Greeting, slide21
Hello! Greeting, Improved, slide22
Sending Email, slide23
CSR (Client Side Rendering), slide24
Getting JSON from HTTP request, slide25
Let's Try It Out!, slide26
Apples, slide27
Apples, slide28
JS and fetch, slide29
Courses — PHP and JSON data, slide30
Front-end courses, slide31
Next Time, slide32

Presentation contains 32 slides

- img
- img
- img
- img
- img

## Announcements

- Office Hours - Appointment and Open. Check out the schedule for the upcoming week for office hours -- there are "open / drop-in" times as well as 20 minute scheduled appointments.
- Final Project information, including GitHub repo info (optional), example report, and submission parts published.
- Wednesday, December 20. Final Project Due and Final Project Presentations [Optional]

## Final Project Notes and Observations

- Implement only three parts.
  - The rest doesn't have to exist
  - Use `href="#"` to link to those things that don't exist yet
- File structure organization:
  - All of your html files at the top level
  - directory/folder for images, styles, and scripts

        .
        |-- index.html
        |-- hello-harvard.html
        |-- images
        |   |-- harvard.jpg
        |   `-- world.jpg
        |-- scripts
        |   `-- map.js
        `-- styles
            `-- site.css

- lowercase file names and without spaces
  - Better: `my_favorite_teas.html`
  - Worse: `My Favorite Teas.html`
- Within your site, use relative URL links.
  - NOT relative:
    1. `<link rel="stylesheet" href="/Users/david/Desktop/final_project/styles/site.css"/>`
    2. `<link rel="stylesheet" href="/styles/site.css"/>` ← this will work in VS Code "Go Live" but most likely won't when you publish your site!
- Site-wide CSS Stylesheet!
  One CSS stylesheet to style all of your HTML pages!

## "Back end" (Server-Side) Web Development

Language | Frameworks/Platforms
--- | ---
JavaScript | "Back-end": Node, Express "Front-end": React, Vue, Angular, Ember
PHP | Laravel, Symfony, CodeIgniter, CakePHP PHP-based CMS: WordPress, Drupal, Joomla
Python | Django, Flask, Zope, Plone
Go | Gin, Echo, Beego, etc.

## CSR or SSR or SSG

- CSR - Client Side Rendering
  e.g. JavaScript within web browser makes request for JSON data, then builds the page based on that data
- SSR - Server Side Rendering
  Web server hands off HTTP request to a program, and the program generates the content
- SSG - Static Site Generation also Build Time Rendering (BTR)
  Content is created programmatically at build time, and the static HTML content is served at time of request.

## Server Side Rendering of Content (SSR)

### Web Program Examples

Markup or content is embedded within a program; program embedded into markup

### first.py - Python

first.py

    #!/usr/bin/python3
    print("Content-type: text/html\n\n")
    print("<html><head><title>Hello World!</title></head>")
    print("<body><h1>Hello, World!</h1></body></html>")

### first.php - PHP

first.php

    <?php
    echo('<html><head><title>First PHP</title></head><body>');
    echo('<h1>Hello!</h1>');
    echo('</body></html>');
    ?>

### second.php - PHP

second.php
program statements within markup

    <?php
          $title = "Hello World!";
    ?>
    <!DOCTYPE html>
      <head>
        <meta charset="utf-8" />
        <title><?php echo($title) ?></title>
      </head>
      <body>
        <h1><?php echo($title) ?></h1>
      </body>
    </html>

## A Personal Greeting

- third.php
- third.php?name=John%20Harvard

    <?php
          $name = $_GET["name"];
    ?>
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <title>Greeting Page</title>
      </head>
      <body>
        <h1>Hello, <?php echo($name) ?>!</h1>
      </body>
    </html>

## A Personal Greeting

Without a "name", present the user a form. With a name, provide a greeting.

- fourth.php
- fourth.php?name=John%20Harvard

    <?php
          $name = $_GET["name"];
    ?>
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8"/>
        <title>Greeting Page</title>
      </head>
      <body>
        <?php
        if ($name) {
          echo("<h1>Hello, $name!</h1>");
        } else {
          echo('<h1><label for="input_name">Enter name:</label></h1>');
          echo('<form method="get">');
          echo('<input type="text" name="name" id="input_name"/>');
          echo('<br /><input type="submit" />');
          echo('<br /><input type="reset" />');
        }
    ?>
      </body>
    </html>

## PHP Example with Courses Database

- https://cscie12.dce.harvard.edu/cgi/ext-courses/departments.php

## Harvard Extension Course Data

### Course Data in a Spreadsheet

## Data Table in a Relational Database

RDBMS = Relational Database Management System

- Postgres
- MySQL
- Oracle
- Microsoft SQL Server

### Course Data in RDBMS Table

Course data for Faculty of Arts & Sciences is in a mysql database on cscie12students (username: class; database name: coursecatalog)

SQL:

    describe ext_courses

Terminal:

    cscie12students$ mysql -u class coursecatalog
    Welcome to the MySQL monitor.  Commands end with ; or \g.

    mysql> describe ext_courses;
    +----------------------+--------------+------+-----+---------+-------+
    | Field                | Type         | Null | Key | Default | Extra |
    +----------------------+--------------+------+-----+---------+-------+
    | academic_year        | year         | YES  |     | NULL    |       |
    | term                 | varchar(32)  | YES  |     | NULL    |       |
    | term_code            | int          | YES  |     | NULL    |       |
    | course_code          | int          | YES  |     | NULL    |       |
    | course_number        | int          | YES  |     | NULL    |       |
    | short_title          | text         | YES  |     | NULL    |       |
    | title                | text         | YES  |     | NULL    |       |
    | faculty_description  | text         | YES  |     | NULL    |       |
    | department_code      | varchar(15)  | YES  |     | NULL    |       |
    | department           | varchar(200) | YES  |     | NULL    |       |
    | course_type          | varchar(100) | YES  |     | NULL    |       |
    | credits              | varchar(50)  | YES  |     | NULL    |       |
    | credit_undergraduate | int          | YES  |     | NULL    |       |
    | credit_graduate      | int          | YES  |     | NULL    |       |
    | url                  | varchar(300) | YES  |     | NULL    |       |
    | days_of_week         | varchar(100) | YES  |     | NULL    |       |
    | start_time           | varchar(15)  | YES  |     | NULL    |       |
    | end_time             | varchar(15)  | YES  |     | NULL    |       |
    | location             | varchar(64)  | YES  |     | NULL    |       |
    | notes                | text         | YES  |     | NULL    |       |
    | description          | text         | YES  |     | NULL    |       |
    +----------------------+--------------+------+-----+---------+-------+
    21 rows in set (0.00 sec)

### Selecting List of Departments

SQL Input:

    select DISTINCT department_code, department from ext_courses

Terminal Output:

    mysql> SELECT DISTINCT department_code, department FROM ext_courses ORDER BY department;
    +-----------------+--------------------------------------+
    | department_code | department                           |
    +-----------------+--------------------------------------+
    | AAAS            | African and African American Studies |
    | ANTH            | Anthropology and Archaeology         |
    | APMA            | Applied Mathematics                  |
    | ARAB            | Arabic                               |
    | ASTR            | Astronomy                            |
    | BIOS            | Biological Sciences                  |
    | BIOT            | Biotechnology                        |
    | CELT            | Celtic Languages and Literatures     |
    | CHEM            | Chemistry                            |
    | CLAS            | Classics                             |
    | CSCI            | Computer Science                     |
    | CREA            | Creative Writing                     |
    | DEVP            | Development Practice                 |
    | DGMD            | Digital Media                        |
    | DRAM            | Dramatic Arts                        |
    | ECON            | Economics                            |
    | EDUC            | Education                            |
    | ENSC            | Engineering Sciences                 |
    | ENGL            | English                              |
    | ENVR            | Environmental Studies                |
    | EXPO            | Expository Writing                   |
    | FREN            | French Language and Literature       |
    | GERM            | German                               |
    | GOVT            | Government                           |
    | CGRK            | Greek                                |
    | HIST            | History                              |
    | HARC            | History of Art and Architecture      |
    | HUMA            | Humanities                           |
    | IORP            | Industrial-Organizational Psychology |
    | ISMT            | Information Systems Management       |
    | ITAL            | Italian                              |
    | JAPA            | Japanese                             |
    | JOUR            | Journalism                           |
    | LATI            | Latin                                |
    | LSTU            | Legal Studies                        |
    | MGMT            | Management                           |
    | MATH            | Mathematics                          |
    | MUSE            | Museum Studies                       |
    | MUSI            | Music                                |
    | NUTR            | Nutrition                            |
    | PHIL            | Philosophy                           |
    | PHYS            | Physics                              |
    | PSYC            | Psychology                           |
    | RELI            | Religion                             |
    | SSCI            | Social Sciences                      |
    | SOCI            | Sociology                            |
    | SPAN            | Spanish Language and Literature      |
    | SPCH            | Speech                               |
    | STAT            | Statistics                           |
    | STAR            | Studio Arts and Film                 |
    +-----------------+--------------------------------------+
    50 rows in set (0.01 sec)

## PHP Script to Connect to Database and Get List of Departments

    <?php

    // set header for text content
    header('Content-type: text/plain');

    // use Dotenv to load database info from .env file
    // DB_HOST, DB_USER, DB_PW, DB_NAME
    require_once('vendor/autoload.php');
    $dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
    $dotenv->safeLoad();

    // Connecting, selecting database
    $mysqli = new mysqli($_ENV['DB_HOST'],$_ENV['DB_USER'],$_ENV['DB_PW'],$_ENV['DB_NAME']);
    if ($mysqli->connect_errno) {
        echo "Failed to connect to mysql: ".$mysqli->connect_errno." ".$mysqli->connect_error;
    }

    // Performing SQL query
    $query = 'SELECT DISTINCT department, department_code FROM ext_courses ORDER BY department';
    $result = $mysqli->query($query);

    // iterating through results
    while ($row = $result->fetch_assoc()){
      echo $row['department_code'];
      echo "\t";
      echo $row['department'];
      echo "\n";
    }
    ?>

### Output

[dph445@cs12:~/www-cscie12/html/cgi/ext-courses$ php dept-txt.php AAAS African and African American Studies ANTH Anthropology and Archaeology APMA Applied Mathematics ARAB Arabic ASTR Astronomy BIOS Biological Sciences BIOT Biotechnology CELT Celtic Languages and Literatures CHEM Chemistry CLAS Classics CSCI Computer Science CREA Creative Writing DEVP Development Practice DGMD Digital Media DRAM Dramatic Arts ECON Economics EDUC Education ENSC Engineering Sciences ENGL English ENVR Environmental Studies EXPO Expository Writing FREN French Language and Literature GERM German GOVT Government CGRK Greek HIST History HARC History of Art and Architecture HUMA Humanities IORP Industrial-Organizational Psychology ISMT Information Systems Management ITAL Italian JAPA Japanese JOUR Journalism LATI Latin LSTU Legal Studies MGMT Management MATH Mathematics MUSE Museum Studies MUSI Music NUTR Nutrition PHIL Philosophy PHYS Physics PSYC Psychology RELI Religion SSCI Social Sciences SOCI Sociology SPAN Spanish Language and Literature SPCH Speech STAT Statistics STAR Studio Arts and Film

## Turn this into HTML Output

    <?php
    // use Dotenv to load database info from .env file
    // DB_HOST, DB_USER, DB_PW,     DB_NAME
    // host,    user,    password,  database name
    require_once('vendor/autoload.php');
    $dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
    $dotenv->safeLoad();

    // Connecting, selecting database
    $mysqli = new mysqli($_ENV['DB_HOST'],$_ENV['DB_USER'],$_ENV['DB_PW'],$_ENV['DB_NAME']);
    if ($mysqli->connect_errno) {
        echo "Failed to connect to mysql: ".$mysqli->connect_errno." ".$mysqli->connect_error;
    }

    // Performing SQL query
    $query = <<<ENDQUERY
    SELECT
        DISTINCT department, department_code
    FROM
        ext_courses
    ORDER BY
        department
    ENDQUERY;

    $result = $mysqli->query($query);

    // iterating through results
    echo "<ul>\n";
    while ($row = $result->fetch_assoc()) {
      echo "<li>";
        echo $row['department'];
        echo "</li>\n";
     }
    echo "</ul>\n";

    // cleanup query result and close connection
    $query_result->free();
    $mysqli->close();
    ?>

## The entire "departments-simple.php"

- https://cscie12.dce.harvard.edu/cgi/ext-courses/departments-simple.php

    <!DOCTYPE html>
    <html>
     <head>
      <title>Departments</title>
      <link rel="stylesheet" href="styles/site.css" />
     </head>
     <body>
    <h1>Harvard Extension School</h1>
    <h2>Departments</h2>

    <?php
    // use Dotenv to load database info from .env file
    // DB_HOST, DB_USER, DB_PW, DB_NAME
    require_once('vendor/autoload.php');
    $dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
    $dotenv->safeLoad();

    // Connecting, selecting database
    $mysqli = new mysqli($_ENV['DB_HOST'],$_ENV['DB_USER'],$_ENV['DB_PW'],$_ENV['DB_NAME']);
    if ($mysqli->connect_errno) {
        echo "Failed to connect to mysql: ".$mysqli->connect_errno." ".$mysqli->connect_error;
    }

    // Performing SQL query
    $query = <<<ENDQUERY
    SELECT
        DISTINCT department, department_code
    FROM
        ext_courses
    ORDER BY
        department
    ENDQUERY;

    $result = $mysqli->query($query);

    // iterating through results
    echo "<ul>\n";
    while ($row = $result->fetch_assoc()) {
      echo "<li>";
        echo $row['department'];
        echo "</li>\n";
     }
    echo "</ul>\n";

    // cleanup query result and close connection
    $query_result->free();
    $mysqli->close();
    ?>

    <footer>
      <p>This is a learning example to demonstrate PHP and mysql for the courses CSCI E-12 and CSCI S-12 taught by David Heitmeyer.  <br/>
    The real <a href="https://courses.dce.harvard.edu/">Harvard Extension School course search</a> is at: <a href="https://courses.dce.harvard.edu/">courses.dce.harvard.edu</a></p>
    </footer>
     </body>
    </html>

## Adding another view - Department Course Listings

Create another PHP file that displays course information based upon a department_code parameter.

- `courses.php` - take a "department_code" parameter and produce alist of courses for that department.

Need to link to to courses.php:

- courses.php?department_code=CHEM
- courses.php?department_code=DGMD

Modify the department listing to include the hyperlink:

    // Printing results in HTML
    echo "<ul>\n";
    while ($row = $result->fetch_assoc()) {
      echo "<li>";
      echo "<a href=\"courses.php?department_code=$row[department_code]\">"
      echo "$row[department]"
      echo "</a>";
      echo "</li>\n";
    }
    echo "</ul>\n";

## courses.php

- courses.php?department_code=CHEM
- courses.php?department_code=DGMD

    <!DOCTYPE html>
    <html>
     <head>
      <meta charset="UTF-8"/>
      <title>Harvard Extension Courses</title>
      <link rel="stylesheet" href="styles/site.css" type="text/css"/>
     </head>
     <body>
    <h1>Harvard Extension Courses</h1>
    <p><a href="departments.php">Return to Department List</a></p>
    <?php

    // use Dotenv to load database info from .env file
    // DB_HOST, DB_USER, DB_PW,     DB_NAME
    // host,    user,    password,  database name
    require_once('vendor/autoload.php');
    $dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
    $dotenv->safeLoad();

    // Connecting, selecting database
    $mysqli = new mysqli($_ENV['DB_HOST'],$_ENV['DB_USER'],$_ENV['DB_PW'],$_ENV['DB_NAME']);
    if ($mysqli->connect_errno) {
        echo "Failed to connect to mysql: ".$mysqli->connect_errno." ".$mysqli->connect_error;
    }

    $dept_code = $_GET['department_code'];
    $sqlescaped_dept_code = $mysqli->real_escape_string($dept_code);
    $dept_code_html = htmlentities($dept_code);
    ?>
    <h2>Department - <?php echo $dept_code_html ?></h2>
    <?php
    // Performing SQL query
    $query = <<<ENDQUERY
    SELECT
      department,
      department_code,
      course_number,
      term,
      academic_year,
      short_title,
      title,
      description,
      faculty_description
    FROM
      ext_courses
    WHERE
      department_code = '$sqlescaped_dept_code'
    ORDER BY
      department,
      course_number,
      title
    ENDQUERY;

    $result = $mysqli->query($query);

    // Printing results in HTML

    $i = 0;
    while ($row = $result->fetch_assoc()) {
      // calculate year
      $academic_year_display = $row['academic_year'];
      if ($row['term'] == 'Spring' or $row['term'] == 'January') {
        $academic_year_display += 1 ;
      }

      $course_content = <<<ENDCONTENT
      <section class="course">
      <h2 class="abbrev"> $row[short_title] </h2>
      <div>
        <p class="term">$row[term] $academic_year_display</p>
        <p class="title"><strong>$row[title]</strong></p>
        <p class="faculty">$row[faculty_description]</p>
        <p class="description">$row[description]</p>
      </div>
      </section>
    ENDCONTENT;
      echo($course_content);
    }

    // cleanup query result and close connection
    $query_result->free();
    $mysqli->close();
    ?>
    <footer>
    <p><a href="./">PHP/mysql example list</a></p>
        <p>This is a learning example to demonstrate PHP and mysql for the courses CSCI E-12 and CSCI S-12 taught by David Heitmeyer.  <br/>
      The real <a href="https://courses.dce.harvard.edu/">Harvard Extension School course search</a> is at: <a href="https://courses.dce.harvard.edu/">courses.dce.harvard.edu</a>
        </p>
    </footer>
    </body>
    </html>

## Separation of Concerns

Separate the data the view using templates!

- PHP code connects to database and does query and gets the data
- Define how to display that data with a template (generic term, not referring to `<template>` element) -- and in this case, we'll use Mustache templates! Handlebars syntax is compatible with Mustache!
  Note that Twig is a popular template system to use with PHP.
  And note that there are many other template systems, including Liquid.

## {{Mustache}} Templates

{{mustache}} is another widely used template system for JavaScript (and other languages!).

## Mustache Departments

### Mustache Template

mustache-dept.php

### PHP

    <?php

      // use Dotenv to load database info from .env file
      // DB_HOST, DB_USER, DB_PW,     DB_NAME
      // host,    user,    password,  database name
      require_once('vendor/autoload.php');
      $dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
      $dotenv->safeLoad();

      // Connecting, selecting database
      $mysqli = new mysqli($_ENV['DB_HOST'],$_ENV['DB_USER'],$_ENV['DB_PW'],$_ENV['DB_NAME']);
      if ($mysqli->connect_errno) {
          echo "Failed to connect to mysql: ".$mysqli->connect_errno." ".$mysqli->connect_error;
      }

      // Performing SQL query
      $query = <<<ENDQUERY
      SELECT DISTINCT
             department,
             department_code
      FROM ext_courses
      ORDER BY department
      ENDQUERY;

      $result = $mysqli->query($query);
      $rows = $result->fetch_all(MYSQLI_ASSOC);

      $template_data['departments'] = $rows;

    // Process with Mustache Template
    include('lib/Mustache.php');

    $m = new Mustache;
    $template_file = 'mustache_templates/departments.html';
    $template_contents = file_get_contents($template_file);
    echo $m->render($template_contents, $template_data);

    // cleanup query result and close connection
    $mysqli->close();
    ?>

### Mustache Template

mustache_templates/departments.html

    <!DOCTYPE html>
    <html>

    <head>
      <meta charset="UTF-8" />
      <title>Harvard Extension School - Departments</title>
      <link rel="stylesheet" href="styles/site.css" />
    </head>

    <body>
      <h1>Harvard Extension School</h1>
      <h2>Departments</h2>
      <ul>
        {{#departments}}
        <li>
          <a href="mustache-courses.php?department_code={{department_code}}">{{department}}</a>
        </li>
        {{/departments}}
      </ul>

      <footer>
        <p><a href="./">PHP/mysql example list</a></p>
        <p>This is a learning example to demonstrate PHP and mysql for the courses CSCI E-12 and CSCI S-12 taught by David
          Heitmeyer. <br />
          The real <a href="https://courses.dce.harvard.edu/">Harvard Extension School course search</a> is at: <a
            href="https://courses.dce.harvard.edu/">courses.dce.harvard.edu</a>
        </p>
      </footer>
    </body>

    </html>

## Mustache Courses

    <!DOCTYPE html>
    <html lang="en">

    <head>
      <title>Harvard Extension Courses in {{ department_name }}</title>
      <link rel="stylesheet" href="styles/site.css" />
      <meta charset="UTF-8" />
    </head>

    <body>
      <h1>Harvard Extension Courses in {{ department_name }}</h1>
      <p><a href="mustache-dept.php">Return to Department List</a></p>
      <h2>{{department_name}}</h2>
      <div>
        {{#courses}}
        <section class="course">
          <h2 class="abbrev">{{ short_title }}</h2>
          <div>
            <p class="term">{{ term }} {{ academic_year_display }}</p>
            <p class="title">{{ title }}</p>
            <p class="faculty">{{ faculty_description }}</p>
            <p class="description">{{{ description }}}</p>
          </div>
          </section>
        {{/courses}}
      </div>

      <footer>
        <p><a href="./">PHP/mysql example list</a></p>
        <p>This is a learning example to demonstrate PHP and mysql for the courses CSCI E-12 and CSCI S-12 taught by David
          Heitmeyer. <br />
          The real <a href="https://courses.dce.harvard.edu/">Harvard Extension School course search</a> is at: <a
            href="https://courses.dce.harvard.edu/">courses.dce.harvard.edu</a>
        </p>
      </footer>
    </body>

    </html>

## Improving the Hello! Greeting

### We started with

Without a "name", present the user a form. With a name, provide a greeting.

- fourth.php
- fourth.php?name=John%20Harvard

    <?php
          $name = $_GET["name"];
    ?>
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <title>Greeting Page</title>
      </head>
      <body>
        <?php
          if ($name) {
            echo("<h1>Hello, $name!</h1>");
          } else {
            echo('<h1><label for="input_name">Enter name:</label></h1>');
            echo('<form method="get">');
            echo('<input type="text" name="name" id="input_name"/>');
            echo('<br /><input type="submit" />');
            echo('<br /><input type="reset" />');
          }
        ?>
      </body>
    </html>

## Hello! Greeting, Improved

- greeting/index.php
- greeting/index.php?name=John+Harvard

Three files: one code; two templates

- index.php
- greeting.html
- form.html

### index.php

    <?php
    $name = $_GET["name"];

    // figure out which template is needed
    if ($name) {
      $template_file = 'greeting.html';
    } else {
      $template_file = 'form.html';
    }
    $template_contents = file_get_contents($template_file);
    $template_data['name'] = $name;

    // Process with Mustache Template
    include('lib/Mustache.php');
    $m = new Mustache;

    echo $m->render($template_contents, $template_data);

    ?>

### greeting.html

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <title>Greeting Page for {{name}}</title>
      </head>
      <body>
          <h1>Hello, {{name}}!</h1>
      </body>
    </html>

### form.html

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <title>Greeting Page</title>
      </head>
      <body>
          <h1><label for="input_name">Enter name:</label></h1>
          <form method="get">
          <input type="text" name="name" id="input_name"/>
          <br /><input type="submit" />
          <br /><input type="reset" />
      </body>
    </html>

## Sending Email

Mail service -- e.g. Mailgun, Sendgrid, etc.

### submit.php Example (uses Mailgun)

    <?php require_once 'vendor/autoload.php';

         $loader = new \Twig\Loader\FilesystemLoader('./templates');
         $twig = new \Twig\Environment($loader, [
             'cache' => './compilation_cache',
             'debug' => true,
             'auto_reload' => true
         ]);
         $requestTime = new DateTime();
         $requestTime->setTimestamp($_SERVER['REQUEST_TIME']);
         $requestTimeHuman = $requestTime->format('Y-m-d\TH:i:s');

         $echocontent = $twig->render('form-response-template.html',
              [
              'getparams' => $_GET,
              'postparams' => $_POST,
              'httpheaders' => getallheaders(),
              'httpmethod' => $_SERVER['REQUEST_METHOD'],
              'serverinfo' => $_SERVER,
              'requesttime' => $requestTimeHuman,
              'httpreferer' => $_SERVER['HTTP_REFERER']
              ]);
         ?>

         <?php

         require 'vendor/autoload.php';
         use Mailgun\Mailgun;

         $mailto = filter_var($_POST['__mailto'], FILTER_VALIDATE_EMAIL);
         $mailkey = '';
         if (preg_match('/^csci(e|s)12\-(spring|summer|fall)-\d{4}-[a-z]+[0-9]+$/',$_POST['__mailkey'])) {
            $mailkey = $_POST['__mailkey'];
         }

         // only send if POST and if __mailto and if __mailkey exist

         if (strcmp($_SERVER['REQUEST_METHOD'],'POST') == 0 && $mailto && $mailkey ) {
           error_log("FormSubmit | MAILGUN | $mailkey | $mailto |");
           // First, instantiate the SDK with your API credentials
           $MG_API_KEY = getenv('MG_API_KEY');
           $MG_DOMAIN = getenv('MG_DOMAIN');
           $MG_ = getenv('MG_');

           $mg = Mailgun::create($MG_API_KEY); // For US servers
           $domain = $MG_DOMAIN;

           // Now, compose and send your message.
           // $mg->messages()->send($domain, $params);
           $mg->messages()->send($domain, [
             ''    => $MG_,
             'to'      => $mailto,
             'subject' => 'Form Submission',
             'html'    => $echocontent
           ]);
         }

         echo($echocontent);
         ?>

### form_response_template.html

This is a PHP "Twig" template.

    <DOCTYPE html>
         <html lang="en">
           <head>
            <title>Form Submission</title>
            <style><!-- inline styles removed for clarity --></style>
           </head>

           <body>
             <h1>Form Submission</h1>
             {% if getparams %}
             <h2>GET Parameters</h2>
             <table>
               <thead>
                 <tr><th>Name</th><th>Value</th></tr>
               </thead>
               <tbody>
               {% for key, value in getparams %}
               <tr>
                 <th>{{ key }}</th>
                 <td>
                   {% if value is iterable %}
                   {% for v in value %}
                     {{ v }}{% if not(loop.last) %},<br/>{% endif %}
                   {% endfor %}
                   {% else %}
                     {{ value }}
                   {% endif %}
                 </td>
               </tr>
               {% endfor %}
               </tbody>
             </table>
             {% endif %}

             {% if postparams %}
             <h2>POST Parameters</h2>
             <table>
               <thead>
                 <tr><th>Name</th><th>Value</th></tr>
               </thead>
               <tbody>
               {% for key, value in postparams %}
               <tr>
                 <th>{{ key }}</th>
                 <td>
                   {% if value is iterable %}
                   {% for v in value %}
                     {{ v }}{% if not(loop.last) %},<br/>{% endif %}
                   {% endfor %}
                   {% else %}
                     {{ value }}
                   {% endif %}
                 </td>
               </tr>
               {% endfor %}
               </tbody>
             </table>
             {% endif %}

             {% if serverinfo %}
             <h2>Request Information</h2>
             <table>
               <thead>
                 <tr><th>Name</th><th>Value</th></tr>
               </thead>
               <tbody>
                 <tr><th>Request Time</th><td>{{ requesttime }}</td></tr>
                 <tr><th>Remote Address</th><td>{{ serverinfo['REMOTE_ADDR'] }}</td></tr>
                 <tr><th>HTTP Referrer</th><td><a href="{{ httpreferer }}">{{ httpreferer }}</a></td></tr>
                 <tr><th>HTTP Method</th><td>{{ httpmethod }}</td></tr>
               </tbody>
             </table>
             {% endif %}

             <footer>
               <p>This form submission tool is only for use by current students in <a href="https://cscie12.dce.harvard.edu/">CSCI E-12</a> and <a href="https://cscis12.dce.harvard.edu/">CSCI S-12</a> courses.</p><p>David Heitmeyer | <a href="https://extension.harvard.edu/">Harvard Extension School</a> | <a href="https://summer.harvard.edu/">Harvard Summer School</a></footer>
           </body>
          </html>

## CSR (Client Side Rendering)

### Front-end JavaScript + templates and Back-end JSON

Departments

- json-dept.php - PHP script that produces JSON
- departments.html - uses Handlebars

Courses

- json-courses.php?department_code=CHEM - PHP script that produces JSON
- courses.html?department_code=CHEM - uses Handlebars

## Getting JSON from HTTP request

JavaScript functions are often asynchronous -- the script continues to run before a step has completed!

### Javascript "fetch"

    fetch(url).then(response => response.json()).then(data => processData(data));

- MDN: Using Fetch
- MDN: Arrow Functions
- Introduction to Arrow Functions

## Let's Try It Out!

- Apples
- Courses
- National Park Service

## Apples

- Apples - https://cscie12.dce.harvard.edu/apples-pyo.php

You may find a "JSON Viewer" plugin or extension for your browser useful if you work with JSON

## Apples

- apples-fetch.html
- JSON data apples-pyo.php

The JavaScript:

    let applesUrl = "https://cscie12.dce.harvard.edu/apples-pyo.php";
      document.addEventListener('DOMContentLoaded',function(){
        fetch(applesUrl)
          .then(response => response.json())
          .then(data => buildApplesList(data));
      });

      function buildApplesList(data){
        let template = document.getElementById('apple-template').innerHTML ;
        console.log(template);
        let compiledTemplate = Handlebars.compile(template);
        let rendered = compiledTemplate(data);
        document.getElementById('applelist').innerHTML = rendered;
      }

The template:

    <template id="apple-template">
      <h2>Picking Now</h2>
        <ul>
          {{#apples.picking_now}}
            <li>{{ . }}
          {{/apples.picking_now}}
        </ul>

        <h2>Picking Soon</h2>
        <ul>
          {{#apples.picking_soon}}
            <li>{{ . }}
          {{/apples.picking_soon}}
        </ul>
      </template>

## JS and fetch

- MDN: Using Fetch
- MDN: Arrow Functions
- Introduction to Arrow Functions

    /* mlb api;  sportId = 1 is major league */
      let urlTeams = "https://statsapi.mlb.com/api/v1/teams?sportId=1";

      document.addEventListener("DOMContentLoaded", function () {
        fetch(urlTeams)
          .then(response => response.json())
          .then(data => buildList(data.teams));
      });

## Courses — PHP and JSON data

Two problems to solve here:

- Producing JSON data on server side
- Processing JSON data on client-side

    <?php

    /// use Dotenv to load database info  .env file
    // DB_HOST, DB_USER, DB_PW, DB_NAME
    require_once('vendor/autoload.php');
    $dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
    $dotenv->safeLoad();

    // Connecting, selecting database
    $mysqli = new mysqli($_ENV['DB_HOST'],$_ENV['DB_USER'],$_ENV['DB_PW'],$_ENV['DB_NAME']);
    if ($mysqli->connect_errno) {
        echo "Failed to connect to mysql: ".$mysqli->connect_errno." ".$mysqli->connect_error;
    }

    $dept_code = $_GET['department_code'];
    $sqlescaped_dept_code = $mysqli->real_escape_string($dept_code);

    // Performing SQL query
    $query = <<<ENDQUERY
    SELECT
      department,
      department_code,
      course_number,
      term,
      academic_year,
      short_title,
      title,
      description,
      faculty_description

      ext_courses
    WHERE
      department_code = '$sqlescaped_dept_code'
    ORDER BY
      department,
      course_number,
      title
    ENDQUERY;

    $query_result = $mysqli->query($query);

    $i = 0;
    while ($row = $query_result->fetch_assoc()) {
      // calculate year
      $academic_year_display = $row['academic_year'];
      if ($row['term'] == 'Spring' or $row['term'] == 'January') {
        $academic_year_display += 1 ;
      }
      $row['academic_year_display'] = $academic_year_display;

      $results[$i++] = $row;
    }

    $template_data['courses'] = $results;
    $template_data['department_name'] = $dept_code;

    header('Content-type: application/json');
    echo json_encode($template_data);

    // cleanup query result and close connection
    $query_result->free();
    $mysqli->close();
    ?>

## Front-end courses

For example: CSCI courses (`courses.html?department_code=CSCI`)

- Use JavaScript `fetch` to get the JSON data
- Use Handlebars to process the data

    <!DOCTYPE html>
    <html>

    <head>
      <meta charset="utf-8" />
      <title>Departments</title>
      <link rel="stylesheet" href="styles/site.css" />
      <script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.7.7/handlebars.min.js"
        integrity="sha512-RNLkV3d+aLtfcpEyFG8jRbnWHxUqVZozacROI4J2F1sTaDqo1dPQYs01OMi1t1w9Y2FdbSCDSQ2ZVdAC8bzgAg=="
        crossorigin="anonymous"></script>

      <script>
        let dataUrl = './json-courses.php';
        let urlParams = new URLSearchParams(window.location.search);
        console.log(urlParams.get('department_code'));
        let department_code = urlParams.get('department_code');
        document.addEventListener('DOMContentLoaded', function () {
          fetch(dataUrl + '?department_code=' + department_code)
            .then(response => response.json())
            .then(data => {
              console.log(data);
              let mysource = document.getElementById('courses-list-template').innerHTML;
              let mytemplate = Handlebars.compile(mysource);
              let myresult = mytemplate(data)
              document.getElementById('courses-list').innerHTML = myresult;
            });
        });
      </script>

    </head>

    <body>
      <h1>Harvard Extension School</h1>
      <p><a href="departments.html">Return to Department List</a></p>

      <div id="courses-list">

      </div>

      <div id="courses-list-template" class="handlebars">
        <h2>{{ department_name }}</h2>
        <p>{{ courses.length }} courses</p>
        <div>
          {{#courses}}
          <section class="course">
            <h2 class="abbrev">{{ short_title }}</h2>
            <div>
              <p class="term">{{ term }} {{ academic_year_display }}</p>
              <p class="title">{{ title }}</p>
              <p class="faculty">{{ faculty_description }}</p>
              <p class="description">{{{ description }}}</p>
            </div>
          </section>
          {{/courses}}
        </div>

        <footer>
          <p><a href="./">PHP/mysql example list</a></p>
          <p>This is a learning example to demonstrate PHP and mysql for the courses CSCI E-12 and CSCI S-12 taught by David
            Heitmeyer. <br />
            The real <a href="https://courses.dce.harvard.edu/">Harvard Extension School course search</a> is at: <a
              href="https://courses.dce.harvard.edu/">courses.dce.harvard.edu</a>
          </p>
        </footer>

    </body>

    </html>

## Next Time

- JavaScript Frameworks that can make this easier!
- Build time rendering (BTR) or Static Site Generation (SSG) approach!
- Punch list of things you should have heard about before completing an intro web development class!