52
Databases PHP Data Objects (PDO) Python DB

Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Embed Size (px)

Citation preview

Page 1: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Databases

PHP Data Objects (PDO)

Python DB

Page 2: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Databases for web 1• In order to do server-based programs we need the ability to

interrogate or ”talk” with databases– Usually the language SQL (Structured Query Language) is used

• There is many RDBMS (Relational DataBase Management Systems) available – from free to expensive– Client-server

• PostgreSQL, MySQL / MariaDB• Microsoft SQL server, Oracle DB, IBM Db2

– Linked into the application with a db file• SQLite, Microsoft Access (Jet)

• Usually the web administrator connect via the web browser and manage the database via some server-side framework.– Other methods is by console or a special management software

• Many hosting services are database enabled since there is little use of server-side programming otherwise!

Page 3: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Databases for web 2• A NoSQL (originally referring to "non SQL", better names may be

"Not only SQL" or "non relational") database provides a mechanism for storage and retrieval of data that is modeled in means other than the tabular relations used in relational databases

• Used when we have datasets that are so large that traditonal methods of storage and processing is inadequate– Big challenge to store, capture, analyse and transfer large data

volumes from social networks, search engines, etc. otherwise

• Benefits of NoSQL over RDBMS– Data models – no predefined schema (tables, fields,

datatypes, etc.)– Data structure – NoSQL handles unstructured data– Cheaper to manage– Scaling – Scale out / horizontal easier

• Types of NoSQL: Document, Column, key-value DBs etc.– MongoDB, CouchDB, Cassandra, Redis etc.– https://www.youtube.com/watch?v=uD3p_rZPBUQ

Page 4: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Databases for web 3• Firebase Realtime, Amazon Dynamo and Google Cloud Bigtable are

examples of cloud-hosted NoSQL databases– Comparison: https://db-engines.com/en/system/Amazon+DynamoDB

%3BFirebase+Realtime+Database%3BGoogle+Cloud+Bigtable

• Firebase data is stored as JSON (Document) and is synchronized in realtime to every connected client

• The Realtime Database API is designed to only allow operations that can be executed quickly

• When you build cross-platform apps with Firebase (iOS, Android and JavaScript SDKs) all of your clients share one Realtime Database instance and automatically receive updates with the newest data

• Example write with set using Firebasefunction writeUserData(userId, name, email, imageUrl) {

firebase.database().ref('users/' + userId).set({

username: name,

email: email,

profile_picture : imageUrl

});

}

Page 5: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

RDBMS 1• A table is a collection of rows and columns just like a

spreadsheet in for example MS Excel• A field is an individual cell in a table• A database is a collection of tables• Normalization – eleminate redundancy

– In a normalised database ach type of data item is held in a separate table with an unique id – takes less space and increases performance

• Example of a hotel management system

Customers table

Rooms table The relation!

Page 6: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

RDBMS 2• It is important to ensure the data integrity (don't end up with tables

that refer to non-existing information)– This means making sure that you maintain the referential integrity– Solved with foreign constraints or triggers

• Consider these different options - if we want to delete a customer Jon Smith from the table– Delete Jon but it it is not possible since we have constraints– Delete Jon. In addition, also delete every affected row in every other

table with triggers– Replace the contents of customer's record with text such as "deleted"– Add a boolean field to the customers table called, is_live, which specifies

whether this is a live customer record or not

Triggers and constraints can ensure data integrity for other CRUD operations as well

• ACID (Atomicity, Consistency, Isolation, Durability) compliance is a set of properties of database transactions intended to guarantee validity even in the event of errors, power failures, etc.

Page 7: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Creating a hotel management database with phpMyAdmin

• LAMP/WAMP (Linux/Windows) server– Apache, MySQL and PHP (plus some helper programs)– http://en.wikipedia.org/wiki/LAMP_(software_bundle)– http://en.wikipedia.org/wiki/Comparison_of_WAMPs

• Install the latest portable XAMPP version– Download, unpack, read readme_en.txt and follow 4 simple instructions,

finished! (if you are lucky!)

• Configure the database with phpMyAdmin– http://localhost/phpmyadmin/ > On the left hand side are the databases– The existing databases are part of the inner workings of MySQL or

phpMyAdmin except the test database

• Create a new database with the name thewebbo_hms (the test DB work as well for your tables)– Preferable use the collation: utf8_***_c* (latin1_***_c* will work as well

for swedish)– *** = language/general/unicode, cs = case sensitive, ci = case insensitive

Page 8: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

phpMyAdmin

Do not update phpMyAdmin!This is a specially configured version and it will probably break the XAMPP installation

Page 9: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Hotel management DB 1• Create

a tablewith theUI

• UseStorageEngineInnoDBorMyISAM

• If no Collationis givenit will usethe DBdefault

Remember to tick the auto_increment box for the id field

Page 10: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Hotel management DB 2• Insert table data with the UI

Page 11: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Hotel management DB 3• Browse and edit the database data with the UI

Page 12: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Hotel management DB 4• Export everything and Import already created formatted

data

Page 13: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Do it faster by hand with SQL• id? PRIMARY KEY? NOT NULL? AUTO_INCREMENT?

CREATE TABLE thewebbo_hms.customers (

id MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,

firstname TINYTEXT NOT NULL,

surname TINYTEXT NOT NULL,

title TINYTEXT NOT NULL,

address TEXT NOT NULL,

phone TINYTEXT NOT NULL,

email TINYTEXT NOT NULL,

PRIMARY KEY (id)

) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_swedish_ci;

INSERT INTO customers (firstname, surname, title, address, phone, email) VALUES

