Rectangle 27 1088

A simple and short PDO tutorial

PHP offers three different APIs to connect to MySQL. These are the mysql(removed as of PHP 7), mysqli, and PDO extensions.

The mysql_* functions used to be very popular, but their use is not encouraged anymore. The documentation team is discussing the database security situation, and educating users to move away from the commonly used ext/mysql extension is part of this (check php.internals: deprecating ext/mysql).

And the later PHP developer team has taken the decision to generate E_DEPRECATED errors when users connect to MySQL, whether through mysql_connect(), mysql_pconnect() or the implicit connection functionality built into ext/mysql.

ext/mysql was officially deprecated as of PHP 5.5 and has been removed as of PHP 7.

When you go on any mysql_* function manual page, you see a red box, explaining it should not be used anymore.

Moving away from ext/mysql is not only about security, but also about having access to all the features of the MySQL database.

ext/mysql was built for MySQL 3.23 and only got very few additions since then while mostly keeping compatibility with this old version which makes the code a bit harder to maintain. Missing features that is not supported by ext/mysql include: (from PHP manual).

mysql_*
  • Removed as of PHP 7
  • Doesn't support prepared statements or parameterized queries
  • Doesn't support all of the functionality in MySQL 5.1

Lack of support for prepared statements is particularly important as they provide a clearer, less error prone method of escaping and quoting external data than manually escaping it with a separate function call.

MySQLi
PDO
E_DEPRECATED
error_reporting
E_DEPRECATED:
error_reporting = E_ALL ^ E_DEPRECATED

Note that this will also hide other deprecation warnings, which, however, may be for things other than MySQL. (from PHP manual)

The article PDO vs. MySQLi: Which Should You Use? by Dejan Marjanovic will help you to choose.

And a better way is PDO, and I am now writing a simple PDO tutorial.

A. PDO PHP Data Objects is a database access layer providing a uniform method of access to multiple databases.

With mysql_* function or we can say it the old way (deprecated in PHP 5.5 and above)

$link = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('testdb', $link);
mysql_set_charset('UTF-8', $link);

With PDO: All you need to do is create a new PDO object. The constructor accepts parameters for specifying the database source PDO's constructor mostly takes four parameters which are DSN (data source name) and optionally username, password.

Here I think you are familiar with all except DSN; this is new in PDO. A DSN is basically a string of options that tell PDO which driver to use, and connection details. For further reference, check PDO MySQL DSN.

$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');

Note: you can also use charset=UTF-8, but sometimes it causes an error, so it's better to use utf8.

If there is any connection error, it will throw a PDOException object that can be cached to handle Exception further.

You can also pass in several driver options as an array to the fourth parameter. I recommend passing the parameter which puts PDO into exception mode. Because some PDO drivers don't support native prepared statements, so PDO performs emulation of the prepare. It also lets you manually enable this emulation. To use the native server-side prepared statements, you should explicitly set it false.

The other is to turn off prepare emulation which is enabled in the MySQL driver by default, but prepare emulation should be turned off to use PDO safely.

I will later explain why prepare emulation should be turned off. To find reason please check this post.

It is only usable if you are using an old version of MySQL which I do not recommended.

Below is an example of how you can do it:

Yes, we can also set some attributes after PDO construction with the setAttribute method:

$db = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF-8', 
              'username', 
              'password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Error handling is much easier in PDO than mysql_*.

A common practice when using mysql_* is:

//Connected to MySQL
$result = mysql_query("SELECT * FROM table", $link) or die(mysql_error($link));

OR die() is not a good way to handle the error since we can not handle the thing in die. It will just end the script abruptly and then echo the error to the screen which you usually do NOT want to show to your end users, and let bloody hackers discover your schema. Alternately, the return values of mysql_* functions can often be used in conjunction with mysql_error() to handle errors.

PDO offers a better solution: exceptions. Anything we do with PDO should be wrapped in a try-catch block. We can force PDO into one of three error modes by setting the error mode attribute. Three error handling modes are below.

  • PDO::ERRMODE_SILENT. It's just setting error codes and acts pretty much the same as mysql_* where you must check each result and then look at $db->errorInfo(); to get the error details.
  • PDO::ERRMODE_WARNING Raise E_WARNING. (Run-time warnings (non-fatal errors). Execution of the script is not halted.)
  • PDO::ERRMODE_EXCEPTION: Throw exceptions. It represents an error raised by PDO. You should not throw a PDOException from your own code. See Exceptions for more information about exceptions in PHP. It acts very much like or die(mysql_error());, when it isn't caught. But unlike or die(), the PDOException can be caught and handled gracefully if you choose to do so.
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

And you can wrap it in try-catch, like below:

try {
    //Connect as appropriate as above
    $db->query('hi'); //Invalid query!
} 
catch (PDOException $ex) {
    echo "An Error occured!"; //User friendly message/message you want to show to user
    some_logging_function($ex->getMessage());
}

You do not have to handle with try-catch right now. You can catch it at any time appropriate, but I strongly recommend you to use try-catch. Also it may make more sense to catch it at outside the function that calls the PDO stuff:

function data_fun($db) {
    $stmt = $db->query("SELECT * FROM table");
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

//Then later
try {
    data_fun($db);
}
catch(PDOException $ex) {
    //Here you can handle error and show message/perform action you want.
}

Also, you can handle by or die() or we can say like mysql_*, but it will be really varied. You can hide the dangerous error messages in production by turning display_errors off and just reading your error log.

Now, after reading all the things above, you are probably thinking: what the heck is that when I just want to start leaning simple SELECT, INSERT, UPDATE, or DELETE statements? Don't worry, here we go:

So what you are doing in mysql_* is:

<?php
$result = mysql_query('SELECT * from table') or die(mysql_error());

$num_rows = mysql_num_rows($result);

while($row = mysql_fetch_assoc($result)) {
    echo $row['field1'];
}

Now in PDO, you can do this like:

Note: If you are using the method like below (query()), this method returns a PDOStatement object. So if you want to fetch the result, use it like above.

<?php
foreach($db->query('SELECT * FROM table') as $row) {
    echo $row['field1'];
}

In PDO Data, it is obtained via the ->fetch(), a method of your statement handle. Before calling fetch, the best approach would be telling PDO how youd like the data to be fetched. In the below section I am explaining this.

Note the use of PDO::FETCH_ASSOC in the fetch() and fetchAll() code above. This tells PDO to return the rows as an associative array with the field names as keys. There are many other fetch modes too which I will explain one by one.

$stmt->fetch(PDO::FETCH_ASSOC)

In the above, I have been using fetch(). You can also use:

  • PDOStatement::fetchAll() - Returns an array containing all of the result set rows
  • PDOStatement::fetchColumn() - Returns a single column from the next row of a result set
  • PDOStatement::fetchObject() - Fetches the next row and returns it as an object.
  • PDOStatement::setFetchMode() - Set the default fetch mode for this statement
  • PDO::FETCH_ASSOC: returns an array indexed by column name as returned in your result set
  • PDO::FETCH_BOTH (default): returns an array indexed by both column name and 0-indexed column number as returned in your result set
PDOStatement

Instead of using mysql_num_rows to get the number of returned rows, you can get a PDOStatement and do rowCount(), like:

<?php
$stmt = $db->query('SELECT * FROM table');
$row_count = $stmt->rowCount();
echo $row_count.' rows selected';

Getting the Last Inserted ID

<?php
$result = $db->exec("INSERT INTO table(firstname, lastname) VAULES('John', 'Doe')");
$insertId = $db->lastInsertId();

What we are doing in mysql_* function is:

<?php
$results = mysql_query("UPDATE table SET field='value'") or die(mysql_error());
echo mysql_affected_rows($result);

And in pdo, this same thing can be done by:

<?php
$affected_rows = $db->exec("UPDATE table SET field='value'");
echo $affected_rows;

In the above query PDO::exec execute an SQL statement and returns the number of affected rows.

The above method is only useful when you are not using variable in query. But when you need to use a variable in a query, do not ever ever try like the above and there for prepared statement or parameterized statement is.

Q. What is a prepared statement and why do I need them?A. A prepared statement is a pre-compiled SQL statement that can be executed multiple times by sending only the data to the server.

The typical workflow of using a prepared statement is as follows (quoted from Wikipedia three 3 point):

Prepare: The statement template is created by the application and sent to the database management system (DBMS). Certain values are left unspecified, called parameters, placeholders or bind variables (labelled ? below):

INSERT INTO PRODUCT (name, price) VALUES (?, ?)

The DBMS parses, compiles, and performs query optimization on the statement template, and stores the result without executing it.

  • Execute: At a later time, the application supplies (or binds) values for the parameters, and the DBMS executes the statement (possibly returning a result). The application may execute the statement as many times as it wants with different values. In this example, it might supply 'Bread' for the first parameter and 1.00 for the second parameter.

You can use a prepared statement by including placeholders in your SQL. There are basically three ones without placeholders (don't try this with variable its above one), one with unnamed placeholders, and one with named placeholders.

Q. So now, what are named placeholders and how do I use them?A. Named placeholders. Use descriptive names preceded by a colon, instead of question marks. We don't care about position/order of value in name place holder:

$stmt->bindParam(':bla', $bla);
bindParam(parameter,variable,data_type,length,driver_options)

You can also bind using an execute array as well:

<?php
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

Another nice feature for OOP friends is that named placeholders have the ability to insert objects directly into your database, assuming the properties match the named fields. For example:

class person {
    public $name;
    public $add;
    function __construct($a,$b) {
        $this->name = $a;
        $this->add = $b;
    }

}
$demo = new person('john','29 bla district');
$stmt = $db->prepare("INSERT INTO table (name, add) value (:name, :add)");
$stmt->execute((array)$demo);

Q. So now, what are unnamed placeholders and how do I use them?A. Let's have an example:

<?php
$stmt = $db->prepare("INSERT INTO folks (name, add) values (?, ?)");
$stmt->bindValue(1, $name, PDO::PARAM_STR);
$stmt->bindValue(2, $add, PDO::PARAM_STR);
$stmt->execute();

and

In the above, you can see those ? instead of a name like in a name place holder. Now in the first example, we assign variables to the various placeholders ($stmt->bindValue(1, $name, PDO::PARAM_STR);). Then, we assign values to those placeholders and execute the statement. In the second example, the first array element goes to the first ? and the second to the second ?.

NOTE: In unnamed placeholders we must take care of the proper order of the elements in the array that we are passing to the PDOStatement::execute() method.

SELECT
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
INSERT
$stmt = $db->prepare("INSERT INTO table(field1,field2) VALUES(:field1,:field2)");
$stmt->execute(array(':field1' => $field1, ':field2' => $field2));
$affected_rows = $stmt->rowCount();
DELETE
$stmt = $db->prepare("DELETE FROM table WHERE id=:id");
$stmt->bindValue(':id', $id, PDO::PARAM_STR);
$stmt->execute();
$affected_rows = $stmt->rowCount();
UPDATE
$stmt = $db->prepare("UPDATE table SET name=? WHERE id=?");
$stmt->execute(array($name, $id));
$affected_rows = $stmt->rowCount();

However PDO and/or MySQLi are not completely safe. Check the answer Are PDO prepared statements sufficient to prevent SQL injection? by ircmaxell. Also, I am quoting some part from his answer:

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->query('SET NAMES GBK');
$stmt = $pdo->prepare("SELECT * FROM test WHERE name = ? LIMIT 1");
$stmt->execute(array(chr(0xbf) . chr(0x27) . " OR 1=1 /*"));

What the good read above should propably mention: prepared statement take away any meaningful use of the IN (...) construct.

Just out of curiosity, is there some reason that MySQL/PHP developers couldn't have extended the MySQL library, updating the code behind existing functions and adding new function (including OO), all the while maintaining upward compatibility? Was that simply impossible to do cleanly, or they didn't want to bother? There's something to be said for maintaining upward compatibility, so existing applications don't break.

@Amine, No, it is not! :] While NullPoite really did a great job of writing it, this is most certainly isn't a good reading, because it is way to long. I'm pretty sure, that 8 of 10 visitors will simply skip it. And you also have explanation, why this answer isn't top voted. A tl;dr part in the beginning would be a good idea, I think.

@NullPoite As I said, your answer is great (no doubt about that!) and 405 score does reflect this. However, it is way to long. I only expressed my personal thinking and how I do understand, why other answer has more point than yours. Both answers are great, yours in only quite very long! :]

The question was "Why shouldnt I use mysql_* functions in PHP". This answer, while impressive and full of helpful information, goes WAY out of scope and like @trejder says - 8 out of 10 people are going to miss out on that information simply because they don't have 4 hours to spend trying to work through it. This would be far more valuable broken up and used as answers to several, more precise, questions.

mysql - Why shouldn't I use mysql_* functions in PHP? - Stack Overflow

php mysql database
Rectangle 27 1077

A simple and short PDO tutorial

PHP offers three different APIs to connect to MySQL. These are the mysql(removed as of PHP 7), mysqli, and PDO extensions.

The mysql_* functions used to be very popular, but their use is not encouraged anymore. The documentation team is discussing the database security situation, and educating users to move away from the commonly used ext/mysql extension is part of this (check php.internals: deprecating ext/mysql).

And the later PHP developer team has taken the decision to generate E_DEPRECATED errors when users connect to MySQL, whether through mysql_connect(), mysql_pconnect() or the implicit connection functionality built into ext/mysql.

ext/mysql was officially deprecated as of PHP 5.5 and has been removed as of PHP 7.

When you go on any mysql_* function manual page, you see a red box, explaining it should not be used anymore.

Moving away from ext/mysql is not only about security, but also about having access to all the features of the MySQL database.

ext/mysql was built for MySQL 3.23 and only got very few additions since then while mostly keeping compatibility with this old version which makes the code a bit harder to maintain. Missing features that is not supported by ext/mysql include: (from PHP manual).

mysql_*
  • Removed as of PHP 7
  • Doesn't support prepared statements or parameterized queries
  • Doesn't support all of the functionality in MySQL 5.1

Lack of support for prepared statements is particularly important as they provide a clearer, less error prone method of escaping and quoting external data than manually escaping it with a separate function call.

MySQLi
PDO
E_DEPRECATED
error_reporting
E_DEPRECATED:
error_reporting = E_ALL ^ E_DEPRECATED

Note that this will also hide other deprecation warnings, which, however, may be for things other than MySQL. (from PHP manual)

The article PDO vs. MySQLi: Which Should You Use? by Dejan Marjanovic will help you to choose.

And a better way is PDO, and I am now writing a simple PDO tutorial.

A. PDO PHP Data Objects is a database access layer providing a uniform method of access to multiple databases.

With mysql_* function or we can say it the old way (deprecated in PHP 5.5 and above)

$link = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('testdb', $link);
mysql_set_charset('UTF-8', $link);

With PDO: All you need to do is create a new PDO object. The constructor accepts parameters for specifying the database source PDO's constructor mostly takes four parameters which are DSN (data source name) and optionally username, password.

Here I think you are familiar with all except DSN; this is new in PDO. A DSN is basically a string of options that tell PDO which driver to use, and connection details. For further reference, check PDO MySQL DSN.

$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');

Note: you can also use charset=UTF-8, but sometimes it causes an error, so it's better to use utf8.

