Fix menu inconsistencies - Chapter 7

This commit is contained in:
jrfnl
2014-12-08 23:52:46 +01:00
parent e84f63a51e
commit f3db6b7ad4
5 changed files with 102 additions and 87 deletions

View File

@@ -13,94 +13,7 @@ Native drivers are great if you are only using _one_ database in your applicatio
MySQL and a little bit of MSSQL, or you need to connect to an Oracle database, then you will not be able to use the MySQL and a little bit of MSSQL, or you need to connect to an Oracle database, then you will not be able to use the
same drivers. You'll need to learn a brand new API for each database — and that can get silly. same drivers. You'll need to learn a brand new API for each database — and that can get silly.
## MySQL Extension
The [mysql] extension for PHP is no longer in active development, and is [officially deprecated as of PHP 5.5.0]
[mysql_deprecated], meaning that it will be removed within the next few releases. If you are using any functions that
start with `mysql_*` such as `mysql_connect()` and `mysql_query()` in your applications then these will simply not be
available in later versions of PHP. This means you will be faced with a rewrite at some point down the line, so the
best option is to replace mysql usage with [mysqli] or [PDO] in your applications within your own development schedules
so you won't be rushed later on.
**If you are starting from scratch then absolutely do not use the [mysql] extension: use the [MySQLi extension][mysqli],
or use [PDO].**
* [PHP: Choosing an API for MySQL][mysql_api]
* [PDO Tutorial for MySQL Developers][pdo4mysql_devs]
## PDO Extension
[PDO] is a database connection abstraction library — built into PHP since 5.1.0 — that provides a common
interface to talk with many different databases. For example, you can use basically identical code to interface with
MySQL or SQLite:
{% highlight php %}
<?php
// PDO + MySQL
$pdo = new PDO('mysql:host=example.com;dbname=database', 'user', 'password');
$statement = $pdo->query("SELECT some\_field FROM some\_table");
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo htmlentities($row['some_field']);
// PDO + SQLite
$pdo = new PDO('sqlite:/path/db/foo.sqlite');
$statement = $pdo->query("SELECT some\_field FROM some\_table");
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo htmlentities($row['some_field']);
{% endhighlight %}
PDO will not translate your SQL queries or emulate missing features; it is purely for connecting to multiple types of
database with the same API.
More importantly, `PDO` allows you to safely inject foreign input (e.g. IDs) into your SQL queries without worrying
about database SQL injection attacks.
This is possible using PDO statements and bound parameters.
Let's assume a PHP script receives a numeric ID as a query parameter. This ID should be used to fetch a user record
from a database. This is the `wrong` way to do this:
{% highlight php %}
<?php
$pdo = new PDO('sqlite:/path/db/users.db');
$pdo->query("SELECT name FROM users WHERE id = " . $_GET['id']); // <-- NO!
{% endhighlight %}
This is terrible code. You are inserting a raw query parameter into a SQL query. This will get you hacked in a
heartbeat, using a practice called [SQL Injection]. Just imagine if a hacker passes in an inventive `id` parameter by
calling a URL like `http://domain.com/?id=1%3BDELETE+FROM+users`. This will set the `$_GET['id']` variable to `1;DELETE
FROM users` which will delete all of your users! Instead, you should sanitize the ID input using PDO bound parameters.
{% highlight php %}
<?php
$pdo = new PDO('sqlite:/path/db/users.db');
$stmt = $pdo->prepare('SELECT name FROM users WHERE id = :id');
$stmt->bindParam(':id', $_GET['id'], PDO::PARAM_INT); // <-- Automatically sanitized by PDO
$stmt->execute();
{% endhighlight %}
This is correct code. It uses a bound parameter on a PDO statement. This escapes the foreign input ID before it is
introduced to the database preventing potential SQL injection attacks.
* [Learn about PDO]
You should also be aware that database connections use up resources and it was not unheard-of to have resources
exhausted if connections were not implicitly closed, however this was more common in other languages. Using PDO you can
implicitly close the connection by destroying the object by ensuring all remaining references to it are deleted, i.e.
set to NULL. If you don't do this explicitly, PHP will automatically close the connection when your script ends -
unless of course you are using persistent connections.
* [Learn about PDO connections]
[mysql_deprecated]: http://php.net/migration55.deprecated
[mysql_api]: http://php.net/mysqlinfo.api.choosing
[pdo4mysql_devs]: http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers
[SQL Injection]: http://wiki.hashphp.org/Validation
[Learn about PDO]: http://php.net/book.pdo
[Learn about PDO connections]: http://php.net/pdo.connections
[pdo]: http://php.net/pdo
[mysql]: http://php.net/mysql
[mysqli]: http://php.net/mysqli [mysqli]: http://php.net/mysqli
[pgsql]: http://php.net/pgsql [pgsql]: http://php.net/pgsql
[mssql]: http://php.net/mssql [mssql]: http://php.net/mssql

