Saturday 13 July 2013

What is PHP PDO


PHP Data Object  has a much nicer interface, you will end up being more productive, and write safer and cleaner code. PDO also has different drivers for different SQL database vendors which will allow you to easily use other vendors without having to relearn a different interface. (though you will have to learn slightly different SQL probably). Instead of concatenating escaped strings into SQL, in PDO you bind parameters which is an easier and cleaner way of securing queries. Binding parameters also allow for a performance increase when calling the same SQL query many times with slightly different parameters. PDO also has multiple methods of error handling. The biggest issue I have seen with mysql_* code is that it lacks consistent handling, or no handling at all! With PDO in exception mode, you can get consistent error handling which will end up saving you loads of time tracking down issues.
Getting Connected.

$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); //to show any sql error

Error Handling

try {
    //connect as appropriate as above
    $db->query('hi'); //invalid query!
} catch(PDOException $ex) {
    echo "An Error occured!"; //user friendly message
    some_logging_function($ex->getMessage());
    $db->errorInfo(); to get the error details.
}

Select Query

$stmt = $db->query('SELECT * FROM table'); 
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) 
{
    echo $row['field1'].' '.$row['field2']; 
}

query() method returns a PDOStatement object. A Cursor Handler of that Table, need to use loop to retrieve data.
$stmt = $db->query('SELECT * FROM table');
 while($row = $stmt->fetch(PDO::FETCH_ASSOC))
 { 
 echo $row['field1'].' '.$row['field2']; 
}
 $stmt->fetch(PDO::FETCH_ASSOC)  will fetch single row as an associative Array, to fetch all records use fetchAll.
Row Count
$stmt = $db->query('SELECT * FROM table');
$row_count = $stmt->rowCount();
echo $row_count.' rows selected';
Last Insert ID
$result = $db->exec("INSERT INTO table(firstname, lastname) VAULES('John', 'Doe')");
$insertId = $db->lastInsertId();

SQL Prepare

$stmt = $db->prepare("SELECT * FROM table WHERE id=? AND name=?");
$stmt->bindValue(1, $id, PDO::PARAM_INT);
$stmt->bindValue(2, $name, PDO::PARAM_STR);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

The prepare method sends the query to the server, and it's compiled with the '?' placeholders to be used as expected arguments. The execute method sends the arguments to the server and runs the compiled statement. Since the query and the dynamic parameters are sent separately, there is no way that any SQL that is in those parameters can be executed... so NO SQL INJECTION can occur! This is a much better and safer solution than concatenating strings together.

$stmt = $db->prepare("SELECT * FROM table WHERE id=? AND name=?");
$stmt->bindValue(1, $id, PDO::PARAM_INT);
$stmt->bindValue(2, $name, PDO::PARAM_STR);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

Executing Prepared Statement in a Loop

$values = array('bob', 'alice', 'lisa', 'john');
$name = '';
$stmt = $db->prepare("INSERT INTO table(`name`) VALUES(:name)");
$stmt->bindParam(':name', $name, PDO::PARAM_STR);
foreach($values as $name) {
   $stmt->execute();
}

Transaction

try {
    $db->beginTransaction();

    $db->exec("SOME QUERY");

    $stmt = $db->prepare("SOME OTHER QUERY?");
    $stmt->execute(array($value));

    $stmt = $db->prepare("YET ANOTHER QUERY??");
    $stmt->execute(array($value2, $value3));

    $db->commit();
} catch(PDOException $ex) {
    //Something went wrong rollback!
    $db->rollBack();
    echo $ex->getMessage();
}

Monday 8 July 2013

To Find 2nd and 3rd highest Salary


SELECT sal FROM employee WHERE sal = (SELECT DISTINCT(sal) 
  FROM employee as e1   WHERE (n) = (SELECT COUNT(DISTINCT(sal)) 
  FROM employee as e2  WHERE e1.sal <= e2.sal))

change (n) by 1,2 or 3 or 4 to get second,third or fourth highest salary.

Thursday 25 April 2013

Store And Retrive Images Into MYSQL Using PDO