If there is any connection error, it will throw a PDOException object that can be cached to handle Exception further.

You can also pass in several driver options as an array to the fourth parameter. I recommend passing the parameter which puts PDO into exception mode. Because some PDO drivers don't support native prepared statements, so PDO performs emulation of the prepare. It also lets you manually enable this emulation. To use the native server-side prepared statements, you should explicitly set it false.

The other is to turn off prepare emulation which is enabled in the MySQL driver by default, but prepare emulation should be turned off to use PDO safely.

I will later explain why prepare emulation should be turned off. To find reason please check this post.

It is only usable if you are using an old version of MySQL which I do not recommended.

Below is an example of how you can do it:

Yes, we can also set some attributes after PDO construction with the setAttribute method:

$db = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF-8', 
              'username', 
              'password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Error handling is much easier in PDO than mysql_*.

A common practice when using mysql_* is:

//Connected to MySQL
$result = mysql_query("SELECT * FROM table", $link) or die(mysql_error($link));

OR die() is not a good way to handle the error since we can not handle the thing in die. It will just end the script abruptly and then echo the error to the screen which you usually do NOT want to show to your end users, and let bloody hackers discover your schema. Alternately, the return values of mysql_* functions can often be used in conjunction with mysql_error() to handle errors.

PDO offers a better solution: exceptions. Anything we do with PDO should be wrapped in a try-catch block. We can force PDO into one of three error modes by setting the error mode attribute. Three error handling modes are below.

  • PDO::ERRMODE_SILENT. It's just setting error codes and acts pretty much the same as mysql_* where you must check each result and then look at $db->errorInfo(); to get the error details.
  • PDO::ERRMODE_WARNING Raise E_WARNING. (Run-time warnings (non-fatal errors). Execution of the script is not halted.)
  • PDO::ERRMODE_EXCEPTION: Throw exceptions. It represents an error raised by PDO. You should not throw a PDOException from your own code. See Exceptions for more information about exceptions in PHP. It acts very much like or die(mysql_error());, when it isn't caught. But unlike or die(), the PDOException can be caught and handled gracefully if you choose to do so.
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

And you can wrap it in try-catch, like below:

try {
    //Connect as appropriate as above
    $db->query('hi'); //Invalid query!
} 
catch (PDOException $ex) {
    echo "An Error occured!"; //User friendly message/message you want to show to user
    some_logging_function($ex->getMessage());
}

You do not have to handle with try-catch right now. You can catch it at any time appropriate, but I strongly recommend you to use try-catch. Also it may make more sense to catch it at outside the function that calls the PDO stuff:

function data_fun($db) {
    $stmt = $db->query("SELECT * FROM table");
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

//Then later
try {
    data_fun($db);
}
catch(PDOException $ex) {
    //Here you can handle error and show message/perform action you want.
}

Also, you can handle by or die() or we can say like mysql_*, but it will be really varied. You can hide the dangerous error messages in production by turning display_errors off and just reading your error log.

Now, after reading all the things above, you are probably thinking: what the heck is that when I just want to start leaning simple SELECT, INSERT, UPDATE, or DELETE statements? Don't worry, here we go:

So what you are doing in mysql_* is:

<?php
$result = mysql_query('SELECT * from table') or die(mysql_error());

$num_rows = mysql_num_rows($result);

while($row = mysql_fetch_assoc($result)) {
    echo $row['field1'];
}

Now in PDO, you can do this like:

Note: If you are using the method like below (query()), this method returns a PDOStatement object. So if you want to fetch the result, use it like above.

<?php
foreach($db->query('SELECT * FROM table') as $row) {
    echo $row['field1'];
}

In PDO Data, it is obtained via the ->fetch(), a method of your statement handle. Before calling fetch, the best approach would be telling PDO how youd like the data to be fetched. In the below section I am explaining this.

Note the use of PDO::FETCH_ASSOC in the fetch() and fetchAll() code above. This tells PDO to return the rows as an associative array with the field names as keys. There are many other fetch modes too which I will explain one by one.

$stmt->fetch(PDO::FETCH_ASSOC)

In the above, I have been using fetch(). You can also use:

  • PDOStatement::fetchAll() - Returns an array containing all of the result set rows
  • PDOStatement::fetchColumn() - Returns a single column from the next row of a result set
  • PDOStatement::fetchObject() - Fetches the next row and returns it as an object.
  • PDOStatement::setFetchMode() - Set the default fetch mode for this statement
  • PDO::FETCH_ASSOC: returns an array indexed by column name as returned in your result set
  • PDO::FETCH_BOTH (default): returns an array indexed by both column name and 0-indexed column number as returned in your result set
PDOStatement

Instead of using mysql_num_rows to get the number of returned rows, you can get a PDOStatement and do rowCount(), like:

<?php
$stmt = $db->query('SELECT * FROM table');
$row_count = $stmt->rowCount();
echo $row_count.' rows selected';

Getting the Last Inserted ID

<?php
$result = $db->exec("INSERT INTO table(firstname, lastname) VAULES('John', 'Doe')");
$insertId = $db->lastInsertId();

What we are doing in mysql_* function is:

<?php
$results = mysql_query("UPDATE table SET field='value'") or die(mysql_error());
echo mysql_affected_rows($result);

And in pdo, this same thing can be done by:

<?php
$affected_rows = $db->exec("UPDATE table SET field='value'");
echo $affected_rows;

In the above query PDO::exec execute an SQL statement and returns the number of affected rows.

The above method is only useful when you are not using variable in query. But when you need to use a variable in a query, do not ever ever try like the above and there for prepared statement or parameterized statement is.

Q. What is a prepared statement and why do I need them?A. A prepared statement is a pre-compiled SQL statement that can be executed multiple times by sending only the data to the server.

The typical workflow of using a prepared statement is as follows (quoted from Wikipedia three 3 point):

Prepare: The statement template is created by the application and sent to the database management system (DBMS). Certain values are left unspecified, called parameters, placeholders or bind variables (labelled ? below):

INSERT INTO PRODUCT (name, price) VALUES (?, ?)

The DBMS parses, compiles, and performs query optimization on the statement template, and stores the result without executing it.

  • Execute: At a later time, the application supplies (or binds) values for the parameters, and the DBMS executes the statement (possibly returning a result). The application may execute the statement as many times as it wants with different values. In this example, it might supply 'Bread' for the first parameter and 1.00 for the second parameter.

You can use a prepared statement by including placeholders in your SQL. There are basically three ones without placeholders (don't try this with variable its above one), one with unnamed placeholders, and one with named placeholders.

Q. So now, what are named placeholders and how do I use them?A. Named placeholders. Use descriptive names preceded by a colon, instead of question marks. We don't care about position/order of value in name place holder:

$stmt->bindParam(':bla', $bla);
bindParam(parameter,variable,data_type,length,driver_options)

You can also bind using an execute array as well:

<?php
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

Another nice feature for OOP friends is that named placeholders have the ability to insert objects directly into your database, assuming the properties match the named fields. For example:

class person {
    public $name;
    public $add;
    function __construct($a,$b) {
        $this->name = $a;
        $this->add = $b;
    }

}
$demo = new person('john','29 bla district');
$stmt = $db->prepare("INSERT INTO table (name, add) value (:name, :add)");
$stmt->execute((array)$demo);

Q. So now, what are unnamed placeholders and how do I use them?A. Let's have an example:

<?php
$stmt = $db->prepare("INSERT INTO folks (name, add) values (?, ?)");
$stmt->bindValue(1, $name, PDO::PARAM_STR);
$stmt->bindValue(2, $add, PDO::PARAM_STR);
$stmt->execute();

and

In the above, you can see those ? instead of a name like in a name place holder. Now in the first example, we assign variables to the various placeholders ($stmt->bindValue(1, $name, PDO::PARAM_STR);). Then, we assign values to those placeholders and execute the statement. In the second example, the first array element goes to the first ? and the second to the second ?.

NOTE: In unnamed placeholders we must take care of the proper order of the elements in the array that we are passing to the PDOStatement::execute() method.

SELECT
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
INSERT
$stmt = $db->prepare("INSERT INTO table(field1,field2) VALUES(:field1,:field2)");
$stmt->execute(array(':field1' => $field1, ':field2' => $field2));
$affected_rows = $stmt->rowCount();
DELETE
$stmt = $db->prepare("DELETE FROM table WHERE id=:id");
$stmt->bindValue(':id', $id, PDO::PARAM_STR);
$stmt->execute();
$affected_rows = $stmt->rowCount();
UPDATE
$stmt = $db->prepare("UPDATE table SET name=? WHERE id=?");
$stmt->execute(array($name, $id));
$affected_rows = $stmt->rowCount();

However PDO and/or MySQLi are not completely safe. Check the answer Are PDO prepared statements sufficient to prevent SQL injection? by ircmaxell. Also, I am quoting some part from his answer:

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->query('SET NAMES GBK');
$stmt = $pdo->prepare("SELECT * FROM test WHERE name = ? LIMIT 1");
$stmt->execute(array(chr(0xbf) . chr(0x27) . " OR 1=1 /*"));

What the good read above should propably mention: prepared statement take away any meaningful use of the IN (...) construct.

Just out of curiosity, is there some reason that MySQL/PHP developers couldn't have extended the MySQL library, updating the code behind existing functions and adding new function (including OO), all the while maintaining upward compatibility? Was that simply impossible to do cleanly, or they didn't want to bother? There's something to be said for maintaining upward compatibility, so existing applications don't break.

@Amine, No, it is not! :] While NullPoite really did a great job of writing it, this is most certainly isn't a good reading, because it is way to long. I'm pretty sure, that 8 of 10 visitors will simply skip it. And you also have explanation, why this answer isn't top voted. A tl;dr part in the beginning would be a good idea, I think.

@NullPoite As I said, your answer is great (no doubt about that!) and 405 score does reflect this. However, it is way to long. I only expressed my personal thinking and how I do understand, why other answer has more point than yours. Both answers are great, yours in only quite very long! :]

The question was "Why shouldnt I use mysql_* functions in PHP". This answer, while impressive and full of helpful information, goes WAY out of scope and like @trejder says - 8 out of 10 people are going to miss out on that information simply because they don't have 4 hours to spend trying to work through it. This would be far more valuable broken up and used as answers to several, more precise, questions.

mysql - Why shouldn't I use mysql_* functions in PHP? - Stack Overflow

php mysql database
Rectangle 27 1077

A simple and short PDO tutorial

PHP offers three different APIs to connect to MySQL. These are the mysql(removed as of PHP 7), mysqli, and PDO extensions.

The mysql_* functions used to be very popular, but their use is not encouraged anymore. The documentation team is discussing the database security situation, and educating users to move away from the commonly used ext/mysql extension is part of this (check php.internals: deprecating ext/mysql).

And the later PHP developer team has taken the decision to generate E_DEPRECATED errors when users connect to MySQL, whether through mysql_connect(), mysql_pconnect() or the implicit connection functionality built into ext/mysql.

ext/mysql was officially deprecated as of PHP 5.5 and has been removed as of PHP 7.

When you go on any mysql_* function manual page, you see a red box, explaining it should not be used anymore.

Moving away from ext/mysql is not only about security, but also about having access to all the features of the MySQL database.

ext/mysql was built for MySQL 3.23 and only got very few additions since then while mostly keeping compatibility with this old version which makes the code a bit harder to maintain. Missing features that is not supported by ext/mysql include: (from PHP manual).

mysql_*
  • Removed as of PHP 7
  • Doesn't support prepared statements or parameterized queries
  • Doesn't support all of the functionality in MySQL 5.1

Lack of support for prepared statements is particularly important as they provide a clearer, less error prone method of escaping and quoting external data than manually escaping it with a separate function call.

MySQLi
PDO
E_DEPRECATED
error_reporting
E_DEPRECATED:
error_reporting = E_ALL ^ E_DEPRECATED

Note that this will also hide other deprecation warnings, which, however, may be for things other than MySQL. (from PHP manual)

The article PDO vs. MySQLi: Which Should You Use? by Dejan Marjanovic will help you to choose.

And a better way is PDO, and I am now writing a simple PDO tutorial.

A. PDO PHP Data Objects is a database access layer providing a uniform method of access to multiple databases.

With mysql_* function or we can say it the old way (deprecated in PHP 5.5 and above)

$link = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('testdb', $link);
mysql_set_charset('UTF-8', $link);

With PDO: All you need to do is create a new PDO object. The constructor accepts parameters for specifying the database source PDO's constructor mostly takes four parameters which are DSN (data source name) and optionally username, password.

Here I think you are familiar with all except DSN; this is new in PDO. A DSN is basically a string of options that tell PDO which driver to use, and connection details. For further reference, check PDO MySQL DSN.

$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');

Note: you can also use charset=UTF-8, but sometimes it causes an error, so it's better to use utf8.

If there is any connection error, it will throw a PDOException object that can be cached to handle Exception further.

You can also pass in several driver options as an array to the fourth parameter. I recommend passing the parameter which puts PDO into exception mode. Because some PDO drivers don't support native prepared statements, so PDO performs emulation of the prepare. It also lets you manually enable this emulation. To use the native server-side prepared statements, you should explicitly set it false.

The other is to turn off prepare emulation which is enabled in the MySQL driver by default, but prepare emulation should be turned off to use PDO safely.

I will later explain why prepare emulation should be turned off. To find reason please check this post.

It is only usable if you are using an old version of MySQL which I do not recommended.

Below is an example of how you can do it:

Yes, we can also set some attributes after PDO construction with the setAttribute method:

$db = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF-8', 
              'username', 
              'password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Error handling is much easier in PDO than mysql_*.

A common practice when using mysql_* is:

//Connected to MySQL
$result = mysql_query("SELECT * FROM table", $link) or die(mysql_error($link));

OR die() is not a good way to handle the error since we can not handle the thing in die. It will just end the script abruptly and then echo the error to the screen which you usually do NOT want to show to your end users, and let bloody hackers discover your schema. Alternately, the return values of mysql_* functions can often be used in conjunction with mysql_error() to handle errors.

PDO offers a better solution: exceptions. Anything we do with PDO should be wrapped in a try-catch block. We can force PDO into one of three error modes by setting the error mode attribute. Three error handling modes are below.

  • PDO::ERRMODE_SILENT. It's just setting error codes and acts pretty much the same as mysql_* where you must check each result and then look at $db->errorInfo(); to get the error details.
  • PDO::ERRMODE_WARNING Raise E_WARNING. (Run-time warnings (non-fatal errors). Execution of the script is not halted.)
  • PDO::ERRMODE_EXCEPTION: Throw exceptions. It represents an error raised by PDO. You should not throw a PDOException from your own code. See Exceptions for more information about exceptions in PHP. It acts very much like or die(mysql_error());, when it isn't caught. But unlike or die(), the PDOException can be caught and handled gracefully if you choose to do so.
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

And you can wrap it in try-catch, like below:

try {
    //Connect as appropriate as above
    $db->query('hi'); //Invalid query!
} 
catch (PDOException $ex) {
    echo "An Error occured!"; //User friendly message/message you want to show to user
    some_logging_function($ex->getMessage());
}