('Hans', 'Jones', 'Teacher', 'The road 1', '1234567', '[email protected]'),

('Hans Edy', 'Mårtensson', 'Teacher', 'The road 2', '7654321', '[email protected]'),

('Jerker', 'Westin', 'Doctor', 'The road 3', '1234321', '[email protected]');

SELECT * FROM customers;

Page 14: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Hotel management DB 5• Designing the database tables correct from start is very

important– The suitable data types for the fields (columns)– Split for example address in several new columns as address,

city, state, county, zip code, country

• MySQL have many table types, InnoDB tables which is the default table type is more advanced than the simple MyISAM– https://dev.mysql.com/doc/refman/5.7/en/storage-engines.html

• Query the table

SELECT firstname FROM customers;

SELECT firstname FROM customers ORDER BY firstname;

SELECT title, firstname, surname FROM customers;

SELECT * FROM customers WHERE id = 2;

SELECT * FROM customers WHERE firstname = "Jerker";

SELECT firstname, surname FROM customers WHERE surname = 'Westin';

DROP TABLE customers;

Page 15: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Add a database user, step 1 and 3

• Using phpMyAdmin and the result after creation

Page 16: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Add a database user, step 2• Grant

privileges and add a password in the tab that shows up”User Accounts”

Page 17: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

PHP Data Objects (PDO)

• When accessing a database from PHP we can use the PDO or MySQLi extensions (MySQL is deprecated since PHP v5.5)

• The PHP Data Objects (PDO) extension defines a lightweight, consistent interface for accessing databases in PHP

• PDO ships with PHP 5.1 and later (supported by XAMPP)• It will make your database coding in PHP more secure, faster

and portable (easier to change DB)

• PDO is object oriented with all the benefits coming with this• Using prepared statements will help protect you from SQL

injection so you do not need any own sanitize functions

<?php print_r(PDO::getAvailableDrivers()); ?>returns: Array ( [0] => mysql [1] => sqlite ) in XAMPP

Page 18: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

PDO vs. MySQL extension• The code below is fairly simple, but it does come with its

significant share of downsides– Deprecated: The original MySQL extension is deprecated since PHP

v5.5.x and will generate E_DEPRECATED errors when connecting to a database. Instead, use the MySQLi or PDO_MySQL extensions

– Escaping: The process of escaping user input is left to the developer – many of which don't understand or know how to sanitize the data

– Flexibility: The API isn't flexible; the code below is tailor-made for working with a MySQL database. What if you switch?

<?php # Connect mysql_connect('localhost', 'username', 'password') or die('Could not connect: ' . mysql_error());

# Choose a database mysql_select_db('someDatabase') or die('Could not select database');

# Perform database query $query = "SELECT * from someTable"; $result = mysql_query($query) or die('Query failed: ' . mysql_error());

# Filter through rows and echo desired information while ($row = mysql_fetch_object($result)) {

echo $row->name; }?>

Page 19: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

PDO vs. MySQLi• MySQLi is safe and around 2 - 7% faster than PDO

– Flexibility: MySQLi only works with MySQL databases

https://code.tutsplus.com/tutorials/pdo-vs-mysqli-which-should-you-use--net-24059

Page 20: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

PDO & MySQLi SQL injection security• Lets say a hacker is trying to inject some malicious SQL through the

'username' HTTP query parameter (GET)• It is recommended to always use prepared statements with bound queries,

more about prepared statements later<?php $_GET['username'] = "'; DELETE FROM users; /*" // If we fail to escape this trailing query, it will be included in the query "as is" - // deleting all rows from the users table (both PDO and mysqli support multiple queries)

// PDO, "manual" escaping, must be done with a DB handle as: $pdo = new PDO(dsn, user, passwd); $username = $pdo->quote($_GET['username']); $pdo->query("SELECT * FROM users WHERE username = $username"); // $pdo->quote() not only escapes the string, but it also quotes it // mysqli, "manual" escaping $username = mysqli_real_escape_string($_GET['username']); $mysqli->query("SELECT * FROM users WHERE username = '$username'"); // mysqli_real_escape_string() will only escape the string; you will need to apply the quotes manually

// PDO, prepared statement – automatic escaping $pdo->prepare('SELECT * FROM users WHERE username = :username AND age = :age'); $pdo->execute(array(':username' => $_GET['username'], ':age' => $_GET['age'])); // mysqli, prepared statement – automatic escaping $query = $mysqli->prepare('SELECT * FROM users WHERE username = ? AND age = ?'); $query->bind_param('si', $_GET['username'], $_GET['age']); $query->execute();?>

MySQLi

Page 21: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

PDO – connect and close• Different databases may have slightly different connection

methods – a PDO driver is needed (often included)– http://php.net/manual/en/pdo.drivers.php

<?php $host = 'utb-mysql.du.se'; $dbname = 'db25'; $user = 'db25'; $pass = 'fGBYZtwY'; try {

# MS SQL Server with PDO_SQLSRV$DBH = new PDO("sqlsrv:host=$host;dbname=$dbname, $user, $pass");

# MySQL with PDO_MYSQL$DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);

# SQLite with PDO_SQLITE$DBH = new PDO("sqlite:my/db/path/database.db3");

} catch(PDOException $e) {

echo $e->getMessage(); } # close the db connection $DBH = null;?>

Page 22: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

PDO – exceptions• PDO can use exceptions to handle errors, which means

anything you do with PDO should be wrapped in a try/catch block

• You can force PDO into one of 3 error modes by setting the error mode attribute on your newly created database handle