In this tutorial I’m going to show you how you can store and retrieve images from MySQL database. We use to store images into DB , so as to avoid all those complexity of storing in file system. But storing in database will consume more memory and retrieval is slow for bigger file.
I am using PHP PDO library to DB handle, so that large binary objects such as images can be properly handled.
Step -1  Connect To DB
$dsn = 'mysql:dbname=testbd;host=192.168.1.11';
$user = 'myuser';
$password = 'mypassword';
try {
    $dbh = new PDO($dsn, $user, $password);
    echo 'DB connected<br>';
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}
Step -2 Upload file
Upload an image file using HTML form upload and assign $_FILES into respective variables
$id=1;
$filetype = $_FILES['file']['type'];
$filePointer = fopen($_FILES['file']['tmp_name'], 'rb'); //rb - read , binary
Step-3  Database insertion
I am using late binding method of PDO to store data into imagefiles table where field file is of large BLOB type.
$dbh->beginTransaction(); //** PDO transcation starts
$stmt = $dbh->prepare("insert into imagefiles (id, filetype, file) values (?, ?, ?)");
$stmt->bindParam(1, $id);
$stmt->bindParam(2, $filetype);
$stmt->bindParam(3, $filePointer, PDO::PARAM_LOB);
$stmt->execute(); //** query gets executed
$dbh->commit(); //** commit the whole transcation
//PDO::PARAM_LOB is used to stream large binary objects
so at step 3 we are storing whole image file as binary data into file field of that table. As we bind variable $filePointer which contains file pointer to tmp location of the uploaded image, PDO will read that file using file pointer and store that into DB.

we write below code in php file getimage.php

Step -4 Retrieve Image
To retrieve that image i write a select query to fetch file from table imagesfiles.
$stmt = $dbh->prepare("select filetype,file FROM imagefiles where id='1' LIMIT 0,1");
$stmt->execute();
$stmt->bindColumn(1, $type, PDO::PARAM_STR, 256);
$stmt->bindColumn(2, $file, PDO::PARAM_LOB);
$stmt->fetch(PDO::FETCH_BOUND);
//print_r($file); 
//** will print full special characters on screen if data is image ie Binary Data, else if data is
//** Text it will display as it is
Binding a column from a result set to a variable using PDO::PARAM_LOB is supposed to return a stream resource into the variable when PDO::fetch() is called. This stream can then be operated on using any PHP function that handles files.Unfortunately there’s a bug which means that instead of returning a stream into $file PDO returns a string containing the binary data. When this is then passed to fpassthru() an error is triggered. Fortunately there’s a simple fix for displaying the image: replace the call to fpassthru() with echo or print. Since the browser is expecting an image after the call to header() writing the binary data. Using echo or print has the same effect as calling fpassthru(). In my code I’ve added the following just in case this bug is fixed in a future release:

Way - 1 To show image in webpage

if(is_string($file))
{
$file = imagecreatefromjpeg("data://image/jpeg;base64," . base64_encode($file));
}
//encode string data from DB result into stream data/binary image data using PHP wraper
//With Base64 encoding image data can be send inline ie in example 1 whole image data is 
// embeded in <img> tag ( normally src would do another HTTP request for image ) and 
//it wouldn’t require additional HTTP requests, just some extra millise-conds for sending 
//this data.
/*  Example -1
$img_src = "img/sample.jpg"; $imgbinary = fread(fopen($img_src, "r"), filesize($img_src)); $img_str = base64_encode($imgbinary); echo '<img src="data:image/jpeg;base64,'.$img_str.'" alt="Alt text" />';
*/
/* gif - data:image/gif;base64, ....

jpg - data:image/jpeg;base64, ....
png - data:image/png;base64, ...
*/

//** Method - (1) - To in image tag
ob_clean();   //Clean (erase) the output buffer
flush();   //Flush (send) the output buffer
header('Content-Type: image/jpeg');
imagejpeg($jpegimage);
exit();