You do not have to handle with try-catch right now. You can catch it at any time appropriate, but I strongly recommend you to use try-catch. Also it may make more sense to catch it at outside the function that calls the PDO stuff:

function data_fun($db) {
    $stmt = $db->query("SELECT * FROM table");
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

//Then later
try {
    data_fun($db);
}
catch(PDOException $ex) {
    //Here you can handle error and show message/perform action you want.
}

Also, you can handle by or die() or we can say like mysql_*, but it will be really varied. You can hide the dangerous error messages in production by turning display_errors off and just reading your error log.

Now, after reading all the things above, you are probably thinking: what the heck is that when I just want to start leaning simple SELECT, INSERT, UPDATE, or DELETE statements? Don't worry, here we go:

So what you are doing in mysql_* is:

<?php
$result = mysql_query('SELECT * from table') or die(mysql_error());

$num_rows = mysql_num_rows($result);

while($row = mysql_fetch_assoc($result)) {
    echo $row['field1'];
}

Now in PDO, you can do this like:

Note: If you are using the method like below (query()), this method returns a PDOStatement object. So if you want to fetch the result, use it like above.

<?php
foreach($db->query('SELECT * FROM table') as $row) {
    echo $row['field1'];
}

In PDO Data, it is obtained via the ->fetch(), a method of your statement handle. Before calling fetch, the best approach would be telling PDO how youd like the data to be fetched. In the below section I am explaining this.

Note the use of PDO::FETCH_ASSOC in the fetch() and fetchAll() code above. This tells PDO to return the rows as an associative array with the field names as keys. There are many other fetch modes too which I will explain one by one.

$stmt->fetch(PDO::FETCH_ASSOC)

In the above, I have been using fetch(). You can also use:

  • PDOStatement::fetchAll() - Returns an array containing all of the result set rows
  • PDOStatement::fetchColumn() - Returns a single column from the next row of a result set
  • PDOStatement::fetchObject() - Fetches the next row and returns it as an object.
  • PDOStatement::setFetchMode() - Set the default fetch mode for this statement
  • PDO::FETCH_ASSOC: returns an array indexed by column name as returned in your result set
  • PDO::FETCH_BOTH (default): returns an array indexed by both column name and 0-indexed column number as returned in your result set
PDOStatement

Instead of using mysql_num_rows to get the number of returned rows, you can get a PDOStatement and do rowCount(), like:

<?php
$stmt = $db->query('SELECT * FROM table');
$row_count = $stmt->rowCount();
echo $row_count.' rows selected';

Getting the Last Inserted ID

<?php
$result = $db->exec("INSERT INTO table(firstname, lastname) VAULES('John', 'Doe')");
$insertId = $db->lastInsertId();

What we are doing in mysql_* function is:

<?php
$results = mysql_query("UPDATE table SET field='value'") or die(mysql_error());
echo mysql_affected_rows($result);

And in pdo, this same thing can be done by:

<?php
$affected_rows = $db->exec("UPDATE table SET field='value'");
echo $affected_rows;

In the above query PDO::exec execute an SQL statement and returns the number of affected rows.

The above method is only useful when you are not using variable in query. But when you need to use a variable in a query, do not ever ever try like the above and there for prepared statement or parameterized statement is.

Q. What is a prepared statement and why do I need them?A. A prepared statement is a pre-compiled SQL statement that can be executed multiple times by sending only the data to the server.

The typical workflow of using a prepared statement is as follows (quoted from Wikipedia three 3 point):

Prepare: The statement template is created by the application and sent to the database management system (DBMS). Certain values are left unspecified, called parameters, placeholders or bind variables (labelled ? below):

INSERT INTO PRODUCT (name, price) VALUES (?, ?)

The DBMS parses, compiles, and performs query optimization on the statement template, and stores the result without executing it.

  • Execute: At a later time, the application supplies (or binds) values for the parameters, and the DBMS executes the statement (possibly returning a result). The application may execute the statement as many times as it wants with different values. In this example, it might supply 'Bread' for the first parameter and 1.00 for the second parameter.

You can use a prepared statement by including placeholders in your SQL. There are basically three ones without placeholders (don't try this with variable its above one), one with unnamed placeholders, and one with named placeholders.

Q. So now, what are named placeholders and how do I use them?A. Named placeholders. Use descriptive names preceded by a colon, instead of question marks. We don't care about position/order of value in name place holder:

$stmt->bindParam(':bla', $bla);
bindParam(parameter,variable,data_type,length,driver_options)

You can also bind using an execute array as well:

<?php
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

Another nice feature for OOP friends is that named placeholders have the ability to insert objects directly into your database, assuming the properties match the named fields. For example:

class person {
    public $name;
    public $add;
    function __construct($a,$b) {
        $this->name = $a;
        $this->add = $b;
    }

}
$demo = new person('john','29 bla district');
$stmt = $db->prepare("INSERT INTO table (name, add) value (:name, :add)");
$stmt->execute((array)$demo);

Q. So now, what are unnamed placeholders and how do I use them?A. Let's have an example:

<?php
$stmt = $db->prepare("INSERT INTO folks (name, add) values (?, ?)");
$stmt->bindValue(1, $name, PDO::PARAM_STR);
$stmt->bindValue(2, $add, PDO::PARAM_STR);
$stmt->execute();

and

In the above, you can see those ? instead of a name like in a name place holder. Now in the first example, we assign variables to the various placeholders ($stmt->bindValue(1, $name, PDO::PARAM_STR);). Then, we assign values to those placeholders and execute the statement. In the second example, the first array element goes to the first ? and the second to the second ?.

NOTE: In unnamed placeholders we must take care of the proper order of the elements in the array that we are passing to the PDOStatement::execute() method.

SELECT
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
INSERT
$stmt = $db->prepare("INSERT INTO table(field1,field2) VALUES(:field1,:field2)");
$stmt->execute(array(':field1' => $field1, ':field2' => $field2));
$affected_rows = $stmt->rowCount();
DELETE
$stmt = $db->prepare("DELETE FROM table WHERE id=:id");
$stmt->bindValue(':id', $id, PDO::PARAM_STR);
$stmt->execute();
$affected_rows = $stmt->rowCount();
UPDATE
$stmt = $db->prepare("UPDATE table SET name=? WHERE id=?");
$stmt->execute(array($name, $id));
$affected_rows = $stmt->rowCount();

However PDO and/or MySQLi are not completely safe. Check the answer Are PDO prepared statements sufficient to prevent SQL injection? by ircmaxell. Also, I am quoting some part from his answer:

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->query('SET NAMES GBK');
$stmt = $pdo->prepare("SELECT * FROM test WHERE name = ? LIMIT 1");
$stmt->execute(array(chr(0xbf) . chr(0x27) . " OR 1=1 /*"));

What the good read above should propably mention: prepared statement take away any meaningful use of the IN (...) construct.

Just out of curiosity, is there some reason that MySQL/PHP developers couldn't have extended the MySQL library, updating the code behind existing functions and adding new function (including OO), all the while maintaining upward compatibility? Was that simply impossible to do cleanly, or they didn't want to bother? There's something to be said for maintaining upward compatibility, so existing applications don't break.

@Amine, No, it is not! :] While NullPoite really did a great job of writing it, this is most certainly isn't a good reading, because it is way to long. I'm pretty sure, that 8 of 10 visitors will simply skip it. And you also have explanation, why this answer isn't top voted. A tl;dr part in the beginning would be a good idea, I think.

@NullPoite As I said, your answer is great (no doubt about that!) and 405 score does reflect this. However, it is way to long. I only expressed my personal thinking and how I do understand, why other answer has more point than yours. Both answers are great, yours in only quite very long! :]

The question was "Why shouldnt I use mysql_* functions in PHP". This answer, while impressive and full of helpful information, goes WAY out of scope and like @trejder says - 8 out of 10 people are going to miss out on that information simply because they don't have 4 hours to spend trying to work through it. This would be far more valuable broken up and used as answers to several, more precise, questions.

mysql - Why shouldn't I use mysql_* functions in PHP? - Stack Overflow

php mysql database
Rectangle 27 1073

A simple and short PDO tutorial

PHP offers three different APIs to connect to MySQL. These are the mysql(removed as of PHP 7), mysqli, and PDO extensions.

The mysql_* functions used to be very popular, but their use is not encouraged anymore. The documentation team is discussing the database security situation, and educating users to move away from the commonly used ext/mysql extension is part of this (check php.internals: deprecating ext/mysql).

And the later PHP developer team has taken the decision to generate E_DEPRECATED errors when users connect to MySQL, whether through mysql_connect(), mysql_pconnect() or the implicit connection functionality built into ext/mysql.

ext/mysql was officially deprecated as of PHP 5.5 and has been removed as of PHP 7.

When you go on any mysql_* function manual page, you see a red box, explaining it should not be used anymore.

Moving away from ext/mysql is not only about security, but also about having access to all the features of the MySQL database.

ext/mysql was built for MySQL 3.23 and only got very few additions since then while mostly keeping compatibility with this old version which makes the code a bit harder to maintain. Missing features that is not supported by ext/mysql include: (from PHP manual).

mysql_*
  • Removed as of PHP 7
  • Doesn't support prepared statements or parameterized queries
  • Doesn't support all of the functionality in MySQL 5.1

Lack of support for prepared statements is particularly important as they provide a clearer, less error prone method of escaping and quoting external data than manually escaping it with a separate function call.

MySQLi
PDO
E_DEPRECATED
error_reporting
E_DEPRECATED:
error_reporting = E_ALL ^ E_DEPRECATED

Note that this will also hide other deprecation warnings, which, however, may be for things other than MySQL. (from PHP manual)

The article PDO vs. MySQLi: Which Should You Use? by Dejan Marjanovic will help you to choose.

And a better way is PDO, and I am now writing a simple PDO tutorial.

A. PDO PHP Data Objects is a database access layer providing a uniform method of access to multiple databases.

With mysql_* function or we can say it the old way (deprecated in PHP 5.5 and above)

$link = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('testdb', $link);
mysql_set_charset('UTF-8', $link);

With PDO: All you need to do is create a new PDO object. The constructor accepts parameters for specifying the database source PDO's constructor mostly takes four parameters which are DSN (data source name) and optionally username, password.

Here I think you are familiar with all except DSN; this is new in PDO. A DSN is basically a string of options that tell PDO which driver to use, and connection details. For further reference, check PDO MySQL DSN.

$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');

Note: you can also use charset=UTF-8, but sometimes it causes an error, so it's better to use utf8.

If there is any connection error, it will throw a PDOException object that can be cached to handle Exception further.

You can also pass in several driver options as an array to the fourth parameter. I recommend passing the parameter which puts PDO into exception mode. Because some PDO drivers don't support native prepared statements, so PDO performs emulation of the prepare. It also lets you manually enable this emulation. To use the native server-side prepared statements, you should explicitly set it false.

The other is to turn off prepare emulation which is enabled in the MySQL driver by default, but prepare emulation should be turned off to use PDO safely.

I will later explain why prepare emulation should be turned off. To find reason please check this post.

It is only usable if you are using an old version of MySQL which I do not recommended.

Below is an example of how you can do it:

Yes, we can also set some attributes after PDO construction with the setAttribute method:

$db = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF-8', 
              'username', 
              'password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Error handling is much easier in PDO than mysql_*.

A common practice when using mysql_* is:

//Connected to MySQL
$result = mysql_query("SELECT * FROM table", $link) or die(mysql_error($link));

OR die() is not a good way to handle the error since we can not handle the thing in die. It will just end the script abruptly and then echo the error to the screen which you usually do NOT want to show to your end users, and let bloody hackers discover your schema. Alternately, the return values of mysql_* functions can often be used in conjunction with mysql_error() to handle errors.

PDO offers a better solution: exceptions. Anything we do with PDO should be wrapped in a try-catch block. We can force PDO into one of three error modes by setting the error mode attribute. Three error handling modes are below.

  • PDO::ERRMODE_SILENT. It's just setting error codes and acts pretty much the same as mysql_* where you must check each result and then look at $db->errorInfo(); to get the error details.
  • PDO::ERRMODE_WARNING Raise E_WARNING. (Run-time warnings (non-fatal errors). Execution of the script is not halted.)
  • PDO::ERRMODE_EXCEPTION: Throw exceptions. It represents an error raised by PDO. You should not throw a PDOException from your own code. See Exceptions for more information about exceptions in PHP. It acts very much like or die(mysql_error());, when it isn't caught. But unlike or die(), the PDOException can be caught and handled gracefully if you choose to do so.
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

And you can wrap it in try-catch, like below:

try {
    //Connect as appropriate as above
    $db->query('hi'); //Invalid query!
} 
catch (PDOException $ex) {
    echo "An Error occured!"; //User friendly message/message you want to show to user
    some_logging_function($ex->getMessage());
}

You do not have to handle with try-catch right now. You can catch it at any time appropriate, but I strongly recommend you to use try-catch. Also it may make more sense to catch it at outside the function that calls the PDO stuff:

function data_fun($db) {
    $stmt = $db->query("SELECT * FROM table");
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

//Then later
try {
    data_fun($db);
}
catch(PDOException $ex) {
    //Here you can handle error and show message/perform action you want.
}

Also, you can handle by or die() or we can say like mysql_*, but it will be really varied. You can hide the dangerous error messages in production by turning display_errors off and just reading your error log.

Now, after reading all the things above, you are probably thinking: what the heck is that when I just want to start leaning simple SELECT, INSERT, UPDATE, or DELETE statements? Don't worry, here we go:

So what you are doing in mysql_* is:

<?php
$result = mysql_query('SELECT * from table') or die(mysql_error());

$num_rows = mysql_num_rows($result);

while($row = mysql_fetch_assoc($result)) {
    echo $row['field1'];
}

Now in PDO, you can do this like:

Note: If you are using the method like below (query()), this method returns a PDOStatement object. So if you want to fetch the result, use it like above.

<?php
foreach($db->query('SELECT * FROM table') as $row) {
    echo $row['field1'];
}

In PDO Data, it is obtained via the ->fetch(), a method of your statement handle. Before calling fetch, the best approach would be telling PDO how youd like the data to be fetched. In the below section I am explaining this.

Note the use of PDO::FETCH_ASSOC in the fetch() and fetchAll() code above. This tells PDO to return the rows as an associative array with the field names as keys. There are many other fetch modes too which I will explain one by one.

$stmt->fetch(PDO::FETCH_ASSOC)

In the above, I have been using fetch(). You can also use:

  • PDOStatement::fetchAll() - Returns an array containing all of the result set rows
  • PDOStatement::fetchColumn() - Returns a single column from the next row of a result set
  • PDOStatement::fetchObject() - Fetches the next row and returns it as an object.
  • PDOStatement::setFetchMode() - Set the default fetch mode for this statement
  • PDO::FETCH_ASSOC: returns an array indexed by column name as returned in your result set
  • PDO::FETCH_BOTH (default): returns an array indexed by both column name and 0-indexed column number as returned in your result set
PDOStatement

Instead of using mysql_num_rows to get the number of returned rows, you can get a PDOStatement and do rowCount(), like:

<?php
$stmt = $db->query('SELECT * FROM table');
$row_count = $stmt->rowCount();
echo $row_count.' rows selected';

Getting the Last Inserted ID

<?php
$result = $db->exec("INSERT INTO table(firstname, lastname) VAULES('John', 'Doe')");
$insertId = $db->lastInsertId();

What we are doing in mysql_* function is:

<?php
$results = mysql_query("UPDATE table SET field='value'") or die(mysql_error());
echo mysql_affected_rows($result);

And in pdo, this same thing can be done by:

<?php
$affected_rows = $db->exec("UPDATE table SET field='value'");
echo $affected_rows;

In the above query PDO::exec execute an SQL statement and returns the number of affected rows.

The above method is only useful when you are not using variable in query. But when you need to use a variable in a query, do not ever ever try like the above and there for prepared statement or parameterized statement is.

Q. What is a prepared statement and why do I need them?A. A prepared statement is a pre-compiled SQL statement that can be executed multiple times by sending only the data to the server.

The typical workflow of using a prepared statement is as follows (quoted from Wikipedia three 3 point):

Prepare: The statement template is created by the application and sent to the database management system (DBMS). Certain values are left unspecified, called parameters, placeholders or bind variables (labelled ? below):

INSERT INTO PRODUCT (name, price) VALUES (?, ?)

The DBMS parses, compiles, and performs query optimization on the statement template, and stores the result without executing it.

  • Execute: At a later time, the application supplies (or binds) values for the parameters, and the DBMS executes the statement (possibly returning a result). The application may execute the statement as many times as it wants with different values. In this example, it might supply 'Bread' for the first parameter and 1.00 for the second parameter.

You can use a prepared statement by including placeholders in your SQL. There are basically three ones without placeholders (don't try this with variable its above one), one with unnamed placeholders, and one with named placeholders.

Q. So now, what are named placeholders and how do I use them?A. Named placeholders. Use descriptive names preceded by a colon, instead of question marks. We don't care about position/order of value in name place holder:

$stmt->bindParam(':bla', $bla);
bindParam(parameter,variable,data_type,length,driver_options)

You can also bind using an execute array as well:

<?php
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

Another nice feature for OOP friends is that named placeholders have the ability to insert objects directly into your database, assuming the properties match the named fields. For example:

class person {
    public $name;
    public $add;
    function __construct($a,$b) {
        $this->name = $a;
        $this->add = $b;
    }

}
$demo = new person('john','29 bla district');
$stmt = $db->prepare("INSERT INTO table (name, add) value (:name, :add)");
$stmt->execute((array)$demo);

Q. So now, what are unnamed placeholders and how do I use them?A. Let's have an example:

<?php
$stmt = $db->prepare("INSERT INTO folks (name, add) values (?, ?)");
$stmt->bindValue(1, $name, PDO::PARAM_STR);
$stmt->bindValue(2, $add, PDO::PARAM_STR);
$stmt->execute();

and

In the above, you can see those ? instead of a name like in a name place holder. Now in the first example, we assign variables to the various placeholders ($stmt->bindValue(1, $name, PDO::PARAM_STR);). Then, we assign values to those placeholders and execute the statement. In the second example, the first array element goes to the first ? and the second to the second ?.

NOTE: In unnamed placeholders we must take care of the proper order of the elements in the array that we are passing to the PDOStatement::execute() method.

SELECT
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
INSERT
$stmt = $db->prepare("INSERT INTO table(field1,field2) VALUES(:field1,:field2)");
$stmt->execute(array(':field1' => $field1, ':field2' => $field2));
$affected_rows = $stmt->rowCount();
DELETE
$stmt = $db->prepare("DELETE FROM table WHERE id=:id");
$stmt->bindValue(':id', $id, PDO::PARAM_STR);
$stmt->execute();
$affected_rows = $stmt->rowCount();
UPDATE
$stmt = $db->prepare("UPDATE table SET name=? WHERE id=?");
$stmt->execute(array($name, $id));
$affected_rows = $stmt->rowCount();

However PDO and/or MySQLi are not completely safe. Check the answer Are PDO prepared statements sufficient to prevent SQL injection? by ircmaxell. Also, I am quoting some part from his answer:

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->query('SET NAMES GBK');
$stmt = $pdo->prepare("SELECT * FROM test WHERE name = ? LIMIT 1");
$stmt->execute(array(chr(0xbf) . chr(0x27) . " OR 1=1 /*"));

What the good read above should propably mention: prepared statement take away any meaningful use of the IN (...) construct.

Just out of curiosity, is there some reason that MySQL/PHP developers couldn't have extended the MySQL library, updating the code behind existing functions and adding new function (including OO), all the while maintaining upward compatibility? Was that simply impossible to do cleanly, or they didn't want to bother? There's something to be said for maintaining upward compatibility, so existing applications don't break.

@Amine, No, it is not! :] While NullPoite really did a great job of writing it, this is most certainly isn't a good reading, because it is way to long. I'm pretty sure, that 8 of 10 visitors will simply skip it. And you also have explanation, why this answer isn't top voted. A tl;dr part in the beginning would be a good idea, I think.

@NullPoite As I said, your answer is great (no doubt about that!) and 405 score does reflect this. However, it is way to long. I only expressed my personal thinking and how I do understand, why other answer has more point than yours. Both answers are great, yours in only quite very long! :]

The question was "Why shouldnt I use mysql_* functions in PHP". This answer, while impressive and full of helpful information, goes WAY out of scope and like @trejder says - 8 out of 10 people are going to miss out on that information simply because they don't have 4 hours to spend trying to work through it. This would be far more valuable broken up and used as answers to several, more precise, questions.

mysql - Why shouldn't I use mysql_* functions in PHP? - Stack Overflow

php mysql database
Rectangle 27 1068

A simple and short PDO tutorial

PHP offers three different APIs to connect to MySQL. These are the mysql(removed as of PHP 7), mysqli, and PDO extensions.

The mysql_* functions used to be very popular, but their use is not encouraged anymore. The documentation team is discussing the database security situation, and educating users to move away from the commonly used ext/mysql extension is part of this (check php.internals: deprecating ext/mysql).

And the later PHP developer team has taken the decision to generate E_DEPRECATED errors when users connect to MySQL, whether through mysql_connect(), mysql_pconnect() or the implicit connection functionality built into ext/mysql.

ext/mysql was officially deprecated as of PHP 5.5 and has been removed as of PHP 7.

When you go on any mysql_* function manual page, you see a red box, explaining it should not be used anymore.

Moving away from ext/mysql is not only about security, but also about having access to all the features of the MySQL database.

ext/mysql was built for MySQL 3.23 and only got very few additions since then while mostly keeping compatibility with this old version which makes the code a bit harder to maintain. Missing features that is not supported by ext/mysql include: (from PHP manual).

mysql_*
  • Removed as of PHP 7
  • Doesn't support prepared statements or parameterized queries
  • Doesn't support all of the functionality in MySQL 5.1

Lack of support for prepared statements is particularly important as they provide a clearer, less error prone method of escaping and quoting external data than manually escaping it with a separate function call.

MySQLi
PDO
E_DEPRECATED
error_reporting
E_DEPRECATED:
error_reporting = E_ALL ^ E_DEPRECATED

Note that this will also hide other deprecation warnings, which, however, may be for things other than MySQL. (from PHP manual)

The article PDO vs. MySQLi: Which Should You Use? by Dejan Marjanovic will help you to choose.

And a better way is PDO, and I am now writing a simple PDO tutorial.

A. PDO PHP Data Objects is a database access layer providing a uniform method of access to multiple databases.

With mysql_* function or we can say it the old way (deprecated in PHP 5.5 and above)

$link = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('testdb', $link);
mysql_set_charset('UTF-8', $link);

With PDO: All you need to do is create a new PDO object. The constructor accepts parameters for specifying the database source PDO's constructor mostly takes four parameters which are DSN (data source name) and optionally username, password.

Here I think you are familiar with all except DSN; this is new in PDO. A DSN is basically a string of options that tell PDO which driver to use, and connection details. For further reference, check PDO MySQL DSN.

$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');

Note: you can also use charset=UTF-8, but sometimes it causes an error, so it's better to use utf8.

If there is any connection error, it will throw a PDOException object that can be cached to handle Exception further.

You can also pass in several driver options as an array to the fourth parameter. I recommend passing the parameter which puts PDO into exception mode. Because some PDO drivers don't support native prepared statements, so PDO performs emulation of the prepare. It also lets you manually enable this emulation. To use the native server-side prepared statements, you should explicitly set it false.

The other is to turn off prepare emulation which is enabled in the MySQL driver by default, but prepare emulation should be turned off to use PDO safely.

I will later explain why prepare emulation should be turned off. To find reason please check this post.

It is only usable if you are using an old version of MySQL which I do not recommended.

Below is an example of how you can do it:

Yes, we can also set some attributes after PDO construction with the setAttribute method:

$db = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF-8', 
              'username', 
              'password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Error handling is much easier in PDO than mysql_*.

A common practice when using mysql_* is:

//Connected to MySQL
$result = mysql_query("SELECT * FROM table", $link) or die(mysql_error($link));

OR die() is not a good way to handle the error since we can not handle the thing in die. It will just end the script abruptly and then echo the error to the screen which you usually do NOT want to show to your end users, and let bloody hackers discover your schema. Alternately, the return values of mysql_* functions can often be used in conjunction with mysql_error() to handle errors.

PDO offers a better solution: exceptions. Anything we do with PDO should be wrapped in a try-catch block. We can force PDO into one of three error modes by setting the error mode attribute. Three error handling modes are below.

  • PDO::ERRMODE_SILENT. It's just setting error codes and acts pretty much the same as mysql_* where you must check each result and then look at $db->errorInfo(); to get the error details.
  • PDO::ERRMODE_WARNING Raise E_WARNING. (Run-time warnings (non-fatal errors). Execution of the script is not halted.)
  • PDO::ERRMODE_EXCEPTION: Throw exceptions. It represents an error raised by PDO. You should not throw a PDOException from your own code. See Exceptions for more information about exceptions in PHP. It acts very much like or die(mysql_error());, when it isn't caught. But unlike or die(), the PDOException can be caught and handled gracefully if you choose to do so.
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

And you can wrap it in try-catch, like below:

try {
    //Connect as appropriate as above
    $db->query('hi'); //Invalid query!
} 
catch (PDOException $ex) {
    echo "An Error occured!"; //User friendly message/message you want to show to user
    some_logging_function($ex->getMessage());
}

You do not have to handle with try-catch right now. You can catch it at any time appropriate, but I strongly recommend you to use try-catch. Also it may make more sense to catch it at outside the function that calls the PDO stuff:

function data_fun($db) {
    $stmt = $db->query("SELECT * FROM table");
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

//Then later
try {
    data_fun($db);
}
catch(PDOException $ex) {
    //Here you can handle error and show message/perform action you want.
}

Also, you can handle by or die() or we can say like mysql_*, but it will be really varied. You can hide the dangerous error messages in production by turning display_errors off and just reading your error log.

Now, after reading all the things above, you are probably thinking: what the heck is that when I just want to start leaning simple SELECT, INSERT, UPDATE, or DELETE statements? Don't worry, here we go:

So what you are doing in mysql_* is:

<?php
$result = mysql_query('SELECT * from table') or die(mysql_error());

$num_rows = mysql_num_rows($result);

while($row = mysql_fetch_assoc($result)) {
    echo $row['field1'];
}

Now in PDO, you can do this like:

Note: If you are using the method like below (query()), this method returns a PDOStatement object. So if you want to fetch the result, use it like above.

<?php
foreach($db->query('SELECT * FROM table') as $row) {
    echo $row['field1'];
}

In PDO Data, it is obtained via the ->fetch(), a method of your statement handle. Before calling fetch, the best approach would be telling PDO how youd like the data to be fetched. In the below section I am explaining this.

Note the use of PDO::FETCH_ASSOC in the fetch() and fetchAll() code above. This tells PDO to return the rows as an associative array with the field names as keys. There are many other fetch modes too which I will explain one by one.

$stmt->fetch(PDO::FETCH_ASSOC)

In the above, I have been using fetch(). You can also use:

  • PDOStatement::fetchAll() - Returns an array containing all of the result set rows
  • PDOStatement::fetchColumn() - Returns a single column from the next row of a result set
  • PDOStatement::fetchObject() - Fetches the next row and returns it as an object.
  • PDOStatement::setFetchMode() - Set the default fetch mode for this statement
  • PDO::FETCH_ASSOC: returns an array indexed by column name as returned in your result set
  • PDO::FETCH_BOTH (default): returns an array indexed by both column name and 0-indexed column number as returned in your result set
PDOStatement

Instead of using mysql_num_rows to get the number of returned rows, you can get a PDOStatement and do rowCount(), like:

<?php
$stmt = $db->query('SELECT * FROM table');
$row_count = $stmt->rowCount();
echo $row_count.' rows selected';

Getting the Last Inserted ID

<?php
$result = $db->exec("INSERT INTO table(firstname, lastname) VAULES('John', 'Doe')");
$insertId = $db->lastInsertId();

What we are doing in mysql_* function is:

<?php
$results = mysql_query("UPDATE table SET field='value'") or die(mysql_error());
echo mysql_affected_rows($result);

And in pdo, this same thing can be done by:

<?php
$affected_rows = $db->exec("UPDATE table SET field='value'");
echo $affected_rows;

In the above query PDO::exec execute an SQL statement and returns the number of affected rows.

The above method is only useful when you are not using variable in query. But when you need to use a variable in a query, do not ever ever try like the above and there for prepared statement or parameterized statement is.

Q. What is a prepared statement and why do I need them?A. A prepared statement is a pre-compiled SQL statement that can be executed multiple times by sending only the data to the server.

The typical workflow of using a prepared statement is as follows (quoted from Wikipedia three 3 point):

Prepare: The statement template is created by the application and sent to the database management system (DBMS). Certain values are left unspecified, called parameters, placeholders or bind variables (labelled ? below):

INSERT INTO PRODUCT (name, price) VALUES (?, ?)

The DBMS parses, compiles, and performs query optimization on the statement template, and stores the result without executing it.

  • Execute: At a later time, the application supplies (or binds) values for the parameters, and the DBMS executes the statement (possibly returning a result). The application may execute the statement as many times as it wants with different values. In this example, it might supply 'Bread' for the first parameter and 1.00 for the second parameter.

You can use a prepared statement by including placeholders in your SQL. There are basically three ones without placeholders (don't try this with variable its above one), one with unnamed placeholders, and one with named placeholders.

Q. So now, what are named placeholders and how do I use them?A. Named placeholders. Use descriptive names preceded by a colon, instead of question marks. We don't care about position/order of value in name place holder:

$stmt->bindParam(':bla', $bla);
bindParam(parameter,variable,data_type,length,driver_options)

You can also bind using an execute array as well:

<?php
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

Another nice feature for OOP friends is that named placeholders have the ability to insert objects directly into your database, assuming the properties match the named fields. For example:

class person {
    public $name;
    public $add;
    function __construct($a,$b) {
        $this->name = $a;
        $this->add = $b;
    }

}
$demo = new person('john','29 bla district');
$stmt = $db->prepare("INSERT INTO table (name, add) value (:name, :add)");
$stmt->execute((array)$demo);

Q. So now, what are unnamed placeholders and how do I use them?A. Let's have an example:

<?php
$stmt = $db->prepare("INSERT INTO folks (name, add) values (?, ?)");
$stmt->bindValue(1, $name, PDO::PARAM_STR);
$stmt->bindValue(2, $add, PDO::PARAM_STR);
$stmt->execute();

and

In the above, you can see those ? instead of a name like in a name place holder. Now in the first example, we assign variables to the various placeholders ($stmt->bindValue(1, $name, PDO::PARAM_STR);). Then, we assign values to those placeholders and execute the statement. In the second example, the first array element goes to the first ? and the second to the second ?.

NOTE: In unnamed placeholders we must take care of the proper order of the elements in the array that we are passing to the PDOStatement::execute() method.

SELECT
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
INSERT
$stmt = $db->prepare("INSERT INTO table(field1,field2) VALUES(:field1,:field2)");
$stmt->execute(array(':field1' => $field1, ':field2' => $field2));
$affected_rows = $stmt->rowCount();
DELETE
$stmt = $db->prepare("DELETE FROM table WHERE id=:id");
$stmt->bindValue(':id', $id, PDO::PARAM_STR);
$stmt->execute();
$affected_rows = $stmt->rowCount();
UPDATE
$stmt = $db->prepare("UPDATE table SET name=? WHERE id=?");
$stmt->execute(array($name, $id));
$affected_rows = $stmt->rowCount();

However PDO and/or MySQLi are not completely safe. Check the answer Are PDO prepared statements sufficient to prevent SQL injection? by ircmaxell. Also, I am quoting some part from his answer:

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->query('SET NAMES GBK');
$stmt = $pdo->prepare("SELECT * FROM test WHERE name = ? LIMIT 1");
$stmt->execute(array(chr(0xbf) . chr(0x27) . " OR 1=1 /*"));

What the good read above should propably mention: prepared statement take away any meaningful use of the IN (...) construct.

Just out of curiosity, is there some reason that MySQL/PHP developers couldn't have extended the MySQL library, updating the code behind existing functions and adding new function (including OO), all the while maintaining upward compatibility? Was that simply impossible to do cleanly, or they didn't want to bother? There's something to be said for maintaining upward compatibility, so existing applications don't break.

@Amine, No, it is not! :] While NullPoite really did a great job of writing it, this is most certainly isn't a good reading, because it is way to long. I'm pretty sure, that 8 of 10 visitors will simply skip it. And you also have explanation, why this answer isn't top voted. A tl;dr part in the beginning would be a good idea, I think.

@NullPoite As I said, your answer is great (no doubt about that!) and 405 score does reflect this. However, it is way to long. I only expressed my personal thinking and how I do understand, why other answer has more point than yours. Both answers are great, yours in only quite very long! :]