<?php $host = 'utb-mysql.du.se'; $dbname = 'db25'; $user = 'db25'; $pass = 'fGBYZtwY'; # connect to the database try { $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); # set error attribute # UH-OH! Typed DELECT instead of SELECT! $DBH->prepare('DELECT name FROM people'); } catch(PDOException $e) { echo "I'm sorry, web user. I'm afraid I can't do that."; file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND); # log errors to a file }?>

<?php $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT ); # default error mode $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING ); # useful for debugging, program will continue to execute $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); # the mode for most situations, it fires an exception ?>

Page 23: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

PDO – create and update• Using PDO, create and update is normally a two-step process

<?php # The most basic type of insert, STH means "Statement Handle", no binding here $STH = $DBH->prepare("INSERT INTO folks ( first_name ) values ( 'Cathy' )"); $STH->execute();?>

• A prepared statement is a precompiled SQL statement that can be executed multiple times by just sending the data to the server

• It has the added advantage of automatically making the data used in the placeholders safe from SQL injection attacks!

<?php # no placeholders - ripe for SQL Injection! $STH = $DBH->prepare("INSERT INTO folks (name, addr, city) values ($name, $addr, $city)"); # unnamed placeholders $STH = $DBH->prepare("INSERT INTO folks (name, addr, city) values (?, ?, ?)"); # named placeholders $STH = $DBH->prepare("INSERT INTO folks (name, addr, city) values (:name, :addr, :city)");?>

Page 24: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

PDO - prepared statements 1• Unnamed placeholders<?php $STH = $DBH->prepare("INSERT INTO folks (name, addr, city) values (?, ?, ?)"); # assign variables to each place holder, indexed 1-3 $STH->bindParam(1, $name); $STH->bindParam(2, $addr); $STH->bindParam(3, $city);

# insert one row - once the query have been prepared ... $name = "Daniel"; $addr = "1 Wicked Way"; $city = "Arlington Heights"; $STH->execute();

# ... insert another row with different values – multiple times (looping) $name = "Steve" $addr = "5 Circle Drive"; $city = "Schaumburg"; $STH->execute();

# Does this seem a bit unwieldy for statements with a lot of parameters? It is! # However, if your data is stored in an indexed array, there’s an easy shortcut. # We do not need to use ->bindParam() - the execute($values) method does this! # the array data we want to insert must be in the arg. ->execute(argument) $data = array('Cathy', '9 Dark and Twisty Road', 'Cardiff'); $STH = $DBH->prepare("INSERT INTO folks (name, addr, city) values (?, ?, ?)"); $STH->execute($data);?>

Page 25: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

PDO - prepared statements 2• Named placeholders

<?php $STH = $DBH->prepare("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)"); # the first argument is the named placeholder name - notice named placeholders always start with a colon $STH->bindParam(':name', $name); $STH->bindParam(':addr', $addr); $STH->bindParam(':city', $city);

# insert one row - insert as many rows as you want just updating the variables and ->execute() $name = "Daniel"; $addr = "1 Wicked Way"; $city = "Arlington Heights"; $STH->execute();

# You can use a shortcut here as well, but it works with associative arrays. The data we want to insert $data = array(':name' => 'Cathy', ':addr' => '9 Dark and Twisty', ':city' => 'Cardiff'); $STH = $DBH->prepare("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)"); # And the array shortcut ->execute(arg) $STH->execute($data);

# Another nice feature of named placeholders is the ability to insert objects directly into your # database, assuming the properties match the named fields - a simple object class person {

public $name; public $addr; public $city;function __construct($n, $a, $c) {

$this->name = $n; $this->addr = $a; $this->city = $c;}# etc ...

} $cathy = new person('Cathy','9 Dark and Twisty','Cardiff'); # here's the fun part $STH = $DBH->prepare("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)"); # By casting the object to an associative array in execute, the properties are treated as array keys $STH->execute((array)$cathy);?>

Page 26: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

PDO - prepared statements 3• Update and delete with named placeholders<?php $id = 5; // update using named place holders $name = "Joe the Plumber"; try {

$DBH = new PDO('mysql:host=localhost;dbname=someDatabase', $username, $password);$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$STH = $DBH->prepare('UPDATE someTable SET name = :name WHERE id = :id');$result = $STH->execute(array(':id' => $id, ':name' => $name));echo $STH->rowCount(), " - ", $result;

} catch(PDOException $e) {

echo 'Error: ' . $e->getMessage(); } $id = 5; // delete using named place holders and the bindParam method try {

$DBH = new PDO('mysql:host=localhost;dbname=someDatabase', $username, $password);$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$STH = $DBH->prepare('DELETE FROM someTable WHERE id = :id');$STH->bindParam(':id', $id);$result = $STH->execute();echo $STH->rowCount(), " - ", $result;

} catch(PDOException $e) {

echo 'Error: ' . $e->getMessage(); }?>

Page 27: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

PDO – retrieve data 1

• Data is obtained via $STH->fetch(), a method of your statement handle. Before calling fetch, it’s best to tell PDO how you’d like the data to be fetched– There's two core ways to fetch: query() and execute()

• The most common options which cover most situations are– PDO::FETCH_ASSOC: returns an array indexed by column name– PDO::FETCH_CLASS: Assigns the values of your columns to properties

of the named class. It will create the properties if matching properties do not exist

– PDO::FETCH_OBJ: returns an anonymous object with property names that correspond to the column names

<?php # In order to set the fetch method, the following syntax is used $STH->setFetchMode(PDO::FETCH_ASSOC);?>

Page 28: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

PDO – retrieve data 2• FETCH_ASSOC

– This fetch type creates an associative array, keys by column name