Way -2 To show image in webpage
if(is_string($file))
{
//** Every Time control comes inside this if condition ****
//** our file is a string
$file = fopen('data://text/plain;base64,' . base64_encode($file), 'r');  //* Line A
//print_r($file); 
     //**  would print Resource id #3 ie a filepointer
    //**Line A - data: stream wrapper is used to encode the actual string in Base64
   //Base64 is an encoding format that represent binary data.
}
//we can use above code to convert string data into a stream first then continue accessing it as if it were a string.

The following the methods to show files in browser - image file is jpeg
//** Method - (2) - To in image tag
file_put_contents("/var/www/video/aa.jpeg",$file);
echo "<img src='http://localhost/video/aa.jpeg'>";

//**Method  - (3) 

//$file contain file pointer
 file_put_contents("/tmp/aa.jpeg",$file); //create a file at temporal location
 ob_clean(); 
 flush(); 
 // header('Content-Type: image/jpeg');
 readfile('/tmp/aa.jpeg'); //Reads a file and writes it to the output buffer.

//**Method  - (4) 

// for this, Line A should be first made commented, so as to have $file consist of binary image data as string, with PHP wraper
ob_clean(); 
 flush(); 
 header('Content-Type: image/jpeg');
 echo $file;
Both method 1,3 and 4 , we can view image using image Tag as follows.
<img src="localhost/myproject/getimage.php"  id="img1" alt="myimage" >


following is the table structure

CREATE TABLE IF NOT EXISTS `myimage` (
  `id` int(11) NOT NULL,
  `filetype` varchar(200) NOT NULL,
  `file` blob NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


File field is Blob, used to store binary data

Tuesday 23 April 2013

Handling Binary Data with PDO in PHP


We can handel binary data using PDO database access library in PHP 5 . In one project i am storing images in database as binary Data. PDO allows you to bind a file handle to a parameter in a prepared statement and when the statement is executed the contents of the file are slurped into the database. 
This works perfectly but the problem comes when getting the image out of the database again to display it. 
According to the PHP manual the following code should work:

$db = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2');
$stmt = $db->prepare("select contenttype, imagedata from images where id=?");
$stmt->execute(array($_GET['id']));
$stmt->bindColumn(1, $type, PDO::PARAM_STR, 256);
$stmt->bindColumn(2, $lob, PDO::PARAM_LOB);
$stmt->fetch(PDO::FETCH_BOUND);
header("Content-Type: $type");
fpassthru($lob);

Binding a column from a result set to a variable using PDO::PARAM_LOB is supposed to return a stream resource into the variable when PDO::fetch() is called. This stream can then be operated on using any PHP function that handles files. Unfortunately there’s a bug which means that instead of returning a stream into $lob PDO returns a string containing the binary data. When this is then passed to fpassthru() an error is triggered. Fortunately there’s a simple fix for displaying the image: replace the call to fpassthru() with echo or print. Since the browser is expecting an image after the call to header() writing the binary data. Using echo or print has the same effect as calling fpassthru(). In my code I’ve added the following just in case this bug is fixed in a future release:

if (is_string($lob))
      {
   echo $lob;
} else {
   fpassthru($lob);
}

//or we can use following code to convert string data into a stream first then continue accessing it as if it were a string.
if (is_string($lob)) {
// $lob is now a resource pointing to a stream composed of the data at hand
$lob = fopen('data://text/plain;base64,' . base64_encode($lob), 'r');

fpassthru($lob);

This neatly gets around the problem if you just want to send the binary data back to the browser to be displayed. Anything more requiring the use of any file functions or image editing functions would need quite a few contortions in the code. The information from the database would probably need to be written to a temporary file to allow it to be operated on.
This bug was first reported almost three years ago in PHP 5.2.6 and it’s still not fixed today in the most recent version, 5.3.1.

To encrypt data using mycrypt function


$key = 'mysalt password';

$string = 'string to be encrypted s%$%&*^$#@! <img src="hjdsfshjf/djfhskdhjf"> <a href="#">my link</a> my texy sample text sample text';

$encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), $string, MCRYPT_MODE_CBC, md5(md5($key))));

$decrypted = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($key), base64_decode($encrypted), MCRYPT_MODE_CBC, md5(md5($key))), "\0");


print_r($encrypted); //32
echo "<br>";
print_r($decrypted); //22