The question was "Why shouldnt I use mysql_* functions in PHP". This answer, while impressive and full of helpful information, goes WAY out of scope and like @trejder says - 8 out of 10 people are going to miss out on that information simply because they don't have 4 hours to spend trying to work through it. This would be far more valuable broken up and used as answers to several, more precise, questions.

mysql - Why shouldn't I use mysql_* functions in PHP? - Stack Overflow

php mysql database
Rectangle 27 1052

A simple and short PDO tutorial

PHP offers three different APIs to connect to MySQL. These are the mysql(removed as of PHP 7), mysqli, and PDO extensions.

The mysql_* functions used to be very popular, but their use is not encouraged anymore. The documentation team is discussing the database security situation, and educating users to move away from the commonly used ext/mysql extension is part of this (check php.internals: deprecating ext/mysql).

And the later PHP developer team has taken the decision to generate E_DEPRECATED errors when users connect to MySQL, whether through mysql_connect(), mysql_pconnect() or the implicit connection functionality built into ext/mysql.

ext/mysql was officially deprecated as of PHP 5.5 and has been removed as of PHP 7.

When you go on any mysql_* function manual page, you see a red box, explaining it should not be used anymore.

Moving away from ext/mysql is not only about security, but also about having access to all the features of the MySQL database.

ext/mysql was built for MySQL 3.23 and only got very few additions since then while mostly keeping compatibility with this old version which makes the code a bit harder to maintain. Missing features that is not supported by ext/mysql include: (from PHP manual).

mysql_*
  • Removed as of PHP 7
  • Doesn't support prepared statements or parameterized queries
  • Doesn't support all of the functionality in MySQL 5.1

Lack of support for prepared statements is particularly important as they provide a clearer, less error prone method of escaping and quoting external data than manually escaping it with a separate function call.

MySQLi
PDO
E_DEPRECATED
error_reporting
E_DEPRECATED:
error_reporting = E_ALL ^ E_DEPRECATED

Note that this will also hide other deprecation warnings, which, however, may be for things other than MySQL. (from PHP manual)

The article PDO vs. MySQLi: Which Should You Use? by Dejan Marjanovic will help you to choose.

And a better way is PDO, and I am now writing a simple PDO tutorial.

A. PDO PHP Data Objects is a database access layer providing a uniform method of access to multiple databases.

With mysql_* function or we can say it the old way (deprecated in PHP 5.5 and above)

$link = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('testdb', $link);
mysql_set_charset('UTF-8', $link);

With PDO: All you need to do is create a new PDO object. The constructor accepts parameters for specifying the database source PDO's constructor mostly takes four parameters which are DSN (data source name) and optionally username, password.

Here I think you are familiar with all except DSN; this is new in PDO. A DSN is basically a string of options that tell PDO which driver to use, and connection details. For further reference, check PDO MySQL DSN.

$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');

Note: you can also use charset=UTF-8, but sometimes it causes an error, so it's better to use utf8.

If there is any connection error, it will throw a PDOException object that can be cached to handle Exception further.

You can also pass in several driver options as an array to the fourth parameter. I recommend passing the parameter which puts PDO into exception mode. Because some PDO drivers don't support native prepared statements, so PDO performs emulation of the prepare. It also lets you manually enable this emulation. To use the native server-side prepared statements, you should explicitly set it false.

The other is to turn off prepare emulation which is enabled in the MySQL driver by default, but prepare emulation should be turned off to use PDO safely.

I will later explain why prepare emulation should be turned off. To find reason please check this post.

It is only usable if you are using an old version of MySQL which I do not recommended.

Below is an example of how you can do it:

Yes, we can also set some attributes after PDO construction with the setAttribute method:

$db = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF-8', 
              'username', 
              'password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Error handling is much easier in PDO than mysql_*.

A common practice when using mysql_* is:

//Connected to MySQL
$result = mysql_query("SELECT * FROM table", $link) or die(mysql_error($link));

OR die() is not a good way to handle the error since we can not handle the thing in die. It will just end the script abruptly and then echo the error to the screen which you usually do NOT want to show to your end users, and let bloody hackers discover your schema. Alternately, the return values of mysql_* functions can often be used in conjunction with mysql_error() to handle errors.

PDO offers a better solution: exceptions. Anything we do with PDO should be wrapped in a try-catch block. We can force PDO into one of three error modes by setting the error mode attribute. Three error handling modes are below.

  • PDO::ERRMODE_SILENT. It's just setting error codes and acts pretty much the same as mysql_* where you must check each result and then look at $db->errorInfo(); to get the error details.
  • PDO::ERRMODE_WARNING Raise E_WARNING. (Run-time warnings (non-fatal errors). Execution of the script is not halted.)
  • PDO::ERRMODE_EXCEPTION: Throw exceptions. It represents an error raised by PDO. You should not throw a PDOException from your own code. See Exceptions for more information about exceptions in PHP. It acts very much like or die(mysql_error());, when it isn't caught. But unlike or die(), the PDOException can be caught and handled gracefully if you choose to do so.
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

And you can wrap it in try-catch, like below:

try {
    //Connect as appropriate as above
    $db->query('hi'); //Invalid query!
} 
catch (PDOException $ex) {
    echo "An Error occured!"; //User friendly message/message you want to show to user
    some_logging_function($ex->getMessage());
}

You do not have to handle with try-catch right now. You can catch it at any time appropriate, but I strongly recommend you to use try-catch. Also it may make more sense to catch it at outside the function that calls the PDO stuff:

function data_fun($db) {
    $stmt = $db->query("SELECT * FROM table");
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

//Then later
try {
    data_fun($db);
}
catch(PDOException $ex) {
    //Here you can handle error and show message/perform action you want.
}

Also, you can handle by or die() or we can say like mysql_*, but it will be really varied. You can hide the dangerous error messages in production by turning display_errors off and just reading your error log.

Now, after reading all the things above, you are probably thinking: what the heck is that when I just want to start leaning simple SELECT, INSERT, UPDATE, or DELETE statements? Don't worry, here we go:

So what you are doing in mysql_* is:

<?php
$result = mysql_query('SELECT * from table') or die(mysql_error());

$num_rows = mysql_num_rows($result);

while($row = mysql_fetch_assoc($result)) {
    echo $row['field1'];
}

Now in PDO, you can do this like:

Note: If you are using the method like below (query()), this method returns a PDOStatement object. So if you want to fetch the result, use it like above.

<?php
foreach($db->query('SELECT * FROM table') as $row) {
    echo $row['field1'];
}

In PDO Data, it is obtained via the ->fetch(), a method of your statement handle. Before calling fetch, the best approach would be telling PDO how youd like the data to be fetched. In the below section I am explaining this.

Note the use of PDO::FETCH_ASSOC in the fetch() and fetchAll() code above. This tells PDO to return the rows as an associative array with the field names as keys. There are many other fetch modes too which I will explain one by one.

$stmt->fetch(PDO::FETCH_ASSOC)

In the above, I have been using fetch(). You can also use:

  • PDOStatement::fetchAll() - Returns an array containing all of the result set rows
  • PDOStatement::fetchColumn() - Returns a single column from the next row of a result set
  • PDOStatement::fetchObject() - Fetches the next row and returns it as an object.
  • PDOStatement::setFetchMode() - Set the default fetch mode for this statement
  • PDO::FETCH_ASSOC: returns an array indexed by column name as returned in your result set
  • PDO::FETCH_BOTH (default): returns an array indexed by both column name and 0-indexed column number as returned in your result set
PDOStatement

Instead of using mysql_num_rows to get the number of returned rows, you can get a PDOStatement and do rowCount(), like:

<?php
$stmt = $db->query('SELECT * FROM table');
$row_count = $stmt->rowCount();
echo $row_count.' rows selected';

Getting the Last Inserted ID

<?php
$result = $db->exec("INSERT INTO table(firstname, lastname) VAULES('John', 'Doe')");
$insertId = $db->lastInsertId();

What we are doing in mysql_* function is:

<?php
$results = mysql_query("UPDATE table SET field='value'") or die(mysql_error());
echo mysql_affected_rows($result);

And in pdo, this same thing can be done by:

<?php
$affected_rows = $db->exec("UPDATE table SET field='value'");
echo $affected_rows;

In the above query PDO::exec execute an SQL statement and returns the number of affected rows.

The above method is only useful when you are not using variable in query. But when you need to use a variable in a query, do not ever ever try like the above and there for prepared statement or parameterized statement is.

Q. What is a prepared statement and why do I need them?A. A prepared statement is a pre-compiled SQL statement that can be executed multiple times by sending only the data to the server.

The typical workflow of using a prepared statement is as follows (quoted from Wikipedia three 3 point):

Prepare: The statement template is created by the application and sent to the database management system (DBMS). Certain values are left unspecified, called parameters, placeholders or bind variables (labelled ? below):

INSERT INTO PRODUCT (name, price) VALUES (?, ?)

The DBMS parses, compiles, and performs query optimization on the statement template, and stores the result without executing it.

  • Execute: At a later time, the application supplies (or binds) values for the parameters, and the DBMS executes the statement (possibly returning a result). The application may execute the statement as many times as it wants with different values. In this example, it might supply 'Bread' for the first parameter and 1.00 for the second parameter.

You can use a prepared statement by including placeholders in your SQL. There are basically three ones without placeholders (don't try this with variable its above one), one with unnamed placeholders, and one with named placeholders.

Q. So now, what are named placeholders and how do I use them?A. Named placeholders. Use descriptive names preceded by a colon, instead of question marks. We don't care about position/order of value in name place holder:

$stmt->bindParam(':bla', $bla);
bindParam(parameter,variable,data_type,length,driver_options)

You can also bind using an execute array as well:

<?php
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

Another nice feature for OOP friends is that named placeholders have the ability to insert objects directly into your database, assuming the properties match the named fields. For example:

class person {
    public $name;
    public $add;
    function __construct($a,$b) {
        $this->name = $a;
        $this->add = $b;
    }

}
$demo = new person('john','29 bla district');
$stmt = $db->prepare("INSERT INTO table (name, add) value (:name, :add)");
$stmt->execute((array)$demo);

Q. So now, what are unnamed placeholders and how do I use them?A. Let's have an example:

<?php
$stmt = $db->prepare("INSERT INTO folks (name, add) values (?, ?)");
$stmt->bindValue(1, $name, PDO::PARAM_STR);
$stmt->bindValue(2, $add, PDO::PARAM_STR);
$stmt->execute();

and

In the above, you can see those ? instead of a name like in a name place holder. Now in the first example, we assign variables to the various placeholders ($stmt->bindValue(1, $name, PDO::PARAM_STR);). Then, we assign values to those placeholders and execute the statement. In the second example, the first array element goes to the first ? and the second to the second ?.

NOTE: In unnamed placeholders we must take care of the proper order of the elements in the array that we are passing to the PDOStatement::execute() method.

SELECT
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
INSERT
$stmt = $db->prepare("INSERT INTO table(field1,field2) VALUES(:field1,:field2)");
$stmt->execute(array(':field1' => $field1, ':field2' => $field2));
$affected_rows = $stmt->rowCount();
DELETE
$stmt = $db->prepare("DELETE FROM table WHERE id=:id");
$stmt->bindValue(':id', $id, PDO::PARAM_STR);
$stmt->execute();
$affected_rows = $stmt->rowCount();
UPDATE
$stmt = $db->prepare("UPDATE table SET name=? WHERE id=?");
$stmt->execute(array($name, $id));
$affected_rows = $stmt->rowCount();

However PDO and/or MySQLi are not completely safe. Check the answer Are PDO prepared statements sufficient to prevent SQL injection? by ircmaxell. Also, I am quoting some part from his answer:

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->query('SET NAMES GBK');
$stmt = $pdo->prepare("SELECT * FROM test WHERE name = ? LIMIT 1");
$stmt->execute(array(chr(0xbf) . chr(0x27) . " OR 1=1 /*"));

What the good read above should propably mention: prepared statement take away any meaningful use of the IN (...) construct.

Just out of curiosity, is there some reason that MySQL/PHP developers couldn't have extended the MySQL library, updating the code behind existing functions and adding new function (including OO), all the while maintaining upward compatibility? Was that simply impossible to do cleanly, or they didn't want to bother? There's something to be said for maintaining upward compatibility, so existing applications don't break.

@Amine, No, it is not! :] While NullPoite really did a great job of writing it, this is most certainly isn't a good reading, because it is way to long. I'm pretty sure, that 8 of 10 visitors will simply skip it. And you also have explanation, why this answer isn't top voted. A tl;dr part in the beginning would be a good idea, I think.

@NullPoite As I said, your answer is great (no doubt about that!) and 405 score does reflect this. However, it is way to long. I only expressed my personal thinking and how I do understand, why other answer has more point than yours. Both answers are great, yours in only quite very long! :]

