NSWI142: Web Applications

6. PHP Application III.

Š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 have prepared in advance. Following these instructions will help you get the most out of the seminar and ensure smooth participation.

Preliminaries

Before the start of the practical, you should be able to:

  • Explain Model-View-Presenter and how to use it with PHP.
  • Explain what SQL is and what a relational database is.
  • Use SQL commands CREATE, UPDATE, SELECT, and DELETE.
  • Explain what prepared statements are and how to use them.

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:

  • You have enabled the mysqli extension in your php.ini file.
    You can test this by executing the following code snippet.
    
              new mysqli('localhost', 'my_user', 'my_password', 'my_db');
            
    If you get
    ... Uncaught Error: Class "mysqli" not found in php shell code: ...
    exception, the extension is likely not properly enabled.

Agenda

  • Work on the semestral project, introduction to SQL:
    • Model-View-Presenter (MVP)
    • Databases in PHP
    • Adminer
    • Working with database
    • Exercise: Connecting your models

Updates

New task PHP - REST API Router (non-mandatory, 2 points).

First draft of semestral project assignment: teaching.mff.cuni.cz/nswi142-web/semestral-project/. Please give us feedback if something is unclear. At the end of the next week, we will publish the final version.

MVP

Databases

  • Why do we need databases?
  • What are the benefits compared to .json files?
  • What is a relational database?
  • What is SQL?

MySQL on Webik

There is a MySQL server running on Webik, but it is accessible only from Webik itself (due to firewall rules).

  • Host: localhost
  • Username: your username
  • Password: your original password sent to you at the beginning of the course
  • Your database: stud_<username>

You can try logging in via Adminer on webik.ms.mff.cuni.cz/adminer.

Feel free to use your own SQL database for development, but you will be required to use Webik's MySQL database for your semestral project.

You can also use:

  • More complex phpMyAdmin.
  • Command line tool mysql -p from Webik server.

Accessing Webik MySQL from your own machine

Use SSH tunneling to forward the MySQL port from Webik to your local machine.

ssh -L 3306:localhost:3306 webik

Then, you can use 127.0.0.1 as host for MySQL connection on your PC.

Note: According to the documentation, we cannot use localhost as it is bound to Unix sockets, which we do not have. Therefore, you need to use 127.0.0.1 to explicitly indicate that we want a TCP/IP connection.

Do not forget to have mysql php extension installed. (On Linux, install php-mysql.)

Showcase

Basic use of Adminer on Webik:

  • login/logout
  • navigation (including export/import)
  • my database
  • create table (primary keys, auto increment, default values, collations, inspecting queries)
  • insert/delete data (plus inspecting queries)
  • execute query (including JOINs)

Connecting to the Database

Using the object-oriented API:


$mysqli = new mysqli($host, $user, $password, $database);
if ($mysqli->connect_error) { /* handle error */ }

// work with the connection for the whole duration of the script ...

$mysqli->close();
    

Connection is closed automatically after the script execution. As a result, closing the connection is in general optional. For you, it is mandatory for NSWI142.

Do NOT use the old mysql_* functions!

Utilize a single connection per user request (i.e., one PHP script invocation). Do NOT create a new connection for every SQL query.

If a query fails, an error message can be obtained using $mysqli->error. See the documentation for the object-oriented and procedural versions.

Fetching results from the database

Using the object-oriented API:


if ($result = $mysqli->query("SELECT * FROM MyTable")) {
  // fetch associative array
  while ($row = $result->fetch_assoc()) {
    // access $row["Column1"], $row["Column2"], ...
  }
}
    

Use only for static queries with NO user input.

See mysqli_result class documentation for more details.

SQL Injection

SQL Injection

SQL Injection

SQL Injection is technique abusing SQL statements constructed from user inputs without proper sanitization. Similar technique can be employed in other scenarios as well.

It can be leveraged to extract database data, tamper with existing data, spoof identity, escalate privileges, …

Hackers ARE interested in my little website.

Don't Try This at Home !!!


$query = 'SELECT * FROM products WHERE title = "'. $_GET['search'] . '"';
$query_result = $mysqli->query($query);
      

Preventing SQL Injection

There is a section about SQL Injection in PHP manual.

There are functions that can escape strings similar to htmlspecialchars for HTML. Using them is not recommended.

Use prepared statements with bound variables.


// Notice no quotes around '?'.
$stmt = $mysqli->prepare("INSERT INTO myTable VALUES (?, ?)");

// Bind variables to '?' with hinting the type (string, double).
// Function takes references, thus you must use variables.
$stmt->bind_param('sd', $aStringVar, $aDoubleVar);

$stmt->execute();

$query_result = $stmt->get_result();
    

Exercise 1/2

Modify the EventModel from the last practicals to use MySQL database instead.

Hints (go further to reveal them):

  • How many tables do you need? Typically one table per entity: event - event table, user - user table. Then, tables for m:n relations: user is registered to event - event_participant table.
  • What columns are necessary? Each concept (User, Event, Article) should have its numerical unique ID that is managed by the database: id INT(4) NOT NULL PRIMARY KEY AUTO_INCREMENT

Exercise 2/2

  • Add event date and implement sorting and filtering on the list of events at /events.
  • Hints (go further to reveal them):

    • How to implement the UI? Use form with method GET and action to self. Do not forget to prefill the current state and handle no state.
    • How to construct the query?
    • 
      <?php
      $query = "SELECT * FROM articles";
      $bindTypes = "";
      $bindValues = [];
      
      if (...) {
        $query .= " WHERE name LIKE ?"; // Check SQL LIKE operator if needed
        $bindTypes .= "s";
        $bindValues[] = "%" . $searchTerm . "%";
      }
      
      $mysqli->prepare($query);
      if (count($bindValues) > 0) {
        $stmt->bind_param($bindTypes, ...$bindValues);
      }
                    

Next steps in MVP

Create a template for a 404 page.

Implement an ErrorPresenter that is called when the Front Controller cannot find an appropriate Presenter. Don't forget to return a 404 status code.

Exercise: Who gets the bonus point?

List of students to receive a bonus point. Deadline next practicals.

Questions, ideas, or any other feedback?

Please feel free to use the anonymous feedback form.