<?php # using the shortcut ->query() method here since there are no variable values in the select statement $STH = $DBH->query('SELECT name, addr, city from folks'); # setting the fetch mode PDO::FETCH_ASSOC – which also is the default fetch mode if not set $STH->setFetchMode(PDO::FETCH_ASSOC);

# showing the results while($row = $STH->fetch()) { echo $row['name'] . "\n"; echo $row['addr'] . "\n"; echo $row['city'] . "\n"; } ?>

• FETCH_OBJ– Creates an object of std class for each row of fetched data

<?php # creating the statement manually escaping the users data with the PDO::quoute() method making it safer $STH = $DBH->query('SELECT name, addr, city from folks where name = ' . $DBH->quote($name));

# You can also set the fetch mode directly within the ->fetch() method call as well while($row = $STH->fetch(PDO::FETCH_OBJ)) {

echo $row->name . "\n"; echo $row->addr . "\n"; echo $row->city . "\n"; }?>

Page 29: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

PDO – retrieve data 3• It's strongly advised that you use prepared statements in fetch as well• However if your SQL queries NOT is dependent upon form data, the query

method is OK to use• In this example, we're using the prepare method to prepare the query before

the user's data has been attached• With this technique, SQL injection is virtually impossible, because the data

doesn't ever get inserted into the SQL query, itself. Notice that, instead, we use named parameters (:name) to specify placeholders.

<?php # Best Practice for fetch - The Prepared Statements Method $name = "Daniel"; try {

$DBH = new PDO('mysql:host=localhost;dbname=myDatabase', $username, $password);$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $STH = $DBH->prepare('SELECT * FROM myTable WHERE name = :name');$data = array(':name' => $name);$STH->execute($data);

while($row = $STH->fetch()) { print_r($row); # displays information about a variable in a way that's readable by humans}

} catch(PDOException $e) {

echo 'ERROR: ' . $e->getMessage(); }?>

Page 30: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

PDO – retrieve data 4• One of the neatest aspects of PDO is that it gives the ability to map

the query results to a class instance or object<?php class User {

public $first_name, $last_name;function __construct($fn, $ln = '') { $this->first_name = preg_replace('/[a-z]/', 'x', $fn); $this->last_name = $ln;}public function full_name() { return $this->first_name . ' ' . $this->last_name;}

} try {

$DBH = new PDO('mysql:host=localhost;dbname=someDatabase', $username, $password);$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$STH = $DBH->query('SELECT * FROM someTable');

# Map results to a User object$STH->setFetchMode(PDO::FETCH_CLASS, 'User'); # calls the constructor after the data is assigned in PDO# calls the constructor before the data is assigned in PDO$STH->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'User');

while($user = $STH->fetch()) { # Call our custom full_name method echo $user->full_name();}

} catch(PDOException $e) {

echo 'Error: ' . $e->getMessage(); }?>

# if you need you can pass arguments to the constructor # when fetching data into objects with PDO:$STH->setFetchMode(PDO::FETCH_CLASS, 'User', array('stuff'));# If you need to pass different data to the constructor for each # object you can set the fetch mode inside the fetch method:$i = 0;while($rowObj = $STH->fetch(PDO::FETCH_CLASS, 'User', array($i))) {

// do stuff$i++;

}

Page 31: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

PDO – helpful methods• PDO is a large extension, here are a few more methods to do basic things

<?php # log and write PDO exception data to a file so you can examine errors file_put_contents($filename, $data, $flags); # ensure that you got permission to write the file, chmod xxx # The ->lastInsertId() method is always called on the database handle, not statement handle, # and will return the auto incremented id of the last inserted row by that connection. $DBH->lastInsertId();

# The ->exec() method is used for operations that can not return data other then the # affected rows as database schema changes etc. Here are two examples of using the exec method. $DBH->exec('DROP TABLE folks'); $DBH->exec("SET time_zone = '-8:00'");

# The ->quote() method quotes strings so they are safe to use in queries. # This is your fallback if you’re not using prepared statements. $safe = $DBH->quote($unsafe);

# The ->rowCount() method returns an integer indicating the number of rows affected by an operation $rows_affected = $STH->rowCount();

# If the rowCount method does not work you can get the numbers of rows with # (this is currently the case with SQLite, which need this fix) $sql = "SELECT COUNT(*) FROM folks";