The question was "Why shouldnt I use mysql_* functions in PHP". This answer, while impressive and full of helpful information, goes WAY out of scope and like @trejder says - 8 out of 10 people are going to miss out on that information simply because they don't have 4 hours to spend trying to work through it. This would be far more valuable broken up and used as answers to several, more precise, questions.

mysql - Why shouldn't I use mysql_* functions in PHP? - Stack Overflow

php mysql database
Rectangle 27 1052

A simple and short PDO tutorial

PHP offers three different APIs to connect to MySQL. These are the mysql(removed as of PHP 7), mysqli, and PDO extensions.

The mysql_* functions used to be very popular, but their use is not encouraged anymore. The documentation team is discussing the database security situation, and educating users to move away from the commonly used ext/mysql extension is part of this (check php.internals: deprecating ext/mysql).

And the later PHP developer team has taken the decision to generate E_DEPRECATED errors when users connect to MySQL, whether through mysql_connect(), mysql_pconnect() or the implicit connection functionality built into ext/mysql.

ext/mysql was officially deprecated as of PHP 5.5 and has been removed as of PHP 7.

When you go on any mysql_* function manual page, you see a red box, explaining it should not be used anymore.

Moving away from ext/mysql is not only about security, but also about having access to all the features of the MySQL database.

ext/mysql was built for MySQL 3.23 and only got very few additions since then while mostly keeping compatibility with this old version which makes the code a bit harder to maintain. Missing features that is not supported by ext/mysql include: (from PHP manual).

mysql_*
  • Removed as of PHP 7
  • Doesn't support prepared statements or parameterized queries
  • Doesn't support all of the functionality in MySQL 5.1

Lack of support for prepared statements is particularly important as they provide a clearer, less error prone method of escaping and quoting external data than manually escaping it with a separate function call.

MySQLi
PDO
E_DEPRECATED
error_reporting
E_DEPRECATED:
error_reporting = E_ALL ^ E_DEPRECATED

Note that this will also hide other deprecation warnings, which, however, may be for things other than MySQL. (from PHP manual)

The article PDO vs. MySQLi: Which Should You Use? by Dejan Marjanovic will help you to choose.

And a better way is PDO, and I am now writing a simple PDO tutorial.

A. PDO PHP Data Objects is a database access layer providing a uniform method of access to multiple databases.

With mysql_* function or we can say it the old way (deprecated in PHP 5.5 and above)

$link = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('testdb', $link);
mysql_set_charset('UTF-8', $link);

With PDO: All you need to do is create a new PDO object. The constructor accepts parameters for specifying the database source PDO's constructor mostly takes four parameters which are DSN (data source name) and optionally username, password.

Here I think you are familiar with all except DSN; this is new in PDO. A DSN is basically a string of options that tell PDO which driver to use, and connection details. For further reference, check PDO MySQL DSN.

$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');

Note: you can also use charset=UTF-8, but sometimes it causes an error, so it's better to use utf8.

If there is any connection error, it will throw a PDOException object that can be cached to handle Exception further.

You can also pass in several driver options as an array to the fourth parameter. I recommend passing the parameter which puts PDO into exception mode. Because some PDO drivers don't support native prepared statements, so PDO performs emulation of the prepare. It also lets you manually enable this emulation. To use the native server-side prepared statements, you should explicitly set it false.

The other is to turn off prepare emulation which is enabled in the MySQL driver by default, but prepare emulation should be turned off to use PDO safely.

I will later explain why prepare emulation should be turned off. To find reason please check this post.

It is only usable if you are using an old version of MySQL which I do not recommended.

Below is an example of how you can do it:

Yes, we can also set some attributes after PDO construction with the setAttribute method:

$db = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF-8', 
              'username', 
              'password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Error handling is much easier in PDO than mysql_*.

A common practice when using mysql_* is:

//Connected to MySQL
$result = mysql_query("SELECT * FROM table", $link) or die(mysql_error($link));

OR die() is not a good way to handle the error since we can not handle the thing in die. It will just end the script abruptly and then echo the error to the screen which you usually do NOT want to show to your end users, and let bloody hackers discover your schema. Alternately, the return values of mysql_* functions can often be used in conjunction with mysql_error() to handle errors.

PDO offers a better solution: exceptions. Anything we do with PDO should be wrapped in a try-catch block. We can force PDO into one of three error modes by setting the error mode attribute. Three error handling modes are below.

  • PDO::ERRMODE_SILENT. It's just setting error codes and acts pretty much the same as mysql_* where you must check each result and then look at $db->errorInfo(); to get the error details.
  • PDO::ERRMODE_WARNING Raise E_WARNING. (Run-time warnings (non-fatal errors). Execution of the script is not halted.)
  • PDO::ERRMODE_EXCEPTION: Throw exceptions. It represents an error raised by PDO. You should not throw a PDOException from your own code. See Exceptions for more information about exceptions in PHP. It acts very much like or die(mysql_error());, when it isn't caught. But unlike or die(), the PDOException can be caught and handled gracefully if you choose to do so.
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

And you can wrap it in try-catch, like below:

try {
    //Connect as appropriate as above
    $db->query('hi'); //Invalid query!
} 
catch (PDOException $ex) {
    echo "An Error occured!"; //User friendly message/message you want to show to user
    some_logging_function($ex->getMessage());
}

You do not have to handle with try-catch right now. You can catch it at any time appropriate, but I strongly recommend you to use try-catch. Also it may make more sense to catch it at outside the function that calls the PDO stuff:

function data_fun($db) {
    $stmt = $db->query("SELECT * FROM table");
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

//Then later
try {
    data_fun($db);
}
catch(PDOException $ex) {
    //Here you can handle error and show message/perform action you want.
}

Also, you can handle by or die() or we can say like mysql_*, but it will be really varied. You can hide the dangerous error messages in production by turning display_errors off and just reading your error log.

Now, after reading all the things above, you are probably thinking: what the heck is that when I just want to start leaning simple SELECT, INSERT, UPDATE, or DELETE statements? Don't worry, here we go:

So what you are doing in mysql_* is:

<?php
$result = mysql_query('SELECT * from table') or die(mysql_error());

$num_rows = mysql_num_rows($result);

while($row = mysql_fetch_assoc($result)) {
    echo $row['field1'];
}

Now in PDO, you can do this like:

Note: If you are using the method like below (query()), this method returns a PDOStatement object. So if you want to fetch the result, use it like above.

<?php
foreach($db->query('SELECT * FROM table') as $row) {
    echo $row['field1'];
}

In PDO Data, it is obtained via the ->fetch(), a method of your statement handle. Before calling fetch, the best approach would be telling PDO how youd like the data to be fetched. In the below section I am explaining this.

Note the use of PDO::FETCH_ASSOC in the fetch() and fetchAll() code above. This tells PDO to return the rows as an associative array with the field names as keys. There are many other fetch modes too which I will explain one by one.

$stmt->fetch(PDO::FETCH_ASSOC)

In the above, I have been using fetch(). You can also use:

  • PDOStatement::fetchAll() - Returns an array containing all of the result set rows
  • PDOStatement::fetchColumn() - Returns a single column from the next row of a result set
  • PDOStatement::fetchObject() - Fetches the next row and returns it as an object.
  • PDOStatement::setFetchMode() - Set the default fetch mode for this statement
  • PDO::FETCH_ASSOC: returns an array indexed by column name as returned in your result set
  • PDO::FETCH_BOTH (default): returns an array indexed by both column name and 0-indexed column number as returned in your result set
PDOStatement

Instead of using mysql_num_rows to get the number of returned rows, you can get a PDOStatement and do rowCount(), like:

<?php
$stmt = $db->query('SELECT * FROM table');
$row_count = $stmt->rowCount();
echo $row_count.' rows selected';

Getting the Last Inserted ID

<?php
$result = $db->exec("INSERT INTO table(firstname, lastname) VAULES('John', 'Doe')");
$insertId = $db->lastInsertId();

What we are doing in mysql_* function is:

<?php
$results = mysql_query("UPDATE table SET field='value'") or die(mysql_error());
echo mysql_affected_rows($result);

And in pdo, this same thing can be done by:

<?php
$affected_rows = $db->exec("UPDATE table SET field='value'");
echo $affected_rows;

In the above query PDO::exec execute an SQL statement and returns the number of affected rows.

The above method is only useful when you are not using variable in query. But when you need to use a variable in a query, do not ever ever try like the above and there for prepared statement or parameterized statement is.

Q. What is a prepared statement and why do I need them?A. A prepared statement is a pre-compiled SQL statement that can be executed multiple times by sending only the data to the server.

The typical workflow of using a prepared statement is as follows (quoted from Wikipedia three 3 point):

Prepare: The statement template is created by the application and sent to the database management system (DBMS). Certain values are left unspecified, called parameters, placeholders or bind variables (labelled ? below):

INSERT INTO PRODUCT (name, price) VALUES (?, ?)

The DBMS parses, compiles, and performs query optimization on the statement template, and stores the result without executing it.

  • Execute: At a later time, the application supplies (or binds) values for the parameters, and the DBMS executes the statement (possibly returning a result). The application may execute the statement as many times as it wants with different values. In this example, it might supply 'Bread' for the first parameter and 1.00 for the second parameter.

You can use a prepared statement by including placeholders in your SQL. There are basically three ones without placeholders (don't try this with variable its above one), one with unnamed placeholders, and one with named placeholders.

Q. So now, what are named placeholders and how do I use them?A. Named placeholders. Use descriptive names preceded by a colon, instead of question marks. We don't care about position/order of value in name place holder:

$stmt->bindParam(':bla', $bla);
bindParam(parameter,variable,data_type,length,driver_options)

You can also bind using an execute array as well:

<?php
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

Another nice feature for OOP friends is that named placeholders have the ability to insert objects directly into your database, assuming the properties match the named fields. For example:

class person {
    public $name;
    public $add;
    function __construct($a,$b) {
        $this->name = $a;
        $this->add = $b;
    }

}
$demo = new person('john','29 bla district');
$stmt = $db->prepare("INSERT INTO table (name, add) value (:name, :add)");
$stmt->execute((array)$demo);

Q. So now, what are unnamed placeholders and how do I use them?A. Let's have an example:

<?php
$stmt = $db->prepare("INSERT INTO folks (name, add) values (?, ?)");
$stmt->bindValue(1, $name, PDO::PARAM_STR);
$stmt->bindValue(2, $add, PDO::PARAM_STR);
$stmt->execute();

and

In the above, you can see those ? instead of a name like in a name place holder. Now in the first example, we assign variables to the various placeholders ($stmt->bindValue(1, $name, PDO::PARAM_STR);). Then, we assign values to those placeholders and execute the statement. In the second example, the first array element goes to the first ? and the second to the second ?.

NOTE: In unnamed placeholders we must take care of the proper order of the elements in the array that we are passing to the PDOStatement::execute() method.

SELECT
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
INSERT
$stmt = $db->prepare("INSERT INTO table(field1,field2) VALUES(:field1,:field2)");
$stmt->execute(array(':field1' => $field1, ':field2' => $field2));
$affected_rows = $stmt->rowCount();
DELETE
$stmt = $db->prepare("DELETE FROM table WHERE id=:id");
$stmt->bindValue(':id', $id, PDO::PARAM_STR);
$stmt->execute();
$affected_rows = $stmt->rowCount();
UPDATE
$stmt = $db->prepare("UPDATE table SET name=? WHERE id=?");
$stmt->execute(array($name, $id));
$affected_rows = $stmt->rowCount();

However PDO and/or MySQLi are not completely safe. Check the answer Are PDO prepared statements sufficient to prevent SQL injection? by ircmaxell. Also, I am quoting some part from his answer:

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->query('SET NAMES GBK');
$stmt = $pdo->prepare("SELECT * FROM test WHERE name = ? LIMIT 1");
$stmt->execute(array(chr(0xbf) . chr(0x27) . " OR 1=1 /*"));

What the good read above should propably mention: prepared statement take away any meaningful use of the IN (...) construct.

Just out of curiosity, is there some reason that MySQL/PHP developers couldn't have extended the MySQL library, updating the code behind existing functions and adding new function (including OO), all the while maintaining upward compatibility? Was that simply impossible to do cleanly, or they didn't want to bother? There's something to be said for maintaining upward compatibility, so existing applications don't break.

@Amine, No, it is not! :] While NullPoite really did a great job of writing it, this is most certainly isn't a good reading, because it is way to long. I'm pretty sure, that 8 of 10 visitors will simply skip it. And you also have explanation, why this answer isn't top voted. A tl;dr part in the beginning would be a good idea, I think.

@NullPoite As I said, your answer is great (no doubt about that!) and 405 score does reflect this. However, it is way to long. I only expressed my personal thinking and how I do understand, why other answer has more point than yours. Both answers are great, yours in only quite very long! :]

The question was "Why shouldnt I use mysql_* functions in PHP". This answer, while impressive and full of helpful information, goes WAY out of scope and like @trejder says - 8 out of 10 people are going to miss out on that information simply because they don't have 4 hours to spend trying to work through it. This would be far more valuable broken up and used as answers to several, more precise, questions.

mysql - Why shouldn't I use mysql_* functions in PHP? - Stack Overflow

php mysql database
Rectangle 27 1050

A simple and short PDO tutorial

PHP offers three different APIs to connect to MySQL. These are the mysql(removed as of PHP 7), mysqli, and PDO extensions.

The mysql_* functions used to be very popular, but their use is not encouraged anymore. The documentation team is discussing the database security situation, and educating users to move away from the commonly used ext/mysql extension is part of this (check php.internals: deprecating ext/mysql).

And the later PHP developer team has taken the decision to generate E_DEPRECATED errors when users connect to MySQL, whether through mysql_connect(), mysql_pconnect() or the implicit connection functionality built into ext/mysql.

ext/mysql was officially deprecated as of PHP 5.5 and has been removed as of PHP 7.

When you go on any mysql_* function manual page, you see a red box, explaining it should not be used anymore.

Moving away from ext/mysql is not only about security, but also about having access to all the features of the MySQL database.

ext/mysql was built for MySQL 3.23 and only got very few additions since then while mostly keeping compatibility with this old version which makes the code a bit harder to maintain. Missing features that is not supported by ext/mysql include: (from PHP manual).

mysql_*
  • Removed as of PHP 7
  • Doesn't support prepared statements or parameterized queries
  • Doesn't support all of the functionality in MySQL 5.1

Lack of support for prepared statements is particularly important as they provide a clearer, less error prone method of escaping and quoting external data than manually escaping it with a separate function call.

MySQLi
PDO
E_DEPRECATED
error_reporting
E_DEPRECATED:
error_reporting = E_ALL ^ E_DEPRECATED

Note that this will also hide other deprecation warnings, which, however, may be for things other than MySQL. (from PHP manual)

The article PDO vs. MySQLi: Which Should You Use? by Dejan Marjanovic will help you to choose.

And a better way is PDO, and I am now writing a simple PDO tutorial.

