Web Applications in PHP Martin Kruliš by Martin Kruliš (v1.0) 20.12.2018
HTTP Wrapper - Revision HTTP Request Wrapper Data are automatically prepared in superglobal arrays $_GET – parameters from request URL $_POST – parameters posted in HTTP body (form data) $_FILES – records about uploaded files $_SERVER – server settings and request headers $_ENV – environment variables HTTP Response Script output is the response (echo …) Headers can be modified by specific functions header('header-line'); by Martin Kruliš (v1.0) 20.12.2018
HTTP Wrapper - Revision Example <form action="?op=update&id=42" method="POST"> <input name="name" type="text"> <input name="surname" type="text"> <input name="age" type="number"> <input type="submit" value="Save"> </form> 'op' => 'update' 'id' => '42' 'name' => 'Martin' 'surname' => 'Kruliš' 'age' => '19' $_GET $_POST Note the & entity used in URL, since it is being included in HTML attribute. All values are strings All values are strings Example 1 by Martin Kruliš (v1.0) 20.12.2018
HTTP Wrapper Request Information Decoded to the $_SERVER array REQUEST_METHOD – used method (“GET” or “POST”) SERVER_PROTOCOL – protocol version (“HTTP/1.1”) REQUEST_URI – request part of URL (“/index.php”) REMOTE_ADDR – clients IP address HTTP_ACCEPT – MIME types that the client accepts HTTP_ACCEPT_LANGUAGE – desired translation HTTP_ACCEPT_ENCODING – desired encodings HTTP_ACCEPT_CHARSET – desired charsets + more info about the server and the client’s browser phpinfo() by Martin Kruliš (v1.0) 20.12.2018
Data Verification/Sanitization What to Verify or Sanitize Everything that possibly comes from users: $_GET, $_POST, $_COOKIE, … Data that comes from external sources (database, text files, …) When to Verify or Sanitize On input – verify correctness Before you start using data in $_GET, $_POST, … On output – sanitize to prevent injections When data are inserted into HTML, SQL queries, … by Martin Kruliš (v1.0) 20.12.2018
Input Verification How to Verify Invalid Inputs Regular expressions Filter functions filter_input(), filter_var(), … $foo = filter_input(INPUT_GET, 'foo', FILTER_VALIDATE_INT, $options); Invalid Inputs Ostrich algorithm Attempt to fix (e.g., select a valid part) User error Safely retrieves $_GET['foo'] Additional options based on input type (default, range…) Actually, many DBMS APIs provide a way to prepare SQL statements with properties/variables and then bind values to these properties. Automatic sanitization is then provided. by Martin Kruliš (v1.0) 20.12.2018
Output Sanitization Sanitization How to Sanitize Making sure the output matches target context Automated solutions are preferred How to Sanitize String and filter functions, regular expressions htmlspecialchars() – encoding for HTML urlencode() – encoding for URL DBMS-specific functions (mysqli_escape_string()) Better yet, use prepared statements Actually, many DBMS APIs provide a way to prepare SQL statements with properties/variables and then bind values to these properties. Automatic sanitization is then provided. by Martin Kruliš (v1.0) 20.12.2018
Formatted Data URL Handling Base64 JSON http_build_query() – construct URL query string parse_url() Base64 Encode (any) data into text-safe form (6-bits/char) base64_encode(), base64_decode() JSON json_encode(), json_decode(), json_last_error() Lists are arrays, collections are stdClass objects by Martin Kruliš (v1.0) 20.12.2018
Select Your Charset One Charset to Rule Them All Charset in Meta-data HTML, PHP, database (connection), text files, … Determined by the language(s) used Unicode covers almost every language Early incoming, late outgoing conversions Charset in Meta-data Must be in HTTP headers header('Content-Type: text/html; charset=utf-8'); Do not use HTML meta element with http-equiv Except special cases (like saving HTML file locally) by Martin Kruliš (v1.0) 20.12.2018
HTTP Wrapper File Uploads In form as <input type="file" name=... /> Provide safe way to browse disk files HTTP wrapper handles the file Stores it in temporary location Provide related info in $_FILES[name] 'tmp_name' – path to the file in temp directory 'error' – error code (e.g., UPLOAD_ERR_OK) 'name', 'type', 'size', … File exists only as long as the script runs is_uploaded_file() – verification move_uploaded_file() – a safe way to move files Let us emphasize that the form must use “multipart/form-data” encoding to successfully handle file uploads. Example 2 by Martin Kruliš (v1.0) 20.12.2018
Raw Request Body Access to Request Body Data In case special data are sent (like JSON) For other HTTP methods (PUT, DELETE) Read-only stream php://input $body = file_get_contents(‘php://input’); There are other streams worth mentioning php://output php://stdin, php://stdout, php://stderr php://memory, php://temp Btw. If you place URL into file-reading functions, the HTTP wrapper attempts to load the contents via GET request. by Martin Kruliš (v1.0) 20.12.2018
POST Request Processing Problem with POST POST Request (a submitted form) Again!!! script add/change something +read data (create HTML) Web Server Refresh Client (Browser) Response (a HTML page) by Martin Kruliš (v1.0) 20.12.2018
POST Request Processing Redirect Mechanism in HTTP 3xx response code 301 Moved Permanently 302 Found (originally named Moved Temporarily) 303 See Other Additional header 'Location' has the new URL Browser must try to load the new URL Loops in redirections are detected Creating Redirect in PHP header("Location: my-new-url"); Automatically changes the response code (to 302) by Martin Kruliš (v1.0) 20.12.2018
POST Request Processing Redirect (303 See Other) after POST POST Request (action.php) action.php add/change something Redirect (to index.php) Web Server Redirects to a new URL (without updating history) Client (Browser) index.php generate HTML (only reads DB) Note that setting Location header in PHP always sets the 302 (Found) response code. This is no big deal; however, it is not entirely correct HTTP semantics. GET (index.php) Refresh HTML Page Example 3a by Martin Kruliš (v1.0) 20.12.2018
POST Request Processing Redirect and Front Controller POST Request (index.php) add/change something Redirect (to index.php) Web Server Redirects to a new URL (without updating history) Client (Browser) generate HTML (only reads DB) Note that setting Location header in PHP always sets the 302 (Found) response code. This is no big deal; however, it is not entirely correct HTTP semantics. GET (index.php) Refresh HTML Page Example 3b by Martin Kruliš (v1.0) 20.12.2018
Redirect and AJAX Redirecting Asynchronous HTTP Requests Works transparently – i.e., in the same way as all HTTP requests handled by the browser Typically unnecessary after POST requests A script should not be re-executed after reload, thus it can receive the updated HTML immediately Uncertain semantics Is the redirect meant for the AJAX result or should the whole page load a new URL? Efficiency AJAX typically optimizes network utilization – additional redirect may be suboptimal by Martin Kruliš (v1.0) 20.12.2018
Redirect and AJAX Example – Involving AJAX Let us have a data table, where each item has a delete button that triggers AJAX POST request Trivial solution After successful request, JS triggers reload of the page URL may be in the response body (for location.href) Slightly more optimized solution After successful request, JS triggers reload of affected components (table) via separate AJAX GET request Optimized solution The POST response sends a HTML fragment or (better yet) a difference update for the data table by Martin Kruliš (v1.0) 20.12.2018
Session Management Cookies A way to deal with stateless nature of the HTTP Key-value pairs (of strings) stored in the web browser Set by special HTTP response header Automatically re-sent in headers with every request Each page (domain) has it own set of cookies Cookies in PHP Cookies are set/modified/removed by setcookie() The function modifies HTTP response headers Cookies sent by browser are loaded to $_COOKIE[] Cookies are usually used along with a mechanism that allows keeping session specific data at the server side. PHP supports sessions directly (see documentation). Example 4 by Martin Kruliš (v1.0) 20.12.2018
Databases MySQL Original mysql API is deprecated (as of PHP 5.5) MySQL Improved (mysqli) API Dual object/procedural interface Procedural interface is similar to original (deprecated) API Advanced connectivity features Persistent connections, compression, encryption Directly supports transactions MySQL Native Driver (mysqlnd) extension More direct access to MySQL server Additional features (e.g., asynchronous queries) by Martin Kruliš (v1.0) 20.12.2018
Databases MySQLi Procedural API Establishing connection with MySQL server $mysqli = mysqli_connect("server", "login", "password", "db_name"); Performing queries $res = $mysqli->query("SQL …"); Terminating connection $mysqli->close(); Safe way to include strings in SQL query mysqli_real_escape_string($mysqli, $str); by Martin Kruliš (v1.0) 20.12.2018
Databases MySQL Results mysqli::query() result depends on the query type On failure always returns false Modification queries return true on success Data queries (SELECT, …) return mysqli_result obj mysqli_result::fetch_assoc() mysqli_result::fetch_obj() mysqli_result::fetch_all($format) mysqli_result::fetch_fields() mysqli_result::num_rows() mysqli_result::free_result() by Martin Kruliš (v1.0) 20.12.2018
Placeholders ? can be used for bound variables Databases Placeholders ? can be used for bound variables MySQLi Prepared Statements Prepare new MySQL statement $stmt = mysqli::stmt_init(); mysqli_stmt::prepare("SELECT ..."); Binding parameters (by positional placeholders) mysqli_stmt::bind_param($types, $var1, …) Types string – one char ~ one parameter Execute and get result object mysqli_stmt::execute(); $res = mysqli_stmt::get_result(); Example 5 by Martin Kruliš (v1.0) 20.12.2018
Frameworks PHP Frameworks Symfony – one of the most popular Laravel – one of the most popular Slim - microframework Zend – one of the oldest Nette – Czech developer and comunity CodeIgniter Yii 2 Phalcon CakePHP … by Martin Kruliš (v1.0) 20.12.2018
Discussion by Martin Kruliš (v1.0) 20.12.2018