Every code example in the presentation has a name
GitHub repo:
https://github.com/NHLStenden/Webdev-PHP
Installed in the VM
git pull to get the latest version!
Client Server (HTTP)
Installation & Configuration
Basic Language Constructs
Form handling
https://laracasts.com/skills/php (recommended video tutorial)
Client = Browser
Server = Machine that server request of Clients
HTTP = HyperText Transfer Protocol
We use: Apache
We use: Apache webserver + PHP + MySQL (MariaDb)
In de browser:
student.local/
docent.local/
In de directory: /home/student/websites
See Blackboard for instruction
Warning: do not start up the browser for PhpStorm!
Skips the next slides if you use the VM, recommended
It saves your time as well as it is easy to use.XAMPP, WAMP, LAMP, MAMP are local servers that are mainly used while developing PHP websites.
Choose a Development Server Distribution, Download & Install
Place Your PHP Code in the
<!DOCTYPE html>
<!-- https://www.w3schools.com/php7/ -->
<html>
<body>
<?php
echo "My first PHP script!";
?>
</body>
</html>
HelloWorld.php
IDE == Integrated Development Environment == Text editor For programmers
PhpStorm recommended
Change the following in the php.ini file:
<?php
$text = ""
echo $text;
?><?
$text = "";
echo $text;
?>Use <? instead of <?php
short_open_tag = On
display_errors = On
Follow youtube videos to help you!
search terms: xampp xdebug phpstorm
https://www.youtube.com/watch?v=VL60RCKv7lQ&t=9s
For Mac OSX I had only success with:
<?php
$txt = "Hello world!";
$x = 5;
$y = 10.5;
echo "x: $x";
print("y: $y");
print("HW: " .$txt);
?>Types? Determined by assignment.
i.e. dynamic typing
Tip: decide which type a variable has, don't change it!
<?php
$txt = "Hello world!";
$x = 5;
$y = 10.5;
echo "x: $x";
print("y: $y");
print("HW: " .$txt)
?>Types? Determined by assignment.
i.e. dynamic typing
Tip: decide which type a variable has, don't change it! I'm guilty in some examples (form validation).
<?php
//string
$x = "Hello world!";
$y = 'Hello world!';
echo $x;
echo "<br>";
echo $y;
//integer
$x = 5985;
var_dump($x);
//float
$x = 10.365;
var_dump($x);
//boolean
$x = true;
$y = false;
//array
$cars = array("Volvo","BMW","Toyota");
var_dump($cars);
?><?php
//object
class Car {
function Car() {
$this->model = "VW";
}
}
// create an object
$herbie = new Car();
// show object properties
echo $herbie->model;
//null
$x = null;
var_dump($x);
?><pre>
<?php
$hw = "Hello World";
$h = "Hello";
$s = " ";
$w = "World";
$hw2 = $h . $s . $w; //concat
$hw3 = "Hello $w"; //string interpolation
echo $hw2 ."\n";
print($hw3 ."\n");
//string functions
echo strlen("Hello World!\n");
echo str_word_count("Hello world!\n");
echo strrev("Hello world!") ."\n";
//https://www.w3schools.com/php7/php7_ref_string.asp
echo "test $h \n";
//echo "test $(1+2)"; not possible
?>
</pre>
<?php
$t = date("H");
if ($t < "10") {
echo "Have a good morning!";
} elseif ($t < "20") {
echo "Have a good day!";
} else {
echo "Have a good night!";
}
?>If-statement
<?php
$favcolor = "red";
switch ($favcolor) {
case "red":
echo "Your favorite color is red!";
break;
case "blue":
echo "Your favorite color is blue!";
break;
default:
echo "Your favorite color is neither red, blue, nor green!";
}
?>Switch-statement
<?php
$x = 10;
$y = 10;
echo $x == $y; //true
$x = 10.0;
echo $x == $y; //true
echo $x === $y; //false
$w = null;
$x = $w ?? 'leeg'; //$x == 'leeg'
$y = "t";
$y = 10;
$x = $y == 10 ? "tien" : "geen tien"; //$x == "tien"
$y = 8;
$x = $y == 10 ? "tien" : "geen tien"; //$X == "geen tien"
$x = 10 == 10 && 11 == 11;
$x = 10 == 9 || 11 == 11;
$x = $x or false and 'test' == 'Test' xor 3;
?><?php
$x = 1;
while($x <= 5) {
echo "The number is: $x <br>";
$x++;
}
//https://www.w3schools.com/php7/php7_loop_while.asp
?><?php
for ($x = 0; $x <= 10; $x++) {
echo "The number is: $x <br>";
}
//https://www.w3schools.com/php7/php7_loop_for.asp
?><?php
$colors = array("red", "green", "blue", "yellow");
foreach ($colors as $value) {
echo "$value <br>";
}
//https://www.w3schools.com/php7/php7_loop_for.asp
?><?php
$colors = array("red", "green", "blue", "yellow");
foreach ($colors as $value) {
echo "$value <br>";
}
//https://www.w3schools.com/php7/php7_loop_for.asp
?>To modify values in the
<?
$arr = array(1, 2, 3, 4);
foreach ($arr as &$value) {
$value = $value * 2;
}
print_r($arr);
//https://www.php.net/manual/en/control-structures.foreach.php
?><?
foreach (array("red", "green", "blue", "yellow") as $key => $value) {
// $arr[3] will be updated with each value from $arr...
echo "{$key} => {$value} ";
}
print_r($arr); //prints array of object, very useful
?><?php
$cars = array("Volvo", "BMW", "Toyota");
print_r($cars);
?>Array initialization/creation:
<?php
$cars[0] = "Volvo";
$cars[1] = "BMW";
$cars[2] = "Toyota";
print_r($cars);
?><?php
$cars[] = "Volvo";
$cars[] = "BMW";
$cars[] = "Toyota";
print_r($cars);
?><?php
$cars = array("Volvo", "BMW", "Toyota");
$arrlength = count($cars);
for($x = 0; $x < $arrlength; $x++) {
echo $cars[$x];
echo "<br>";
}
?><?
$age = array("Peter"=>"35", "Ben"=>"37", "Joe"=>"43");
print_r($age);
echo "Peter is " . $age["Peter"] . " years old.";
foreach($age as $x => $x_value) {
echo "Key=" . $x . ", Value=" . $x_value;
echo "<br>";
}
?>Array is also an associative array a stack and a list
Arrays can be used as a stack
array_pop(), array_push()
Useful array methods:
https://www.php.net/manual/en/ref.array.php
<!-- functions.php -->
<?php
function add($x, $y, $z = 0) {
return $x + $y + $z;
}
print add(3, 2);
print "<br/>";
print add(5, 4, 2);
?>Functions in PHP (documentation):
https://www.php.net/manual/en/funcref.php
There is a lot of functionality available!
<!-- form_post -->
<form action="process_post_form.php" method="post">
Name: <input type="text" name="name"><br>
E-mail: <input type="text" name="email"><br>
<input type="submit">
</form><!-- process_post_form.php -->
Welcome <?php echo $_POST["name"]; ?><br>
Your email address is: <?php echo $_POST["email"]; ?>
<!-- form_post.php -->
<form action="process_post_form.php" method="get">
Name: <input type="text" name="name"><br>
E-mail: <input type="text" name="email"><br>
<input type="submit">
</form><!-- process_form_get.php -->
Welcome <?php echo $_GET["name"]; ?><br>
Your email address is: <?php echo $_GET["email"]; ?>POST
GET
<!-- empty_action.php -->
<?php
if(isset($_POST["name"])) {
var_dump($_POST["name"]);
}
if(!empty($_POST["email"])) {
var_dump(isset($_POST["email"]));
}
?>
<form method="post">
Name: <input type="text" name="name"><br>
E-mail: <input type="text" name="email"><br>
<input type="submit">
</form>
If the action attribute in a form is empty (not specified) than the input can be processed on the same page!
<!-- check_method.php -->
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if(isset($_POST["name"])) {
var_dump($_POST["name"]);
}
if(isset($_POST["email"])) {
var_dump(isset($_POST["email"]));
}
} else { // else if ($_SERVER['REQUEST_METHOD'] === 'GET')
?>
<form method="post">
Name: <input type="text" name="name"><br>
E-mail: <input type="text" name="email"><br>
<input type="submit">
</form>
<?php
}
?><!-- hacked.php -->
<?php
if(isset($_GET['name'])) {
echo $_GET['name'];
}
?>
<form method="get">
Name: <input type="text" name="name"><br>
<input type="submit">
</form>Example:
!!!Use filter_var()!!!!
<!-- form_validation.php -->
<?php
$nameErr = $ageErr = "";
$name = $age = "";
$error = true;
if($_SERVER["REQUEST_METHOD"] === "POST") {
$error = false;
if(empty($_POST["name"])) {
$nameErr = "name is required";
$error = true;
} else {
$name = filter_var($_POST["name"], FILTER_SANITIZE_STRING);
}
if(empty($_POST["age"])) {
$ageErr = "age is required";
$error = true;
} else {
$age = filter_var($_POST["age"], FILTER_VALIDATE_INT);
if($age === false) {
$ageErr = "age is incorrect";
$age = "";
$error = true;
} else {
if($age < 18) {
$ageErr = "to young";
$error = true;
}
}
}
}
?>
<form method="post">
Name: <input type="text" name="name">* <?php echo $nameErr ?>
Age: <input name="age">* <?= $ageErr ?>
<button type="submit">Submit</button>
</form>
<?php
if(!$error) {
echo "Name: $name <br/> Age: $age ";
}
?><!-- form_validation2.php -->
<?php
$name = $price = $description = $email = "";
$errorPrice = $errorDescription = $errorEmail = $errorName = "";
$minPrice = 1.0; $maxPrice = 100.0;
$error = false;
if($_SERVER["REQUEST_METHOD"] === "POST")
{
//SANITIZE
if(empty($_POST['name'])) {
$errorName = "Name Required";
$error = true;
} else {
$name = filter_var($_POST['name'], FILTER_SANITIZE_STRING);
if($name === false) {
$errorName = "Error in name";
$error = true;
$name = "";
}
}
//SANITIZE
if(empty($_POST['description'])) {
$errorDescription = "Description is empty";
$error = true;
} else {
$description = filter_var($_POST['description'], FILTER_SANITIZE_STRING);
if($description === false) {
$errorDescription = "Error in Description";
$error = true;
}
}
//VALIDATE FLOAT!
if(!empty($_POST['price'])) {
$price = filter_var($_POST['price'], FILTER_VALIDATE_FLOAT);
if($price === false) {
$errorPrice = "No valid Price between $minPrice and $maxPrice";
$error = true;
}
}
//VALIDATE EMAIL!
if(!empty($_POST['email'])) {
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
if($email === false) {
$errorEmail = "Invalid Email";
$error = true;
}
}
}
?>
<? if($error) {
print "<b>Invalid input</b>";
}
?>
<form method="post">
<label>Name*</label> <input type="text" name="name" value="<?= $name ?>">
<span class="error"><?= $errorName ?></span>
<br/>
<label>Description*</label> <input type="text" name="description" value="<?= $description ?>">
<? if(!empty($errorDescription)) { ?>
<span class="error"><?= $errorDescription ?></span>
<? } ?>
<br/>
<label>Price</label> <input type="text" name="price" value="<? echo $price ?>">
<span class="error"><?= $errorPrice ?></span>
<br/>
<label>Email</label> <input type="text" name="email" value="<?= $email ?>">
<?= isset($errorEmail) ? "<span class='error'>$errorEmail</span>" : '' ?>
<br/>
<button type="submit">Add Product</button>
</form>
<style>
.error {
background-color: red;
}
</style><?php
if(isset($_POST["add"])) {
echo "Add";
}
if(isset($_POST["delete"])) {
echo "Delete";
}
if(isset($_POST["operation"])) {
$operation = $_POST["operation"];
switch ($operation) {
case "add": echo "Add"; break;
case "delete": echo "Delete"; break;
}
}
?>
<form method="post">
<button name="add">Add</button>
<button name="delete">Delete</button>
</form>
<form method="post">
<input type="submit" name="add" value="Add">
<input type="submit" name="delete" value="Delete">
</form>
<!-- multiple forms -->
<form method="post">
<input type="hidden" name="operation" value="add">
<button type="submit">Add</button>
</form>
<form method="post">
<input type="hidden" name="operation" value="delete">
<button type="submit">Delete</button>
</form>
State Management Categories
Client Side
Query Parameters (GET)
Query String
Hidden form fields (POST)
Server Side
Cookies
Sessions (uses cookies)
Limited to strings only (except Session)
casting to right datatype
Categories are a little bit artificial
Client Side
Hidden form fields (POST)
Examples:
Id's, Action
<!-- hiddenFormField.php -->
<?php
$count = (int)($_POST["count"] ?? 0);
$count++;
?>
<?= $count ?>
<hr/>
<form method="post">
<input type="hidden" name="count" value="<?= $count ?>"/>
<button>Inc</button>
</form>
Action Example
<!-- multipleButtons.php -->
<?php
$operation = $_POST['operation'] ?? "";
if($operation === "add") {
echo "Add Button Clicked";
} else if ($operation === "sub") {
echo "Sub Button Clicked";
}
?>
<form method="post">
<button name="operation" value="add" type="submit">+</button>
<button name="operation" value="sub" type="submit">-</button>
</form>ID + Action in Buttons
<!-- part of the code of the todo example -->
<?php
if($_SERVER["REQUEST_METHOD"] === "POST") {
if (isset($_POST["ACTION"])) {
$action = $_POST["ACTION"];
if ($action === "DeleteTodo") {
//delete todo item
} else if ($action === "EditTodo") {
//edit todo item
}
}
}
//code to load todo items in $rows
?>
<ul>
<? foreach ($rows as $row) { ?>
<li>
<?= $row["Description"] ?>
<form method="post">
<input type="hidden" name="todoId" value="<?= $row["TodoId"] ?>">
<button type="submit" name="ACTION" value="DeleteTodo">Delete</button>
<button type="submit" name="ACTION" value="EditTodo">Edit</button>
</form>
</li>
<? } ?>
</ul>GET Request
Can be bookmarked
test.php?key1=value1&key2=value2
limited compared to forms
size, no uploads, everything is visable
<!-- queryparameter.php -->
<?php
$count = (int)($_GET["count"] ?? 0);
$count++;
?>
<?= $count ?>
<hr>
<form method="get">
<input type="hidden" name="count" value="<?= $count ?>"/>
<button type="submit">Inc</button>
</form>
</hr>
<a href="queryparameter.php?count=<?= $count ?>">Inc</a>Example with action and Id
<?php
if ($_SERVER["REQUEST_METHOD"] === "GET") {
if (isset($_GET["todoId"]) && !filter_input(INPUT_GET, "TodoId",
FILTER_VALIDATE_INT)) {
$todoId = (int)$_GET["todoId"];
//rest of code
}
}
?>
<ul>
<? foreach ($rows as $row) { ?>
<li>
<?= $row["Description"] ?>
<a href="todoExample.php?action=EditTodo&todoId=<?= $row['TodoId'] ?>">
Edit
</a>
</li>
<? } ?>
</ul>Example:
https://www.coolblue.nl/mobiele-telefoons/merk:apple
Not possible with PHP without a framework!
Sessions
Links session-id (cookie) to private memory on server
<?php
$expires_time = 5; //5 seconds
$count = 0;
if(!isset($_COOKIE["count"])) {
$_COOKIE["count"] = 0;
} else {
$count = (int)$_COOKIE["count"];
}
$count++;
if($count % 5 == 0) {
setcookie("count", $count, time() - $expires_time);
} else {
setcookie("count", $count, time() + $expires_time);
}
?>
<?= $count ?>
<hr>
<a href="cookies.php">Inc</a>
<?php
//https://www.tutorialspoint.com/php/php_sessions.htm
session_start();
//read-session var count or initialize to 0
$count = (int)($_SESSION['count'] ?? 0);
$count++;
//write-session var count
$_SESSION['count'] = $count;
if($count % 5 == 0) {
unset($_SESSION['count']);
//to destroy all session vars use:
//session_destroy();
}
?>
<? echo $count ?>
<hr/>
<form action="session.php">
<button type="submit">Request page again</button>
</form><?php
class MyUser
{
public $name;
public $password;
}
session_start();
if(!isset($_SESSION['user'])) {
$user = new MyUser();
$user->name = "Joris";
$user->password = "Geheim";
$_SESSION["user"] = $user;
echo "Session Created, refresh/reload page!";
} else {
$user = (MyUser)$_SESSION["user"];
echo "Username: " .$user->name;
echo "Password: " .$user->password;
}
?><?php
$username = $_POST["username"] ?? "";
$password = $_POST["password"] ?? "";
if($username === "user" && $password === "session") {
session_start();
$_SESSION["user_id"] = uniqid();
header('Location: logout.php');
}
?>
<form method="post">
<input type="text" name="username">
<input type="password" name="password">
<button type="submit">Login</button>
</form>
<?php
session_start();
$logged_in = false;
if(isset($_POST["logout"])) {
if(isset($_SESSION["user_id"])) {
unset($_SESSION["user_id"]);
echo "logged out with session";
}
} else {
$user_id = $_SESSION["user_id"] ?? "";
if(!empty($user_id)) {
echo "Logged in Session with user_id: $user_id";
$logged_in = true;
}
if(!$logged_in) {
echo "Not logged in";
}
}
?>
<? if($logged_in) { ?>
<form method="post">
<button name="logout" type="submit">Logout</button>
</form>
<? } else { ?>
<form action="login.php">
<button type="submit">Login</button>
</form>
<? } ?><?php
//redirect
$url = "/test.php?a=b";
header("Location: " .$url);
die();
?><?php
//checkSamePage.php
function currentUrl( $trim_query_string = false ) {
$pageURL = (isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] == 'on') ? "https://" : "http://";
$pageURL .= $_SERVER["SERVER_NAME"] .':' .$_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
if( ! $trim_query_string ) {
return $pageURL;
} else {
$url = explode( '?', $pageURL );
return $url[0];
}
}
function requestIsFromSamePage()
{
$current_url = currentUrl(true);
$request_page = explode('?',$_SERVER['HTTP_REFERER'] ?? "")[0];
return $current_url === $request_page;
}
if(requestIsFromSamePage()) {
echo "Same page";
} else {
echo "Different page";
}
?>
<form>
<button type="submit"></button>
</form>
Use a combination of techniques
Gut feeling
Connect to a database
MySQL
Admin Tool
PDO
Prevent SQL Injection
Prevent XSS (Cross Side Scripting)
MySQL (MariaDB) is a Relational Database Management System (RDMS)
Admin Tools for Database
Use WebStorm or other IDE (plugin)
phpMyAdmin
Demo:
insert data
select data
Every table needs a primary key
AUTO_INCREMENT
Name of table + ID (for example TodoId)
NOT NULL columns are preferred
Choose correct datatypes for columns
important
Go to the terminal
start --> system tools --> LXTerminal
Type het volgende commando (install PDO):
sudo apt install php7.3-mysql
enter
voer het password in (student)
enter
sudo service apache2 restart
enter
For Flex students
See video on previous page how to do this!
Steps:
Connect to a database
Prepare a statement (prepared statement)
Statement = Query
Execute the statement
Send the Query to the database
Process the result
Close connection!
connection string
creating object (new PDO(...), connection)
handeling errors, with exception (try, catch)
close connection ($conn = null)
<?php
//connectToDatabaseAndClose.php
$host = "localhost";
$databaseName = "TodoDb";
$connectionString = "mysql:host=$host;dbname=$databaseName";
$username = "student"; //root is default in most cases
$password = "student"; //root is default in most cases
$conn = null;
try {
$conn = new PDO($connectionString, $username, $password);
//enables exception mode, exception is throw when an error occurs
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected successful";
} catch (PDOException $ex) {
echo "PDOException: $ex";
} finally {
if($conn != null) {
//$conn->close();
$conn = null;
}
}
?>
Prepare Statement
PDO::FETCH_ASSOC
foreach ($stmt->fetchAll() as $row)
$row["columnName"]
<?php
//queryData.php
$host = "localhost";
$databaseName = "TodoDb";
$connectionString = "mysql:host=$host;dbname=$databaseName";
$username = "student"; //root is default in most cases
$password = "student"; //root is default in most cases
$conn = null;
try {
$conn = new PDO($connectionString, $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT TodoId, Description, Done FROM Todos";
$stmt = $conn->prepare($sql);
$stmt->execute();
$result = $stmt->setFetchMode(PDO::FETCH_ASSOC);
foreach ($stmt->fetchAll() as $row) {
echo $row["Description"]
." "
.($row["Done"] ? "completed" : "") ."<br/>";
}
} catch (PDOException $ex) {
echo "Connection failed: $ex";
} finally {
$conn = null;
}
?>
!!!!Dangerous example (line 17)!!!!
Show the problem!
<?php
//insertData.php
$host = "localhost";
$databaseName = "TodoDb";
$connectionString = "mysql:host=$host;dbname=$databaseName";
$username = "student"; //root is default in most cases
$password = "student"; //root is default in most cases
$description = $_POST["description"] ?? false;
if($description !== false) {
try {
$conn = new PDO($connectionString, $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//don't do this!!! SQL INJECTION!!!!!!!!!
$sql = "INSERT INTO Todos (Description) VALUES ('$description')";
//don't do this!!! SQL INJECTION!!!!!!!!!
$conn->exec($sql);
echo "Inserted Record";
} catch (PDOException $ex) {
echo "PDOException: $ex";
} finally {
if(isset($conn)) {
$conn = null;
}
}
}
?>
<form method="post">
<input name="description" type="text">
<button name="AddTodo" type="submit">Add Todo</button>
</form>
Simple explanation:
Longer explanation:
<?php
//sqlInjectionExample.php
$host = "localhost";
$databaseName = "TodoDb";
$connectionString = "mysql:host=$host;dbname=$databaseName";
$username = "student"; //root is default in most cases
$password = "student"; //root is default in most cases
if(isset($_GET["searchDescription"]) && $_GET["searchDescription"])
{
$searchDescription = $_GET["searchDescription"];
//default username, password for wamp is root, empty/blank
try {
$conn = new PDO($connectionString, $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//Add the following string to the querystring searchDescription: "' OR 1 = 1; --"
//Or something like this: "'; DROP TABLE Todos; --"
$sql = "SELECT TodoId, Description, Done FROM Todos WHERE Description = '$searchDescription'";
$stmt = $conn->prepare($sql);
$stmt->execute();
$result = $stmt->setFetchMode(PDO::FETCH_ASSOC);
foreach ($stmt->fetchAll() as $row) {
echo $row["Description"]
." "
.($row["Done"] ? "completed" : "")
."<br/>";
}
} catch (PDOException $ex) {
echo "PDOException: $ex";
}
} else {
echo "invalid input!";
}
?>
<form method="get">
<input name="searchDescription" type="text">
<button type="submit">Search</button>
</form>
Line 21
Always, Use Prepared Statements in combination with Parameter Placeholders!
Use Query Parameter Placeholders
for example: :description, :done
Use a prepare statements
Creates a sql statement that can be executed on the server
Use bindValue(...)
Fills in the value in the SQL
<?php
//query with named placeholders
$sql = "INSERT INTO Todos (Description, Done) VALUES (:description, :done)";
$stmt = $conn->prepare($sql);
$stmt->bindValue("description", $description, PDO::PARAM_STR);
$stmt->bindValue("done", $done, PDO::PARAM_BOOL);
$stmt->execute();
?><?php
//insertDataWithNamedPlaceholders.php
$host = "localhost";
$databaseName = "TodoDb";
$connectionString = "mysql:host=$host;dbname=$databaseName";
$username = "student"; //root is default in most cases
$password = "student"; //root is default in most cases
if(!empty($_POST["description"]))
{
$description = filter_var($_POST["description"], FILTER_SANITIZE_STRING);
if($description === false) {
echo "Error in description";
die();
}
$done = isset($_POST["done"]) ? true : false;
//default username, password for wamp is root, empty/blank
$conn = null;
try {
$conn = new PDO($connectionString, $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "INSERT INTO Todos (Description, Done) VALUES (:description, :done)";
$stmt = $conn->prepare($sql);
$stmt->bindValue("description", $description, PDO::PARAM_STR);
$stmt->bindValue("done", $done, PDO::PARAM_BOOL);
if($stmt->execute()) {
echo "Inserted Record";
} //else is in the Exception (an error occurred)!
} catch (PDOException $ex) {
echo "PDOException: $ex";
} finally {
if($conn != null) {
$conn = null;
}
}
} else {
echo "invalid input!";
}
?>
<form method="post">
<input name="description" type="text">
<input name="done" type="checkbox">
<button name="AddTodo" type="submit">Add Todo</button>
</form>
<?php
//insertIdAndResult.php
$host = "localhost";
$databaseName = "TodoDb";
$connectionString = "mysql:host=$host;dbname=$databaseName";
$username = "student"; //root is default in most cases
$password = "student"; //root is default in most cases
if(!empty($_POST["description"]))
{
$description = filter_var($_POST["description"], FILTER_SANITIZE_STRING);
$done = isset($_POST["done"]) ? true : false; //this is a trick (only possible with checkbox)
$conn = null;
try {
$conn = new PDO($connectionString, $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "INSERT INTO Todos (Description, Done) VALUES (:description, :done)";
$stmt = $conn->prepare($sql);
$stmt->bindParam("description", $description, PDO::PARAM_STR);
$stmt->bindParam("done", $done, PDO::PARAM_BOOL);
if($stmt->execute()) {
$todoId = $conn->lastInsertId();
echo "Inserted record with TodoId: $todoId";
} else {
//never executed, exception is thrown
echo "Inserted failed";
}
} catch (PDOException $ex) {
echo "PDOException: $ex";
} finally {
if(isset($conn)) {
$conn = null;
}
}
} else {
echo "invalid input!";
}
?>
<form method="post">
<input name="description" type="text">
<input name="done" type="checkbox">
<button name="AddTodo" type="submit">Add Todo</button>
</form>
Line 27
<?php
//insertCrossSideScriptingAttack.php
$host = "localhost";
$databaseName = "TodoDb";
$connectionString = "mysql:host=$host;dbname=$databaseName";
$username = "student"; //root is default in most cases
$password = "student"; //root is default in most cases
if(!empty($_POST["description"]))
{
$description = $_POST["description"];
$done = isset($_POST["done"]) ? true : false; //this is a trick (only possible with checkbox)
$conn = null;
try {
$conn = new PDO($connectionString, $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "INSERT INTO Todos (Description, Done) VALUES (:description, :done)";
$stmt = $conn->prepare($sql);
$stmt->bindParam("description", $description, PDO::PARAM_STR);
$stmt->bindParam("done", $done, PDO::PARAM_BOOL);
if($stmt->execute()) {
$todoId = $conn->lastInsertId();
echo "Inserted record with TodoId: $todoId";
} else {
//never executed, exception is thrown
echo "Inserted failed";
}
} catch (PDOException $ex) {
echo "PDOException: $ex";
} finally {
if(isset($conn)) {
$conn = null;
}
}
} else {
echo "invalid input!";
}
?>
<form method="post">
<input name="description" type="text">
<input name="done" type="checkbox">
<button name="AddTodo" type="submit">Add Todo</button>
</form>
Cross Site Scripting (XSS)
Cross Site Scripting (XSS)
<script>alert("test");</script>
alert("test"); is not dangerous, but other scripts are really dangerous!
Always:
Otherwise:
Probably some script that searches the internet for hackable sites
<?php
//deleteDoneTodos.php
$host = "localhost";
$databaseName = "TodoDb";
$connectionString = "mysql:host=$host;dbname=$databaseName";
$username = "student"; //root is default in most cases
$password = "student"; //root is default in most cases
//pay attention, isset($_POST["DeleteTodos"]) instead of !empty($_POST["DeleteTodos"])
//because the button has no value
if(isset($_POST["DeleteTodos"]))
{
$conn = null;
try {
$conn = new PDO($connectionString, $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "DELETE FROM Todos WHERE Done = true";
$stmt = $conn->prepare($sql);
if($stmt->execute()) {
$deleteCount = $stmt->rowCount();
echo "Deleted $deleteCount todo records";
} else {
//never executed, exception is thrown
echo "No todos delete";
}
} catch (PDOException $ex) {
echo "PDOException: $ex";
} finally {
if(isset($conn)) {
$conn = null;
}
}
}
?>
<form method="post">
<button name="DeleteTodos" type="submit">Delete Done Todos</button>
</form>
Line 26
Two examples:
The techniques combined from the first three lessons
Structuring and reuse of code in web application
includes / requires
functions
classes
Separation of Concerns
Code & UI --> Template Library (Twig)
include(), include_once() emit warning (file not found)
require(), require_once() emit fatal error (file not found)
<?php
//method1/page1.php
$_title = "Page 1";
//include "_header.php"
require "_header.php";
?>
<div class="row">
<div class="col-sm-4">
<h3>Page 1 Column 1</h3>
</div>
</div>
<?php
require "_footer.php";
?><!-- $_title is defined on other page -->
//part of _header.php
<div class="jumbotron text-center">
<h1>Company Logo & Text</h1>
<p><?= $_title ?></p>
</div>
<?php
//method1/page1.php
$_title = "Page 1";
//include "_header.php"
require "_header.php";
?>Use functions instead, can be placed in separate file and included
HTML Helpers, simple function that generate html!
Very useful
return type can be seen as html code!
<?php
//method1/htmlHelpers.html
function displayHeader($title)
{
?>
<html>
<head>
<title><?= $title ?></title>
</head>
<body>
<?
}
function displayFooter($title) {
?>
<h1><?= $title ?></h1>
</body>
</html>
<?
}
?>
<?php
displayHeader("My Title");
displayFooter("End of Page")
?>
Separates code (Logic) form User Interface
Separation of Concerns (SOC)
Increases maintainability, readability
Php has many template libraries:
We use Twig as an example
native support in PhpStorm (and other IDE's)
In the terminal, execute the following commands:
For Windows Users:
https://getcomposer.org/doc/00-intro.md#installation-windows
<?php
<!-- https://twig.symfony.com/doc/2.x/api.html -->
require_once '/path/to/vendor/autoload.php';
$loader = new \Twig\Loader\ArrayLoader([
'index.html' => 'Hello {{ name }}!',
]);
$twig = new \Twig\Environment($loader);
echo $twig->render('index.html', ['name' => 'Fabien']);
?><!DOCTYPE html>
<html>
<head>
<title>My Webpage</title>
</head>
<body>
<ul id="navigation">
{% for item in navigation %}
<li><a href="{{ item.href }}">{{ item.caption }}</a></li>
{% endfor %}
</ul>
<h1>My Webpage</h1>
{{ a_variable }}
<h2>Not set variable: {{ empty_var }}</h2>
</body>
</html><?php
require_once ($_SERVER['DOCUMENT_ROOT'] .'/vendor/autoload.php');
$loader = new \Twig\Loader\FilesystemLoader('Templates');
$twig = new \Twig\Environment($loader);
$template = $twig->load("example.twig");
//echo $template->render(['todos'=> $todos, 'rowToEdit' => $rowToEdit]);
echo $template->render([
'navigation' => [
['href'=>"index.html", "caption"=>"home"],
['href'=>"contact.html", "caption"=>"contact"]
],
"a_variable" => "<script>alert('test');</script>"
]);
Asynchronous JavaScript and XML.
Tip: use jQuery for Ajax!
The complete page is updated!
Idea: Only update what's changed!
Text
More examples:
<!-- /Les5/SimpleExamples/nocommentversion.php -->
<!-- Import JQUERY -->
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<p id="text-load"></p>
<p id="text-post"></p>
<p id="text-json"></p>
<script>
$(document).ready(function() {
$("#text-load").load("textGenerator.php", {
action: "load",
food: "pizza"
});
$.post("textGenerator.php", {
action: "calculateSum",
number1: 5,
number2: 6
}, function(data) {
$("#text-post").text("Sum: " + data);
});
$.post("textGenerator.php", {
action: "sendPersonInfo"
}, function(data, status) {
if (status != "success") {
// You can output an error message here if something went wrong with the request
}
else {
$("#text-json").text("Name: " + data.name + ", Age: " + data.age + ", Country: " + data.country);
}
}, "json")
});
</script>
<?php
if (isset($_POST["action"])) {
$action = $_POST["action"];
// You don't "need" to use a switch statement and separate functions
// This is just one way, but it makes your code look extremely clean and readable:
switch ($action) {
case "load": sendFood();
break;
case "calculateSum": calculateSum();
break;
case "sendPersonInfo": sendPersonInfo();
break;
}
}
function sendFood() {
$food = $_POST["food"];
// You need to echo what gets returned. For example: echo $food;
// Or you can escape php in order to echo HTML,
// and inside the HTML you can even include PHP variables again (useful if you echo a big block of HTML):
?>
<b><i>My favorite food is <?= $food ?></i></b>
<?php
}
function calculateSum() {
$number1 = $_POST["number1"];
$number2 = $_POST["number2"];
$sum = $number1 + $number2;
echo $sum;
}
function sendPersonInfo() {
$jsonData["name"] = "Bob";
$jsonData["age"] = "30";
$jsonData["country"] = "Netherlands";
// This converts your array into json format which can be sent and read
echo json_encode($jsonData);
}<!-- Les5/ajax.html -->
<form class="js-ajax-php-json" method="post" accept-charset="utf-8">
<input type="text" name="favorite_beverage" value="" placeholder="Favorite restaurant" />
<input type="text" name="favorite_restaurant" value="" placeholder="Favorite beverage" />
<select name="gender">
<option value="male">Male</option>
<option value="female">Female</option>
</select>
<input type="submit" name="submit" value="Submit form" />
</form>
<ul class="the-return">
[HTML is replaced when successful.]
</ul>
<script
src="https://code.jquery.com/jquery-3.4.1.js"
integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
crossorigin="anonymous"></script>
<script type="text/javascript">
$("document").ready(function(){
$(".js-ajax-php-json").submit(function(){
var data = {
"action": "test"
};
data = $(this).serialize() + "&" + $.param(data);
$.ajax({
type: "POST",
dataType: "json",
url: "ajax.php",
data: data,
success: function(data) {
console.log(data);
$(".the-return").empty();
$ul = $(".the-return").append("<ul></ul>");
for (var key in data) {
if (data.hasOwnProperty(key)) {
$ul.append(`<li>Key: ${key} -- Value: ${data[key]} </li>`)
}
}
$(".the-return").append($ul);
}
});
return false;
});
});
</script><?php
//Les4/ajax.php
function is_ajax() {
return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
}
if(is_ajax()) {
if (isset($_POST["action"]) && !empty($_POST["action"])) { //Checks if action value exists
$action = $_POST["action"];
switch($action) { //Switch case for value of action
case "test": test_function(); break;
}
}
}
function test_function(){
$return = $_POST;
//Do what you need to do with the info. The following are some examples.
//if ($return["favorite_beverage"] == ""){
// $return["favorite_beverage"] = "Coke";
//}
//$return["favorite_restaurant"] = "McDonald's";
//$return["json"] = json_encode($return);
header('Content-type: application/json');
echo json_encode($return);
}
?>