A. PDO PHP Data Objects is a database access layer providing a uniform method of access to multiple databases.

With mysql_* function or we can say it the old way (deprecated in PHP 5.5 and above)

$link = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('testdb', $link);
mysql_set_charset('UTF-8', $link);

With PDO: All you need to do is create a new PDO object. The constructor accepts parameters for specifying the database source PDO's constructor mostly takes four parameters which are DSN (data source name) and optionally username, password.

Here I think you are familiar with all except DSN; this is new in PDO. A DSN is basically a string of options that tell PDO which driver to use, and connection details. For further reference, check PDO MySQL DSN.

$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');

Note: you can also use charset=UTF-8, but sometimes it causes an error, so it's better to use utf8.

If there is any connection error, it will throw a PDOException object that can be cached to handle Exception further.

You can also pass in several driver options as an array to the fourth parameter. I recommend passing the parameter which puts PDO into exception mode. Because some PDO drivers don't support native prepared statements, so PDO performs emulation of the prepare. It also lets you manually enable this emulation. To use the native server-side prepared statements, you should explicitly set it false.

The other is to turn off prepare emulation which is enabled in the MySQL driver by default, but prepare emulation should be turned off to use PDO safely.

I will later explain why prepare emulation should be turned off. To find reason please check this post.

It is only usable if you are using an old version of MySQL which I do not recommended.

Below is an example of how you can do it:

Yes, we can also set some attributes after PDO construction with the setAttribute method:

$db = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF-8', 
              'username', 
              'password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Error handling is much easier in PDO than mysql_*.

A common practice when using mysql_* is:

//Connected to MySQL
$result = mysql_query("SELECT * FROM table", $link) or die(mysql_error($link));

OR die() is not a good way to handle the error since we can not handle the thing in die. It will just end the script abruptly and then echo the error to the screen which you usually do NOT want to show to your end users, and let bloody hackers discover your schema. Alternately, the return values of mysql_* functions can often be used in conjunction with mysql_error() to handle errors.

PDO offers a better solution: exceptions. Anything we do with PDO should be wrapped in a try-catch block. We can force PDO into one of three error modes by setting the error mode attribute. Three error handling modes are below.

  • PDO::ERRMODE_SILENT. It's just setting error codes and acts pretty much the same as mysql_* where you must check each result and then look at $db->errorInfo(); to get the error details.
  • PDO::ERRMODE_WARNING Raise E_WARNING. (Run-time warnings (non-fatal errors). Execution of the script is not halted.)
  • PDO::ERRMODE_EXCEPTION: Throw exceptions. It represents an error raised by PDO. You should not throw a PDOException from your own code. See Exceptions for more information about exceptions in PHP. It acts very much like or die(mysql_error());, when it isn't caught. But unlike or die(), the PDOException can be caught and handled gracefully if you choose to do so.
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

And you can wrap it in try-catch, like below:

try {
    //Connect as appropriate as above
    $db->query('hi'); //Invalid query!
} 
catch (PDOException $ex) {
    echo "An Error occured!"; //User friendly message/message you want to show to user
    some_logging_function($ex->getMessage());
}

You do not have to handle with try-catch right now. You can catch it at any time appropriate, but I strongly recommend you to use try-catch. Also it may make more sense to catch it at outside the function that calls the PDO stuff:

function data_fun($db) {
    $stmt = $db->query("SELECT * FROM table");
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

//Then later
try {
    data_fun($db);
}
catch(PDOException $ex) {
    //Here you can handle error and show message/perform action you want.
}

Also, you can handle by or die() or we can say like mysql_*, but it will be really varied. You can hide the dangerous error messages in production by turning display_errors off and just reading your error log.

Now, after reading all the things above, you are probably thinking: what the heck is that when I just want to start leaning simple SELECT, INSERT, UPDATE, or DELETE statements? Don't worry, here we go:

So what you are doing in mysql_* is:

<?php
$result = mysql_query('SELECT * from table') or die(mysql_error());

$num_rows = mysql_num_rows($result);

while($row = mysql_fetch_assoc($result)) {
    echo $row['field1'];
}

Now in PDO, you can do this like:

Note: If you are using the method like below (query()), this method returns a PDOStatement object. So if you want to fetch the result, use it like above.

<?php
foreach($db->query('SELECT * FROM table') as $row) {
    echo $row['field1'];
}

In PDO Data, it is obtained via the ->fetch(), a method of your statement handle. Before calling fetch, the best approach would be telling PDO how youd like the data to be fetched. In the below section I am explaining this.

Note the use of PDO::FETCH_ASSOC in the fetch() and fetchAll() code above. This tells PDO to return the rows as an associative array with the field names as keys. There are many other fetch modes too which I will explain one by one.

$stmt->fetch(PDO::FETCH_ASSOC)

In the above, I have been using fetch(). You can also use:

  • PDOStatement::fetchAll() - Returns an array containing all of the result set rows
  • PDOStatement::fetchColumn() - Returns a single column from the next row of a result set
  • PDOStatement::fetchObject() - Fetches the next row and returns it as an object.
  • PDOStatement::setFetchMode() - Set the default fetch mode for this statement
  • PDO::FETCH_ASSOC: returns an array indexed by column name as returned in your result set
  • PDO::FETCH_BOTH (default): returns an array indexed by both column name and 0-indexed column number as returned in your result set
PDOStatement

Instead of using mysql_num_rows to get the number of returned rows, you can get a PDOStatement and do rowCount(), like:

<?php
$stmt = $db->query('SELECT * FROM table');
$row_count = $stmt->rowCount();
echo $row_count.' rows selected';

Getting the Last Inserted ID

<?php
$result = $db->exec("INSERT INTO table(firstname, lastname) VAULES('John', 'Doe')");
$insertId = $db->lastInsertId();

What we are doing in mysql_* function is:

<?php
$results = mysql_query("UPDATE table SET field='value'") or die(mysql_error());
echo mysql_affected_rows($result);

And in pdo, this same thing can be done by:

<?php
$affected_rows = $db->exec("UPDATE table SET field='value'");
echo $affected_rows;

In the above query PDO::exec execute an SQL statement and returns the number of affected rows.

The above method is only useful when you are not using variable in query. But when you need to use a variable in a query, do not ever ever try like the above and there for prepared statement or parameterized statement is.

Q. What is a prepared statement and why do I need them?A. A prepared statement is a pre-compiled SQL statement that can be executed multiple times by sending only the data to the server.

The typical workflow of using a prepared statement is as follows (quoted from Wikipedia three 3 point):

Prepare: The statement template is created by the application and sent to the database management system (DBMS). Certain values are left unspecified, called parameters, placeholders or bind variables (labelled ? below):

INSERT INTO PRODUCT (name, price) VALUES (?, ?)

The DBMS parses, compiles, and performs query optimization on the statement template, and stores the result without executing it.

  • Execute: At a later time, the application supplies (or binds) values for the parameters, and the DBMS executes the statement (possibly returning a result). The application may execute the statement as many times as it wants with different values. In this example, it might supply 'Bread' for the first parameter and 1.00 for the second parameter.

You can use a prepared statement by including placeholders in your SQL. There are basically three ones without placeholders (don't try this with variable its above one), one with unnamed placeholders, and one with named placeholders.

Q. So now, what are named placeholders and how do I use them?A. Named placeholders. Use descriptive names preceded by a colon, instead of question marks. We don't care about position/order of value in name place holder:

$stmt->bindParam(':bla', $bla);
bindParam(parameter,variable,data_type,length,driver_options)

You can also bind using an execute array as well:

<?php
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

Another nice feature for OOP friends is that named placeholders have the ability to insert objects directly into your database, assuming the properties match the named fields. For example:

class person {
    public $name;
    public $add;
    function __construct($a,$b) {
        $this->name = $a;
        $this->add = $b;
    }

}
$demo = new person('john','29 bla district');
$stmt = $db->prepare("INSERT INTO table (name, add) value (:name, :add)");
$stmt->execute((array)$demo);

Q. So now, what are unnamed placeholders and how do I use them?A. Let's have an example:

<?php
$stmt = $db->prepare("INSERT INTO folks (name, add) values (?, ?)");
$stmt->bindValue(1, $name, PDO::PARAM_STR);
$stmt->bindValue(2, $add, PDO::PARAM_STR);
$stmt->execute();

and

In the above, you can see those ? instead of a name like in a name place holder. Now in the first example, we assign variables to the various placeholders ($stmt->bindValue(1, $name, PDO::PARAM_STR);). Then, we assign values to those placeholders and execute the statement. In the second example, the first array element goes to the first ? and the second to the second ?.

NOTE: In unnamed placeholders we must take care of the proper order of the elements in the array that we are passing to the PDOStatement::execute() method.

SELECT
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
INSERT
$stmt = $db->prepare("INSERT INTO table(field1,field2) VALUES(:field1,:field2)");
$stmt->execute(array(':field1' => $field1, ':field2' => $field2));
$affected_rows = $stmt->rowCount();
DELETE
$stmt = $db->prepare("DELETE FROM table WHERE id=:id");
$stmt->bindValue(':id', $id, PDO::PARAM_STR);
$stmt->execute();
$affected_rows = $stmt->rowCount();
UPDATE
$stmt = $db->prepare("UPDATE table SET name=? WHERE id=?");
$stmt->execute(array($name, $id));
$affected_rows = $stmt->rowCount();

However PDO and/or MySQLi are not completely safe. Check the answer Are PDO prepared statements sufficient to prevent SQL injection? by ircmaxell. Also, I am quoting some part from his answer:

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->query('SET NAMES GBK');
$stmt = $pdo->prepare("SELECT * FROM test WHERE name = ? LIMIT 1");
$stmt->execute(array(chr(0xbf) . chr(0x27) . " OR 1=1 /*"));

What the good read above should propably mention: prepared statement take away any meaningful use of the IN (...) construct.

Just out of curiosity, is there some reason that MySQL/PHP developers couldn't have extended the MySQL library, updating the code behind existing functions and adding new function (including OO), all the while maintaining upward compatibility? Was that simply impossible to do cleanly, or they didn't want to bother? There's something to be said for maintaining upward compatibility, so existing applications don't break.

@Amine, No, it is not! :] While NullPoite really did a great job of writing it, this is most certainly isn't a good reading, because it is way to long. I'm pretty sure, that 8 of 10 visitors will simply skip it. And you also have explanation, why this answer isn't top voted. A tl;dr part in the beginning would be a good idea, I think.

@NullPoite As I said, your answer is great (no doubt about that!) and 405 score does reflect this. However, it is way to long. I only expressed my personal thinking and how I do understand, why other answer has more point than yours. Both answers are great, yours in only quite very long! :]

The question was "Why shouldnt I use mysql_* functions in PHP". This answer, while impressive and full of helpful information, goes WAY out of scope and like @trejder says - 8 out of 10 people are going to miss out on that information simply because they don't have 4 hours to spend trying to work through it. This would be far more valuable broken up and used as answers to several, more precise, questions.

mysql - Why shouldn't I use mysql_* functions in PHP? - Stack Overflow

php mysql database
Rectangle 27 2

Another thing to check, which happened to be my solution (found here), is how data is being returned from your server. In my application, I'm using PDO to connect from PHP to MySQL. I needed to add a flag to the connection which said get the data back in UTF-8 format