if ($STH = $DBH->query($sql)) {if ($STH->fetchColumn() > 0) { # check the row count

# issue a real select here, because there's data!}else { echo "No rows matched the query."; }

}?>

<?php // PDO supports transactions as well $DBH->beginTransaction(); // modify db ... // either commit or rollback! if($someResultCheck == true)

$DBH->commit(); else

$DBH>rollback();?>

Page 32: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

PDO CRUD resources

• Introduction to PHP PDO– http://www.phpro.org/tutorials/Introduction-to-PHP-PDO.html

• Why you should be using PHP’s PDO for Database Access– The article contains some errors so read the comments!– http://net.tutsplus.com/tutorials/php/why-you-should-be-using-

phps-pdo-for-database-access/

• PHP Database Access: Are You Doing It Correctly?– http://net.tutsplus.com/tutorials/php/php-database-access-are-

you-doing-it-correctly/

• PHP Data Objects documentation– http://www.php.net/manual/en/book.pdo.php

Page 33: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

SQL injection and why PDO!

• SQL injection article– http://users.du.se/~hjo/cs/mi1004/

docs/hi_07_2013_teaser.pdf

• PDO vs. MySQLi– PDO is better on all points!– http://net.tutsplus.com/tutorials/php/

pdo-vs-mysqli-which-should-you-use/

• PDO and MySQLi protects against first order SQL injection if they are correctly used– http://download.oracle.com/oll/

tutorials/SQLInjection/html/lesson1/les01_tm_attacks.htm

Page 34: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

pdo-test.php• Open DB server at school and print out the filmer table

<?php echo "<html><body>"; $dsn = 'mysql:host=utb-mysql.du.se;dbname=db25;charset=UTF8'; $dbuser = 'db25'; $dbpass = 'fGBYZtwY'; $DBH = null; $filmer = "filmer"; try {

# a DB Handler to manage the database connection$DBH = new PDO($dsn, $dbuser, $dbpass);# SQL query$sql = 'SELECT * FROM ' . $filmer;# STH means "Statement Handle"$STH = $DBH->query($sql);# setting the fetch mode (associative array indexed by column name)$STH->setFetchMode(PDO::FETCH_ASSOC);

echo "# of cols: ", $STH->columnCount(), " and # of rows: ", $STH->rowCount(), "<br />";

while($row = $STH->fetch()) { echo "{$row['genre']} {$row['titel']} {$row['betyg']} {$row['langd']} {$row['bild']} <br />"; }# close the connection $DBH = null;

} catch (PDOException $e){

echo '<b>PDOException: </b>', $e->getMessage();die();

} echo "</body></html>";?>

Page 35: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

List customers - thewebbo_hms

• PDO read example<?php echo "<html><body>"; $dbtype = "mysql"; // PDO configuration $dbhost = "localhost"; $dbname = "thewebbo_hms"; $dbuser = "hjo"; $dbpass = "abc123xyz"; $charset = "UTF8"; $dsn = "$dbtype:host=$dbhost;dbname=$dbname;charset=$charset";

$query = "select firstname, surname from customers";

# MySQL with PDO_MYSQL $DBH = $DBH = new PDO($dsn, $dbuser, $dbpass);

# using the shortcut ->query() method here since there are no variable # values in the select statement. $STH = $DBH->query($query);

# setting the fetch mode (array indexed by column name) $STH->setFetchMode(PDO::FETCH_ASSOC); while($row = $STH->fetch()) { echo $row['firstname'] . " " . $row['surname'] . "<br />"; } ################## Do it again ########################## $STH = $DBH->query($query);

# setting fetch mode (object with names by column name) $STH->setFetchMode(PDO::FETCH_OBJ);

# showing the results while($row = $STH->fetch()) { echo $row->firstname . " " . $row->surname . "<br />"; } echo "</body></html>";?>

Page 36: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Counting rows - thewebbo_hms

<?php include "utils.php"; # Start the page properly, found in utils.php printHeader(); try {

if($DBH == null) $DBH = new PDO($dsn, $dbuser, $dbpass);# using the shortcut ->query() method here since there # are no variable values in the select statement $query = 'SELECT * FROM customers';$STH = $DBH->query($query);$total = $STH->rowCount();

if ($total == 0) { echo "Sorry, no matches found!";}else { echo "Total number of customers in the database is " . $total;}# close the connection $DBH = null;

} catch (PDOException $e) {

echo '<b>PDOException: </b>',$e->getMessage();die();

} # End the page properly, found in utils.php printFooter();?>

• Try if it works with some simple script

# If the rowCount method does not work you can get # the numbers of row with$sql = "SELECT COUNT(*) FROM customers";$STH = $DBH->query($sql);if($STH->fetchColumn() > 0) { # check the row count# ... }

Page 37: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Reading data – make it nice - thewebbo_hms

<?php include "utils.php"; printHeader(); # Start the page properly, found in utils.php try {

# a DB Handler to manage the database connectionif($DBH == null) $DBH = new PDO($dsn, $dbuser, $dbpass);

$sql = "select firstname, surname, phone from customers";# STH means "Statement Handle"$STH = $DBH->query($sql);# setting the fetch mode $STH->setFetchMode(PDO::FETCH_OBJ);

#echo "# of cols: " . $STH->columnCount() . " and # of rows: " . $STH->rowCount() . "<br />";echo "<table border='1'><tr>";echo "<td colspan='2'>These are the customers on file</td></tr>";

while ($row = $STH->fetch()) { echo "<tr><td title={$row->phone}>{$row->firstname}</td>"; echo "<td>{$row->surname}</td></tr>";}echo "</table>";# close the connection $DBH = null;

} catch (PDOException $e) {

echo '<b>PDOException: </b>',$e->getMessage();die();

} printFooter(); # End the page properly, found in utils.php?>

Page 38: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Searching a table 1 - thewebbo_hms<?php include "utils.php"; # SEARCH.PHP – search for firstname # Start the page properly, SEARCH.PHP – search for firstname printHeader();

# Check whether the searchtype radio button has been set # If not set, display the search form. if (!isset($_POST["searchtype"])) {

echo "<form method='POST' action='search.php'>";echo "Search for firstname:<br>";# using html5 input type search echo "<input type='search' name='searchtext' size='15'

placeholder='search' results='5'' autosave='saved-searches'>";echo "<br><br>";echo "Full search ";echo"<input type='radio' value='FULL' checked name='searchtype'><br>";echo "Partial search ";echo "<input type='radio' name='searchtype' value='PARTIAL'>";echo "<br><br>";echo "<input type='submit' value='Search' name='submit'>";echo "</form>";

} # if else { # Searchtype was set, so retrieve form data and do the search

$searchtext = $_POST["searchtext"]; # Retrieve from the form$searchtype = $_POST["searchtype"]; # Retrieve from the form$searchtext_san = sanitize_form_text($searchtext); # Prevents SQL injections!

