NSWI142: Web Applications

5. PHP Application I.

Štěpán Stenchlák, KSI
stepan.stenchlak@matfyz.cuni.cz

Preliminaries

Please read this section at least one day prior to the seminar. This section outlines what you are expected to know, be able to do, or prepare in advance. Following these instructions will help you get the most out of the seminar and ensure smooth participation.

Preliminaries

Please make sure you BRING A PEN with you to the practical. In addition, before the start of the practical, you should be able to:

  • Create an HTML form and process it using PHP script.
  • Read HTTP query and POST data from PHP script.
  • Use interleaving and print, or echo, to produce PHP script output.
  • include or require a PHP file.

You can use OneCompiler PHP to test yourself before the lecture.

Preliminaries software

This slide applies to you only if you plan to use your own computer for the practical.

Before the start of the practical, make sure that:

Agenda

  • Exercise: Project review
  • Exercise: Fixing the project
  • Demonstration: Front controller
  • Demonstration: Unit test
  • Exercise: Unit test

PHP - Šablonátor

  • How easy is to add new types of blocks such as {while cond} ... {/while}
  • Name variables accordingly:
    • Do not use $i for the position in the text when processing the template.
  • Use block comments for variables (see the next slide)
  • Extending Exceptions

Using block comments

<?php

$variable1 = 1; // This is variable 1

// This is variable 2
$variable2 = 2;

/**
 * This is variable 3
 */
$variable3 = 3;

// --------------------------------

$variable1;
$variable2;
$variable3;

Extending Exceptions

<?php

/**
 * Exception thrown when a tag is not properly closed.
 */
class UnclosedTagException extends Exception
{
  public readonly string $tagName;
  public readonly int $lineNumber;

  public function __construct($tagName, $lineNumber)
  {
    $this->tagName = $tagName;
    $this->lineNumber = $lineNumber;

    $message = "Unclosed tag {$tagName} detected at line $lineNumber.";
    parent::__construct($message);
  }
}

Exercise: Project review

You already know how to create a simple web application to register users for an event. The application consists from a landing page, registration form, confirmation, etc.. Yet, in reality you are likely to work in an existing codebase rather than staring from nothing.

Project review

Download the event registration project, unpack it, run it, explore it. You can run the project using PHP


      php -S 127.0.0.1:8080
    

Imagine you are doing a review and want to submit the review to GitHub. We use default GitHub labels:

  • Bug - Something isn't working
  • Enhancement - New feature or request

As we do not have GitHub repository ready ( ... work in progress), we utilize pen and paper today.

Focus on functionality, visuals, and the code. In addition, you should mark issues as "critical" or "low" to indicate priorities. These priorities are important for developers to know what they should focus on first.

Task Complete

Congratulation, if you have followed the instruction you just reached the end of this exercise.

Exercise: Fixing the project

Issues have been identified. Now it is your turn to fix them.

Well, that is your problem now.

Reading query arguments

We can do better with filter_input function to read values from $_GET and $_POST.


    <?php
    // Value is NULL - if the value is not set.
    // Value is false - if the value is not integer.
    // Value is of type int - if a number value is provided.
    $counter = filter_input(INPUT_GET, 'counter', FILTER_VALIDATE_INT);

    // We can use the fourth argument to customize the behavior
    $page = filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT, [
      'options' => [ 'default' => 0, 'min_range' => 0, 'max_range' => 12
    ]]);
    

The function can be used with various options.

The function can read from different inputs such as INPUT_GET, INPUT_POST, INPUT_SESSION, INPUT_SERVER, ...

Redirect on POST

To prevent form resubmit on refresh it is a good idea to use redirect.


    <?php
    // Keep in mind you must not send any output before calling header function.
    // This will instruct browser to perform GET at given URL.
    // Take a note that we may need to transfer the data to the new location.
    header("Location: ./form.php?name=petr");
    exit();
    

Sanitization

Task Complete

Congratulation, if you have followed the instruction you just reached the end of this exercise.

Demonstration: Front controller

We need all request to arrive at the bootstrap script. From there we can perform routing and dispatching. A good practice is to put the index.php, the bootstrap script, file into a public directory.

Front controller - PHP build-in server

Running with PHP build-in server is easy.


    php -S 127.0.0.1:8888 ./public/index.php
    

You can try using a web browser that all request are handled by the single file. You can find the original URL in $_SERVER['REQUEST_URI'].

Front controller - Apache configuration

The Apache server must be configured to allow for use of .htaccess and rewrites. webik.ms.mff.cuni.cz is configured in this way. We need two file to make it work.

The first .htaccess file is located in root of your project. It redirects all request to the public directory.


      RewriteEngine on
      RewriteRule ^$ public/ [L]
      RewriteRule (.*) public/$1 [L]
    

The second .htaccess file is in the public directory. It redirects requests to the index.php file.


      RewriteEngine On
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteCond %{REQUEST_FILENAME} !-d
      RewriteRule ^ index.php [QSA,L]
    

Keep in mind that files starting with dot '.', like .htaccess, are hidden by default on some systems.

Demonstration: Unit test

Máte sklep? A mohla bych ho vidět?

Unit tests

How can you ensure that your app continues to work as you add more features or change existing functionality?
By writing tests. Unit tests are handy for verifying the behavior of a single function, method, or class.

— Flutter, An introduction to unit testing

A unit test is a type of software test that focuses on testing individual components of a software product.

— Bright, Unit Testing: Definition, Examples, and Critical Best Practices

Unit testy testují malé jednotky programu, typicky jednotlivé třídy a metody v nich.

— Lubomír Bulej, MFF UK, Best Practices in Programming, Unit testing and testable design (CS)

PHPUnit

PHPUnit is a programmer-oriented testing framework for PHP. There is a small PHP cheat sheet you can use.

We are going to utilize only some basic stuff from PHP unit. If you want to know more, or you missed something, please read the PHPUnit manual.

In the Organizing Tests section, there is an approach to put tests into a separate directory called ./tests/unit.

Exercise: Unit test

Testing the application

Pick a piece of code from the given application and made it testable. Then write a test using PHPUnit.

Questions, ideas, or any other feedback?

Please feel free to use the anonymous feedback form.