$dbHandle = new PDO("mysql:host=$dbHost;dbname=$dbName;charset=utf8", $dbUser, $dbPass, 
    array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"));

php - Fixing Broken UTF8 encoding - Stack Overflow

php mysql unicode utf-8
Rectangle 27 16

PDO is the "PHP Data Object." I mostly use PDO, so I can only speak on its merits:

  • Works for many more databases than just MySQL (may not matter to you)
  • Prepared statements (others have these, though)
  • SO seems to like it, so you can probably get a lot of help here at least
  • Various fetch/error handling modes you can set and change on the fly

So what is the difference between PDO, prepared statements and MySQLi ...

PDO and MySQLi are DB wrappers. "Prepared statements" is a different concept altogether. You can prepare a query that can be executed multiple times, and properly parameterized statements are SQL-Injection safe (though maybe not proof). The latter reason is most of the reason why you should be using PDO (or MySQLi), but prepared statements also bring a level of clarity to the queries.

/* mysql_* version */
mysql_connect("host");
$query = "SELECT column FROM db1.t1 WHERE id = ";
foreach ($_GET['id'] as $id) {
   $id = mysql_real_escape_string($id);
   $result = mysql_query($query . "'$id'";
   while ($row = mysql_fetch_assoc($result)) {
      echo "$row[column]\n";
   }
}
//NOTE: it would probably be better to store the resource returned by
//mysql_connect and use that consistently (in query/escape)

/* PDO version */
$pdo = new PDO('mysql:host=HOST', 'user', 'pass');
$query = $pdo->prepare("SELECT column FROM db1.t1 WHERE id = ?";
foreach ($_GET['id'] as $id) {
   $query->execute($id);
   echo $query->fetch(PDO::FETCH_COLUMN);
}
//Notice that you skip the escape step.

You can do essentially the same with MySQLi, but I prefer PDO's syntax. It may be faster too, but I could be making that up. There's also the PEAR MDB2 that rarely gets spoken of, and I'm sure many more. Since PDO is built in, I would go with it.

This source states that MySQL and MySQLi are a bit faster: code.tutsplus.com/tutorials/

You missed a closing bracket Explosion Pillis in your pdo prepare query statement.

mysql - PHP PDO and MySQLi - Stack Overflow

php mysql pdo mysqli
Rectangle 27 16

PDO is the "PHP Data Object." I mostly use PDO, so I can only speak on its merits:

  • Works for many more databases than just MySQL (may not matter to you)
  • Prepared statements (others have these, though)
  • SO seems to like it, so you can probably get a lot of help here at least
  • Various fetch/error handling modes you can set and change on the fly

So what is the difference between PDO, prepared statements and MySQLi ...

PDO and MySQLi are DB wrappers. "Prepared statements" is a different concept altogether. You can prepare a query that can be executed multiple times, and properly parameterized statements are SQL-Injection safe (though maybe not proof). The latter reason is most of the reason why you should be using PDO (or MySQLi), but prepared statements also bring a level of clarity to the queries.

/* mysql_* version */
mysql_connect("host");
$query = "SELECT column FROM db1.t1 WHERE id = ";
foreach ($_GET['id'] as $id) {
   $id = mysql_real_escape_string($id);
   $result = mysql_query($query . "'$id'";
   while ($row = mysql_fetch_assoc($result)) {
      echo "$row[column]\n";
   }
}
//NOTE: it would probably be better to store the resource returned by
//mysql_connect and use that consistently (in query/escape)

/* PDO version */
$pdo = new PDO('mysql:host=HOST', 'user', 'pass');
$query = $pdo->prepare("SELECT column FROM db1.t1 WHERE id = ?";
foreach ($_GET['id'] as $id) {
   $query->execute($id);
   echo $query->fetch(PDO::FETCH_COLUMN);
}
//Notice that you skip the escape step.

You can do essentially the same with MySQLi, but I prefer PDO's syntax. It may be faster too, but I could be making that up. There's also the PEAR MDB2 that rarely gets spoken of, and I'm sure many more. Since PDO is built in, I would go with it.

This source states that MySQL and MySQLi are a bit faster: code.tutsplus.com/tutorials/

You missed a closing bracket Explosion Pillis in your pdo prepare query statement.

mysql - PHP PDO and MySQLi - Stack Overflow

php mysql pdo mysqli
Rectangle 27 16

PDO is the "PHP Data Object." I mostly use PDO, so I can only speak on its merits:

  • Works for many more databases than just MySQL (may not matter to you)
  • Prepared statements (others have these, though)
  • SO seems to like it, so you can probably get a lot of help here at least
  • Various fetch/error handling modes you can set and change on the fly

So what is the difference between PDO, prepared statements and MySQLi ...

PDO and MySQLi are DB wrappers. "Prepared statements" is a different concept altogether. You can prepare a query that can be executed multiple times, and properly parameterized statements are SQL-Injection safe (though maybe not proof). The latter reason is most of the reason why you should be using PDO (or MySQLi), but prepared statements also bring a level of clarity to the queries.

/* mysql_* version */
mysql_connect("host");
$query = "SELECT column FROM db1.t1 WHERE id = ";
foreach ($_GET['id'] as $id) {
   $id = mysql_real_escape_string($id);
   $result = mysql_query($query . "'$id'";
   while ($row = mysql_fetch_assoc($result)) {
      echo "$row[column]\n";
   }
}
//NOTE: it would probably be better to store the resource returned by
//mysql_connect and use that consistently (in query/escape)

/* PDO version */
$pdo = new PDO('mysql:host=HOST', 'user', 'pass');
$query = $pdo->prepare("SELECT column FROM db1.t1 WHERE id = ?";
foreach ($_GET['id'] as $id) {
   $query->execute($id);
   echo $query->fetch(PDO::FETCH_COLUMN);
}
//Notice that you skip the escape step.

You can do essentially the same with MySQLi, but I prefer PDO's syntax. It may be faster too, but I could be making that up. There's also the PEAR MDB2 that rarely gets spoken of, and I'm sure many more. Since PDO is built in, I would go with it.

This source states that MySQL and MySQLi are a bit faster: code.tutsplus.com/tutorials/

You missed a closing bracket Explosion Pillis in your pdo prepare query statement.

mysql - PHP PDO and MySQLi - Stack Overflow

php mysql pdo mysqli
Rectangle 27 16

PDO is the "PHP Data Object." I mostly use PDO, so I can only speak on its merits:

  • Works for many more databases than just MySQL (may not matter to you)
  • Prepared statements (others have these, though)
  • SO seems to like it, so you can probably get a lot of help here at least
  • Various fetch/error handling modes you can set and change on the fly

So what is the difference between PDO, prepared statements and MySQLi ...

PDO and MySQLi are DB wrappers. "Prepared statements" is a different concept altogether. You can prepare a query that can be executed multiple times, and properly parameterized statements are SQL-Injection safe (though maybe not proof). The latter reason is most of the reason why you should be using PDO (or MySQLi), but prepared statements also bring a level of clarity to the queries.

/* mysql_* version */
mysql_connect("host");
$query = "SELECT column FROM db1.t1 WHERE id = ";
foreach ($_GET['id'] as $id) {
   $id = mysql_real_escape_string($id);
   $result = mysql_query($query . "'$id'";
   while ($row = mysql_fetch_assoc($result)) {
      echo "$row[column]\n";
   }
}
//NOTE: it would probably be better to store the resource returned by
//mysql_connect and use that consistently (in query/escape)

/* PDO version */
$pdo = new PDO('mysql:host=HOST', 'user', 'pass');
$query = $pdo->prepare("SELECT column FROM db1.t1 WHERE id = ?";
foreach ($_GET['id'] as $id) {
   $query->execute($id);
   echo $query->fetch(PDO::FETCH_COLUMN);
}
//Notice that you skip the escape step.

You can do essentially the same with MySQLi, but I prefer PDO's syntax. It may be faster too, but I could be making that up. There's also the PEAR MDB2 that rarely gets spoken of, and I'm sure many more. Since PDO is built in, I would go with it.

This source states that MySQL and MySQLi are a bit faster: code.tutsplus.com/tutorials/

You missed a closing bracket Explosion Pillis in your pdo prepare query statement.

mysql - PHP PDO and MySQLi - Stack Overflow

php mysql pdo mysqli
Rectangle 27 1

Using the old, deprecated, mysql extension:

If you run that command from PHP code, the LOAD DATA LOCAL INFILE command can be enabled on the connection to the MySQL server.

The exact procedure depends on the PHP extension used for communication with MySQL.

Put 128 into the parameter $flags of mysql_connect(), OR-ed, as usual, with other MYSQL_CLIENT_* flags you may need. The value 128 enables LOAD DATA LOCAL handling but there is no constant defined for it. Read the documentation page for mysql_connect().

// Put your connection parameters in $server, $username, $password as usual
$server   = '127.0.0.1';
$username = 'root';
$password = '****';
// Put 128 bitwise OR-ed with other flags, if needed
$flags = 128;
// ... and connect
$link = mysql_connect($server, $username, $password, $new_link, $flags);
mysqli_options()
MYSQLI_OPT_LOCAL_INFILE
TRUE
$link = mysqli_init();
mysqli_options($link, MYSQLI_OPT_LOCAL_INFILE, TRUE);
mysqli_real_connect($server, $username, $password);

As it is explained in the documentation, this is the correct way to use mysqli_options().

Set the option PDO::MYSQL_ATTR_LOCAL_INFILE to TRUE on $options parameter of the PDO constructor:

$options = array(
    PDO::MYSQL_ATTR_LOCAL_INFILE = TRUE;
);
$link = new PDO($dsn, $username, $password, $options);

Its a php script and im using mysql. @axiac I tried your solution for mysql exstension, but still geting same message. I cant see or change my.conf

I am using it since 2012 with Amazon RDS and it works fine.

php - mysql 5.1.73 load data local infile error - Stack Overflow

php mysql database
Rectangle 27 82

There are (more than) three popular ways to use MySQL from PHP.

  • (DEPRECATED) The mysql functions are procedural and use manual escaping.
  • MySQLi is a replacement for the mysql functions, with object-oriented and procedural versions. It has support for prepared statements.
  • PDO (PHP Data Objects) is a general database abstraction layer with support for MySQL among many other databases. It provides prepared statements, and significant flexibility in how data is returned.

I would recommend using PDO with prepared statements. It is a well-designed API and will let you more easily move to another database (including any that supports ODBC) if necessary.

There is often the confusion that for procedural you have to use mysql_*() functions where for OO you use mysqli! The fact is that mysqli completely replace the early (PHP 4) implementation of mysql. It is possible to use both the procedural style and the OO one with mysqli.

php - What is the difference between MySQL, MySQLi and PDO? - Stack Ov...

php mysql pdo mysqli
Rectangle 27 2

// database cobfigurations
$config= array(
    // first database
    array(
        'type'=>'mysql',                    // DB type
        'host'=>'localhost',                // DB host
        'dbname'=>'database1',      // DB name
        'user'=>'root',                 // DB username
        'pass'=>'12345',                // DB password
    ),
    // second database
    array(
        'type'=>'mysql',                    // DB type
        'host'=>'localhost',                // DB host
        'dbname'=>'database2',      // DB name
        'user'=>'root',                 // DB username
        'pass'=>'987654',               // DB password
    ),
);
// database connections
$mysql=array();
foreach($config as $con)
{
    $con=(object)$con;
    $start= new PDO($con->type.':host='.$con->host.';dbname='.$con->dbname.'', $con->user, $con->pass, array(
            // pdo setup
            PDO::ATTR_PERSISTENT            => FALSE,
            PDO::ATTR_DEFAULT_FETCH_MODE    => PDO::FETCH_OBJ,
            PDO::ATTR_ERRMODE               => PDO::ERRMODE_EXCEPTION,
            PDO::MYSQL_ATTR_INIT_COMMAND    => 'SET NAMES UTF8'
    ));

    if ($start && !empty($start) && !is_resource($start))
        $mysql[]=$start;    // connection is OK prepare objects
    else
        $mysql[]=false; // connection is NOT OK, return false
}

/**********************
 ****  HOW TO USE ****
**********************/ 

// fetch data from database 1
$data1 = $mysql[0]->query("SELECT id, title, text FROM content1")->fetchAll();
if(count($data1)>0)
{
    foreach($data1 as $i=>$result)
    {
        echo $result->id.' '.$result->title.' '.$result->text.'<br>'
    }
}

// fetch data from database 2
$data2 = $mysql[1]->query("SELECT id, title, text FROM content2")->fetchAll();
if(count($data2)>0)
{
    foreach($data2 as $i=>$result)
    {
        echo $result->id.' '.$result->title.' '.$result->text.'<br>'
    }
}

If you not use PDO before, please read this short tutorial:

Is practicly same like mysql and mysqli connections but is more advanced, fast and secure.

php - Pros and cons of connecting more than one database in single scr...

php mysql sql database database-connection
Rectangle 27 2

// database cobfigurations
$config= array(
    // first database
    array(
        'type'=>'mysql',                    // DB type
        'host'=>'localhost',                // DB host
        'dbname'=>'database1',      // DB name
        'user'=>'root',                 // DB username
        'pass'=>'12345',                // DB password
    ),
    // second database
    array(
        'type'=>'mysql',                    // DB type
        'host'=>'localhost',                // DB host
        'dbname'=>'database2',      // DB name
        'user'=>'root',                 // DB username
        'pass'=>'987654',               // DB password
    ),
);
// database connections
$mysql=array();
foreach($config as $con)
{
    $con=(object)$con;
    $start= new PDO($con->type.':host='.$con->host.';dbname='.$con->dbname.'', $con->user, $con->pass, array(
            // pdo setup
            PDO::ATTR_PERSISTENT            => FALSE,
            PDO::ATTR_DEFAULT_FETCH_MODE    => PDO::FETCH_OBJ,
            PDO::ATTR_ERRMODE               => PDO::ERRMODE_EXCEPTION,
            PDO::MYSQL_ATTR_INIT_COMMAND    => 'SET NAMES UTF8'
    ));

    if ($start && !empty($start) && !is_resource($start))
        $mysql[]=$start;    // connection is OK prepare objects
    else
        $mysql[]=false; // connection is NOT OK, return false
}

/**********************
 ****  HOW TO USE ****
**********************/ 

// fetch data from database 1
$data1 = $mysql[0]->query("SELECT id, title, text FROM content1")->fetchAll();
if(count($data1)>0)
{
    foreach($data1 as $i=>$result)
    {
        echo $result->id.' '.$result->title.' '.$result->text.'<br>'
    }
}

// fetch data from database 2
$data2 = $mysql[1]->query("SELECT id, title, text FROM content2")->fetchAll();
if(count($data2)>0)
{
    foreach($data2 as $i=>$result)
    {
        echo $result->id.' '.$result->title.' '.$result->text.'<br>'
    }
}

If you not use PDO before, please read this short tutorial:

Is practicly same like mysql and mysqli connections but is more advanced, fast and secure.

php - Pros and cons of connecting more than one database in single scr...

php mysql sql database database-connection
Rectangle 27 6

You can simply use MySQL's LOAD DATA INFILE command, which will be considerably faster than parsing the CSV into PHP, constructing an INSERT statement for every record, submitting it as a string to MySQL and having MySQL parse said string for SQL (at risk of SQL injection):

LOAD DATA INFILE ? INTO TABLE tictoc
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
IGNORE 1 LINES
(tasktime, sessiontime, sessionstart, sessionend, sessionnotes)
SET employee = ?, taskname = ?
$dbh = new PDO('mysql:dbname='.$dbname, $username, $password);

if (is_uploaded_file($_FILES['filename']['tmp_name'])) {
  $qry = $dbh->prepare('
    LOAD DATA INFILE :filepath INTO TABLE tictoc
    FIELDS TERMINATED BY \',\' OPTIONALLY ENCLOSED BY \'"\'
    IGNORE 1 LINES
    (tasktime, sessiontime, sessionstart, sessionend, sessionnotes)
    SET employee = :employee, taskname = :taskname
  ');

  $qry->execute(array(
    ':filepath' => $_FILES['filename']['tmp_name'],
    ':employee' => $userinfo['first_name'],
    ':taskname' => $userinfo['last_name']
  ));
}

@wlin: Use the LOCAL modifier.

php - Import CSV, exclude first row - Stack Overflow

php mysql csv import-from-excel
Rectangle 27 7

Use PDO (PHP Data Objects) to connect to your MySQL database. This method will make sure that all database input will always be treated as text strings and you will never have to do any manual escaping.

This combined with proper use of html_entities() to display data from your database is a solid and good way to protect your page from injection. I always use PDO to handle all my database connections in my projects.

Create database object (and in this case enforce a certain character encoding):

try {
    $db = new PDO("mysql:host=[hostname];dbname=[database]",'[username]','[password]');
    $db->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES utf8");
    $db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
    $db->exec('SET NAMES utf8');
} catch (PDOException $e) {
    echo $e->getMessage();
}
$id = 1;
$q = $db->prepare('SELECT * FROM Table WHERE id = ?');
$q->execute(array($id));
$row = $q->fetch();
echo $row['Column_1'];
$q = $db->prepare('UPDATE Table SET Column_1 = ?, Column_2 = ? WHERE id = ?');
$q->execute(array('Value for Column_1','Value for Column_2',$id));

and with wildcards:

$search = 'John';
$q = $db->prepare('SELECT * FROM Table WHERE Column_1 LIKE ?');
$q->execute(array('%'.$search.'%'));
$num = $q->rowCount();
if ($num > 0) {
  while ($row = $q->fetch()) {
    echo $row['Column_1'];
  }
} else {
  echo "No hits!";
}

php - MySQL Prepared Statements - Stack Overflow

php mysql sql-injection
Rectangle 27 7

Use PDO (PHP Data Objects) to connect to your MySQL database. This method will make sure that all database input will always be treated as text strings and you will never have to do any manual escaping.

This combined with proper use of html_entities() to display data from your database is a solid and good way to protect your page from injection. I always use PDO to handle all my database connections in my projects.

Create database object (and in this case enforce a certain character encoding):

try {
    $db = new PDO("mysql:host=[hostname];dbname=[database]",'[username]','[password]');
    $db->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES utf8");
    $db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
    $db->exec('SET NAMES utf8');
} catch (PDOException $e) {
    echo $e->getMessage();
}
$id = 1;
$q = $db->prepare('SELECT * FROM Table WHERE id = ?');
$q->execute(array($id));
$row = $q->fetch();
echo $row['Column_1'];
$q = $db->prepare('UPDATE Table SET Column_1 = ?, Column_2 = ? WHERE id = ?');
$q->execute(array('Value for Column_1','Value for Column_2',$id));

and with wildcards:

$search = 'John';
$q = $db->prepare('SELECT * FROM Table WHERE Column_1 LIKE ?');
$q->execute(array('%'.$search.'%'));
$num = $q->rowCount();
if ($num > 0) {
  while ($row = $q->fetch()) {
    echo $row['Column_1'];
  }
} else {
  echo "No hits!";
}

php - MySQL Prepared Statements - Stack Overflow

php mysql sql-injection