# Now connect to the databasetry { if($DBH == null)

$DBH = new PDO($dsn, $dbuser, $dbpass);

Page 39: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Searching a table 2 - thewebbo_hms# Construct the appropriate querys$sql = "select firstname, surname from customers where firstname";

if ($searchtype == "FULL") { $sql .= " = :searchtext_san"; $STH = $DBH->prepare($sql); $STH->execute(array(':searchtext_san' => $searchtext_san));}

if ($searchtype == "PARTIAL") { $sql .= " LIKE :searchtext_san"; $STH = $DBH->prepare($sql); $STH->execute(array(':searchtext_san' => '%'.$searchtext_san.'%'));}$STH->setFetchMode(PDO::FETCH_ASSOC); # setting the fetch mode

$total = $STH->rowCount();if ($total == 0) { echo "Sorry, no matches found!";}if ($total > 0) { while ($row = $STH->fetch()){

echo "{$row["firstname"]} {$row["surname"]}<br>"; } # while} # if matches found# close the connection $DBH = null;

}catch (PDOException $e) { echo '<b>PDOException: </b>',$e->getMessage(); die();}

} # else PrintFooter(); # End the page properly?>

Page 40: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Python MySQL DB access 1

#!"\dev\Python37\python.exe"

import MySQLdb, sys, cgitb

cgitb.enable() # Install an exception handler that formats tracebacks as HTML

try: # Open database connection

db = MySQLdb.connect(host="localhost", # your host, usually localhost

user="hjo", # your username

passwd="secret", # your password

db="test", # name of the data base

charset="UTF8") # character encoding

except BaseException as e:

print("Connect error: {}".format(e))

sys.exit(0)

with db.cursor() as cursor: # prepare a cursor object using the cursor() method

try:

cursor.execute("SELECT VERSION()") # execute SQL queries using the execute() method

data = cursor.fetchone() # Fetch a single row using the fetchone() method

print("Database version: %s <br>" % data)

except BaseException as e:

print("Fetch data error: {}".format(e)))

• Python supports most databases via separate DB API modules– MySQLdb (mysqlclient) or PyMySQL is the interfaces to use for MySQL

• Both are very similar in usage - Docs: https://pymysql.readthedocs.io and https://mysqlclient.readthedocs.io/

https://www.lfd.uci.edu/~gohlke/pythonlibs/#mysqlclient

pip install C:/some-dir/some-file.whl

Page 41: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Python MySQL DB access 2

# same code as previous slide and additionally...

with db.cursor() as cursor:

sql = "SELECT * FROM filmer"

try:

cursor.execute(sql) # Execute the SQL command

result = cursor.fetchall() # Fetch all the rows in a list of lists

# print(results)

print("Row, Genre, Title, Grade, Length, Picture <br>")

for row in result:

line = row[0]

genre = row[1]

titel = row[2]

betyg = row[3]

langd = row[4]

bild = row[5]

# print fetched result formatted

print("{}, {}, {}, {}, {}, <a href='{}'>{}</a><br>"

.format(line, genre, titel, betyg, langd, bild, bild))

except BaseException as e:

print("Unable to fecth or display data error: {}".format(e))

• Read data with cursor.fetchall() using the filmer table

Page 42: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Python MySQL DB access 3

# same code as previous slide and additionally...

with db.cursor() as cursor:

sql = "INSERT INTO filmer (genre, titel, betyg, langd, bild) VALUES (%s, %s, %s, %s, %s)"

# Movies in a list of lists

movie_list = [

("Action", "Killers", 1, "82 min", "http://images.filmtipset.se/posters/525.jpg"),

("Thriller", "Murder at eight", 2, "100 min", "http://images.filmtipset.se/posters/525.jpg"),

("Animation", "Dumbo", 4, "123 min", "http://images.filmtipset.se/posters/525.jpg")

]

try:

num_rows = cursor.executemany(sql, movie_list)

print("Inserted {} rows!<br>".format(num_rows))

except BaseException as e:

print("Insert data error: {}".format(e))

• Insert data using the filmer table. With a prepared statement (cursor.executemany()) it works as unnamed placeholders in PDO

• Using parameterised queries one avoids the formatting issues (escaping of characters), possibilities for incorrect SQL and SQL injection

Page 43: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Python MySQL DB access 4

with db.cursor() as cursor: # Prepare SQL query to UPDATE required records

sql = "UPDATE filmer SET betyg = betyg + 1 WHERE titel = '{}'".format('Dumbo')

try:

num_rows = cursor.execute(sql) # Execute the SQL command

print("Updated {} records!<br>".format(num_rows))

db.commit() # Commit your changes in the database

except BaseException as e:

print("Update error: {}".format(e))

db.rollback() # Rollback in case there is any error

with db.cursor() as cursor: # Prepare SQL query to DELETE required records

sql = "DELETE FROM filmer WHERE betyg > '{}'".format(5)

try:

num_rows = cursor.execute(sql)

print("Deleted {} records!<br>".format(num_rows))

db.commit()

except BaseException as e:

print("Delete error: {}".format(e))

db.rollback()

finally:

db.close() # disconnect from server when last query is done

• Update and delete data using the filmer table

See the db-test-mysql.py file for full listing

Page 44: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Python SQLite DB access

#!"\dev\Python37\python.exe"

import sqlite3, sys, cgitb

cgitb.enable() # Install an exception handler that formats tracebacks as HTML

def connectDB():

try:

#db = sqlite3.connect(':memory:') # Create a database in RAM

db = sqlite3.connect('users.db3') # Creates or opens a file called users.db3 with a SQLite3 DB