View File

@@ -0,0 +1,28 @@
---
isChild: true
title: MySQL Extension
anchor: mysql_extension
---
## MySQL Extension {#mysql_extension_title}
The [mysql] extension for PHP is no longer in active development, and is [officially deprecated as of PHP 5.5.0]
[mysql_deprecated], meaning that it will be removed within the next few releases. If you are using any functions that
start with `mysql_*` such as `mysql_connect()` and `mysql_query()` in your applications then these will simply not be
available in later versions of PHP. This means you will be faced with a rewrite at some point down the line, so the
best option is to replace mysql usage with [mysqli] or [PDO] in your applications within your own development schedules
so you won't be rushed later on.
**If you are starting from scratch then absolutely do not use the [mysql] extension: use the [MySQLi extension][mysqli],
or use [PDO].**
* [PHP: Choosing an API for MySQL][mysql_api]
* [PDO Tutorial for MySQL Developers][pdo4mysql_devs]
[mysql]: http://php.net/mysql
[mysql_deprecated]: http://php.net/migration55.deprecated
[mysqli]: http://php.net/mysqli
[pdo]: http://php.net/pdo
[mysql_api]: http://php.net/mysqlinfo.api.choosing
[pdo4mysql_devs]: http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers

View File

@@ -0,0 +1,74 @@
---
isChild: true
title: PDO Extension
anchor: pdo_extension
---
## PDO Extension {#pdo_extension_title}
[PDO] is a database connection abstraction library &mdash; built into PHP since 5.1.0 &mdash; that provides a common
interface to talk with many different databases. For example, you can use basically identical code to interface with
MySQL or SQLite:
{% highlight php %}
<?php
// PDO + MySQL
$pdo = new PDO('mysql:host=example.com;dbname=database', 'user', 'password');
$statement = $pdo->query("SELECT some\_field FROM some\_table");
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo htmlentities($row['some_field']);
// PDO + SQLite
$pdo = new PDO('sqlite:/path/db/foo.sqlite');
$statement = $pdo->query("SELECT some\_field FROM some\_table");
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo htmlentities($row['some_field']);
{% endhighlight %}
PDO will not translate your SQL queries or emulate missing features; it is purely for connecting to multiple types of
database with the same API.
More importantly, `PDO` allows you to safely inject foreign input (e.g. IDs) into your SQL queries without worrying
about database SQL injection attacks.
This is possible using PDO statements and bound parameters.
Let's assume a PHP script receives a numeric ID as a query parameter. This ID should be used to fetch a user record
from a database. This is the `wrong` way to do this:
{% highlight php %}
<?php
$pdo = new PDO('sqlite:/path/db/users.db');
$pdo->query("SELECT name FROM users WHERE id = " . $_GET['id']); // <-- NO!
{% endhighlight %}
This is terrible code. You are inserting a raw query parameter into a SQL query. This will get you hacked in a
heartbeat, using a practice called [SQL Injection]. Just imagine if a hacker passes in an inventive `id` parameter by
calling a URL like `http://domain.com/?id=1%3BDELETE+FROM+users`. This will set the `$_GET['id']` variable to `1;DELETE
FROM users` which will delete all of your users! Instead, you should sanitize the ID input using PDO bound parameters.
{% highlight php %}
<?php
$pdo = new PDO('sqlite:/path/db/users.db');
$stmt = $pdo->prepare('SELECT name FROM users WHERE id = :id');
$stmt->bindParam(':id', $_GET['id'], PDO::PARAM_INT); // <-- Automatically sanitized by PDO
$stmt->execute();
{% endhighlight %}
This is correct code. It uses a bound parameter on a PDO statement. This escapes the foreign input ID before it is
introduced to the database preventing potential SQL injection attacks.
* [Learn about PDO]
You should also be aware that database connections use up resources and it was not unheard-of to have resources
exhausted if connections were not implicitly closed, however this was more common in other languages. Using PDO you can
implicitly close the connection by destroying the object by ensuring all remaining references to it are deleted, i.e.
set to NULL. If you don't do this explicitly, PHP will automatically close the connection when your script ends -
unless of course you are using persistent connections.
* [Learn about PDO connections]
[pdo]: http://php.net/pdo
[SQL Injection]: http://wiki.hashphp.org/Validation
[Learn about PDO]: http://php.net/book.pdo
[Learn about PDO connections]: http://php.net/pdo.connections