return db

except BaseException as e:

print("Connect error: {}".format(e))

sys.exit(0)

def createTable(cursor):

try:

# execute SQL queries using the execute() method

cursor.execute('''CREATE TABLE users(id INTEGER PRIMARY KEY, name TEXT,

phone TEXT, email TEXT unique, password TEXT)''')

db.commit()

except BaseException as e:

print("Create table error: {}".format(e))

db = connectDB() # Connect

cursor = db.cursor() # Get a cursor object

• Works more or less as with MySQLdb but with is not supported– https://www.pythoncentral.io/introduction-to-sqlite-in-python/

See the db-test-sqlite.py file for full listing

Page 45: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Preventing SQL Injection Attacks before PDO

• In the previous example we did something like: select firstname, surname from customers where surname = 'Smith' – But what if the visitor enters some search text as follows: Smith' or

surname != 'Smith– We end up with: select firstname, surname from customers where

surname = 'Smith' or surname != 'Smith' – In other words, it will return the entire contents of the table!

• Consider what happens if the following is entered as a surname: Smith' or surname != 'Smith; delete from customers– The semicolon is the standard character in MySQL for separating

multiple commands on a single line. So now, after your program searches for the entered surname, it will then delete the entire contents of your customer database!

• Note that we can enter characters in HEX code as well %3B = ; which means that we must block the % too

• Attackers have sophisticated tools that automatically look for such errors on web sites and try to exploit them!

Page 46: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Adding data 1 - thewebbo_hms<?php include "utils.php"; # ADDCUST.PHP - Add a new customer to the customers table # Check whether there's a surname specified. If not, then just display the form. if(!isset($_POST["tb_surname"])) { # if no surname specified

printHeader();echo "<form method='POST' action='addcust.php'>"; echo "<table><tr>";echo "<td>First Name</td>"; echo "<td><input type='text' name='tb_firstname' size='25'></td>"; echo "</tr><tr>"; echo "<td>Surname</td>"; echo "<td><input type='text' name='tb_surname' size='25'></td>"; echo "</tr><tr>"; echo "<td>Title</td>"; echo "<td><input type='text' name='tb_title' size='25'></td>"; echo "</tr><tr>"; echo "<td>Address</td>"; echo "<td><textarea rows='2' name='ta_address' cols='20'></textarea></td>"; echo "</tr><tr>"; echo "<td>Phone</td>"; echo "<td><input type='text' name='tb_phone' size='25'></td>"; echo "</tr><tr>"; echo "<td>Email</td>"; echo "<td><input type='text' name='tb_email' size='25'></td>"; echo "</tr></table>"; echo "<br>"; echo "<input type='submit' value='Create Customer' name='button'>"; echo "</form>"; printFooter();

} # if no surname specified else { # a surname was specified so create a new record and retrieve the data from the form

Page 47: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Adding data 2 - thewebbo_hms$title = $_POST["tb_title"];$firstname = $_POST["tb_firstname"];$surname = $_POST["tb_surname"];$address = $_POST["ta_address"];$phone = $_POST["tb_phone"];$email = $_POST["tb_email"];# Now connect to the databasetry { # a DB Handler to manage the database connection if($DBH == null)

$DBH = new PDO($dsn, $dbuser, $dbpass); # Now construct the query to create the new record with named placeholders $sql = "insert into customers "; $sql .= "(firstname, surname, title, address, phone, email) "; $sql .= "values(:firstname,:surname,:title,:address,:phone,:email)"; #echo $sql; # STH means "Statement Handle" $STH = $DBH->prepare($sql); $result = $STH->execute(array(':firstname'=>$firstname,':surname'=>$surname,

':title'=>$title,':address'=>$address,':phone'=>$phone,':email'=>$email)); $m = "Done! Inserted $result new row. To return to the "; $m .= "home screen click <a href='addcust.php'>here.</a>"; show_message($m); # close the connection $DBH = null;}catch (PDOException $e){ echo '<b>PDOException: </b>',$e->getMessage(); die();}printFooter();

} # else ?>

Page 48: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Editing a data record• Remembering that the Web is a stateless system, where each page

has no idea what came before it, a parameter is used on the URL to maintain state

• Then, we use $_GET["action"] to retrieve the value of the "action" parameter from the URL which tells us what to do next

• The name of the radio button is id2edit. The value of each radio button is the database id number of the customer– This is standard practice, and a very common way of using radio buttons

(or dropdown boxes) to select a database record– The "action" for the form is set to: editcust.php?action=show_record

• When we detect that $_GET["action"] is "show_record", we know that we need to display the customer record form and that we also need to pre-load it with the data for the specified customer as:– <input fieldtype="text" name="firstname" value="Robert" size="25">

• Next the action for this editing form is set to: editcust.php?action=store_record– This time we retrieve the edited values from the form and update the

database accordingly. Note the usage of the hidden field id2edit

Page 49: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Edit a data record 1 - thewebbo_hms<?php # EDITCUST.PHP - Allow the user to edit a customer record include "utils.php"; # Connect to our database. We'll need this regardless. $db_host = "localhost"; $db_database = "thewebbo_hms"; try { if($DBH == null) # a DB Handler to manage the database connection

$DBH = new PDO($dsn, $dbuser, $dbpass); } catch (PDOException $e) { echo '<b>PDOException: </b>',$e->getMessage(); die(); } # Now check the action parameter from the URL to see what we need to do $action = empty($_GET['action']) ? "" : $_GET['action']; if ($action == "") { # No action specified so show the home page try {

$sql = "select id, firstname, surname from customers"; # STH means "Statement Handle" $STH = $DBH->query($sql); # setting the fetch mode $STH->setFetchMode(PDO::FETCH_ASSOC); printHeader(); echo "<form method='post' action='editcust.php?action=show_record'>"; echo "<table border=1>"; echo "<tr><th>Name</th><th>Select</th></tr>"; # Create the table top row while ($row = $STH->fetch()) { echo "<tr><td>{$row["firstname"]} {$row["surname"]}</td>"; echo "<td><input type='radio' value='{$row["id"]}' name='id2edit'>"; echo "</td></tr>"; } echo "</table><br>"; echo "<input type='submit' value='Edit selected customer' name='button'>"; echo "</form>"; $DBH = null; # close the connection

} catch (PDOException $e) {

echo '<b>PDOException: </b>',$e->getMessage(); die();

} printFooter(); } # action = ""

Page 50: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Edit a data record 2 - thewebbo_hms else if ($action == "show_record") { # Display the customer record form. Populate it with the details of # the customer whose id is passed in the id2edit radio button. Get the contents of the id2edit form variable $id2edit = empty($_POST["id2edit"]) ? "" : $_POST["id2edit"]; if ($id2edit == "") {

$m = "No customer selected! To return to the home "; $m .= "screen click <a href='editcust.php'>here.</a>"; show_message($m);

} else {

try { # Now get the customer's details as we'll need them to populate the form $sql = "select * from customers where id = :id2edit"; $STH = $DBH->prepare($sql); # STH means "Statement Handle" $STH->execute(array(':id2edit' => $id2edit)); # setting the fetch mode, don't need a while loop as there's only 1 row $row = $STH->fetch(PDO::FETCH_ASSOC); printHeader(); echo "<form method='POST' action='editcust.php?action=store_record'>"; echo "<table><tr><td>First Name</td>"; echo "<td><input value='{$row["firstname"]}' type='text' "; echo "name='tb_firstname' size='25'></td></tr>"; echo "<tr><td>Surname</td>"; echo "<td><input value='{$row["surname"]}' type='text' "; echo "name='tb_surname' size='25'></td></tr>"; echo "<tr><td>Title</td>"; echo "<td><input value='{$row["title"]}' type='text' "; echo "name='tb_title' size='25'></td></tr>"; echo "<tr><td>Address</td>"; echo "<td><textarea rows='2' name='ta_address' cols='20'>{$row["address"]}</textarea></td></tr>"; echo "<tr><td>Phone</td>"; echo "<td><input value='{$row["phone"]}' type='text' "; echo "name='tb_phone' size='25'></td></tr>"; echo "<tr><td>Email</td>"; echo "<td><input value='{$row["email"]}' type='text' "; echo "name='tb_email' size='25'></td></tr></table><br>"; echo "<input type='submit' value='Save' name='button'>"; echo "<input type='hidden' name='id2edit' value='{$id2edit}'>"; # Pass the id along to the next routine in a hidden field echo "</form>"; $DBH = null; # close the connection }catch (PDOException $e) { echo '<b>PDOException: </b>',$e->getMessage(); die();}printFooter();

} } # action = show_record

Page 51: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Edit a data record 3 - thewebbo_hms else if ($action == "store_record") {

# Retrieve the data from the form and update customer record $id2edit = $_POST["id2edit"]; # Get the id from the hidden field $firstname = $_POST["tb_firstname"];$surname = $_POST["tb_surname"];$title = $_POST["tb_title"];$address = $_POST["ta_address"];$phone = $_POST["tb_phone"];$email = $_POST["tb_email"];

# Now we can update the customer's data.try { $sql = "update customers set firstname=?, surname=?, title=?, address=?,

phone=?, email=? where id = $id2edit"; #echo $sql; # STH means "Statement Handle" $STH = $DBH->prepare($sql); $result = $STH->execute(array($firstname, $surname, $title, $address, $phone, $email));

$m = "Thank you! Edit of $result row complete. To return to the home "; $m .= "screen click <a href='editcust.php'>here.</a>"; show_message($m); # close the connection $DBH = null;}catch (PDOException $e) { echo '<b>PDOException: </b>', $e->getMessage(); die();}

} # action = store_record

function show_message($s) {

printHeader();echo $s;printFooter();

}?>

Page 52: Databases PHP Data Objects (PDO) Python DB - users.du.seusers.du.se/~hjo/cs/mi1004/lectures/SP-IA_10_php-python-db-mysql.pdf · Triggers and constraints can ensure data integrity

Delete a data record - thewebbo_hms

else if ($action == "delete_record") { # Delete the record$id2edit = empty($_POST["id2edit"]) ? "" : $_POST["id2edit"];if ($id2edit == "") { $m = "No customer selected! To return to the home "; $m .= "screen click <a href='delcust.php'>here.</a>"; show_message($m);}else { try {

# Now get the customer's id to delete $STH = $DBH->prepare('delete from customers where id = :id');$STH->bindParam(':id', $id2edit);$STH->execute();$m = "Customer with ID $id2edit deleted. To return to the home "; $m .= "screen click <a href='delcust.php'>here.</a>"; show_message($m);# close the connection $DBH = null;

} catch (PDOException $e) {

echo '<b>PDOException: </b>',$e->getMessage();die();

} } } # action = delete_record

• Similar to previous example, be careful, don't delete the whole database!• A reminder! To retrieve information that was passed as

– part of the URL → use $_GET['name'];

– a form field (textbox, textarea, hidden field etc.) → use $_POST['name'];

• Remember that information that you don't explicitly pass either on the URL or in a form field will NOT be present