How to Query a BLOB in PostgreSQL using PHP
Introduction
In SQL, binary data can be stored in a database as a BLOB, or binary large object. A BLOB often takes the form of an audio file, an image or some other multimedia object. Although PostgreSQL doesn’t offer a specific BLOB data type, it’s still possible to store and query BLOB data. In this article, we’ll show you how to query a BLOB in PostgreSQL using PHP.
Prerequisites
Before we start explaining how to query PostgreSQL BLOB data using PHP, let’s review a few important prerequisites that need to be in place:
- First, you’ll need to ensure that PHP has been installed and configured. To check your PHP version, use the
php -v
command. On Linux systems, the result of this command should look something like this:
1 2 3 4 | PHP 7.3.7-2+ubuntu18.04.1+deb.sury.org+1 (cli) (built: Jul 25 2019 11:44:59) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.3.7, Copyright (c) 1998-2018 Zend Technologies with Zend OPcache v7.3.7-2+ubuntu18.04.1+deb.sury.org+1, Copyright (c) 1999-2018, by Zend Technologies |
On Windows systems, you’ll see something like the following:
1 2 3 | PHP 7.3.11 (cli) (built: Oct 22 2019 11:20:18) ( ZTS MSVC15 (Visual C++ 2017) x64 ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.3.11, Copyright (c) 1998-2018 Zend Technologies |
- You’ll also need to make sure that Composer is installed and configured. To confirm that it’s installed, use the command
composer --version
. You should see output that looks like the following:
1 | Composer version 1.9.1 2019-11-01 17:20:17 |
The Sample Dataset
Now that we’ve discussed the prerequisites, we can turn our attention to data. We’ll need some sample data to use in this tutorial. In this section, we’ll show you the sample dataset structure that we’ll be working with throughout this tutorial.
Shown below is the table structure for our hypothetical flowershop
business:
1 2 3 4 5 6 7 | CREATE TABLE tbl_flower ( id SERIAL PRIMARY KEY, flower_id INTEGER, m_class CHARACTER VARYING(255), m_name CHARACTER VARYING(255), m_data BYTEA NOT NULL ); |
Here’s the sample dataset for this table:
1 2 3 4 5 6 | flowershop=# SELECT * FROM tbl_flower; id | flower_id | m_class | m_name | m_data ----+---------+------------+-----------+-------------- 1 | 1 | image/jpg | rose | \x3136373735 2 | 2 | image/jpg | sunflower | \x3136373736 (2 ROWS) |
Composer creates PHP project structure.
Next, we’ll create our project directory’s structure:
First, we’ll create the main project directory and name it
flowerphp
.Then we’ll create our
composer.json
file and add the following code to it:
1 2 3 4 5 6 7 | { "autoload": { "psr-4": { "flowerphp\": "app/" } } } |
This file will handle the class mapping of our PHP application and will create the PostgreSQL namespace.
NOTE: Follow PHP Standard Recommendations PSR-4, which offers improved autoloading, to be able to use Fully Qualified Class Names (FQCN) in a file path.
- After editing the file, we’ll navigate to our project directory in the terminal and execute the command shown below:
1 | composer update |
- This command will create a folder named
vendor
within the project directory. Since we don’t specify any other configuration, nothing else will be installed or updated; instead, it will generate autoload files.
1 2 3 4 | Loading composer repositories with package information Updating dependencies (including require-dev) Nothing to install or update Generating autoload files |
The PHP configuration file
Next, let’s create a configuration file inside the app
directory and name it configuration.ini
. This file will contain details about our PostgreSQL database.
1 2 3 4 5 | host=localhost port=5432 database=flowershop user=postgres password=1234 |
NOTE: We’ll need to create an assets
folder and a sub-folder inside this folder named img
. This is where we’ll store the images that we plan to use in this tutorial.
The Connection.php
In this section, we’ll show you how to create the connection.php
file that stores the connection details needed for our application.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | <?php namespace flowerphp; /** * Represents the Connection */ class Connection { /** * The Connection * @var type */ private static $conn; /** * Connect to the database and return an instance of \PDO object * @return \PDO * @throws \Exception */ public function connect() { // The following script will parse the parameters in the conf.ini configuration file $params = parse_ini_file('configuration.ini'); if ($params === false) { throw new \Exception("Error reading database configuration file"); } // connect to the postgresql database from the config.file parameters $conStr = sprintf("pgsql:host=%s;dbname=%s;user=%s;password=%s", $params['host'], $params['database'], $params['user'], $params['password']); $pdo = new \PDO($conStr); $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); return $pdo; } /** * return an instance of the Connection object * @return type */ public static function get() { if (null === static::$conn) { static::$conn = new static(); } return static::$conn; } } |
- The code shown above creates a singleton class named
Connection
. A singleton class is created only once, and it will refer to an existing instance should one exist.
Query BLOB data in PostgreSQL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | /** * Read BLOB from the database and output to the web browser * @param int $id */ public function read($id) { global $pdo; $this->pdo=$pdo; $this->pdo->beginTransaction(); $stmt = $this->pdo->prepare("SELECT id, m_data, m_class " . "FROM tbl_flower " . "WHERE flower_id= :id"); // query blob from the database $stmt->execute([$id]); $stmt->bindColumn('m_data', $fileData, \PDO::PARAM_STR); $stmt->bindColumn('m_class', $mimeClass, \PDO::PARAM_STR); $stmt->fetch(\PDO::FETCH_BOUND); $stream = $this->pdo->pgsqlLOBOpen($fileData, 'r'); // output the file header("Content-type: " . $mimeClass); fpassthru($stream); } ?> |
Let’s take a closer look at what’s happening in the code shown above:
We begin by preparing a statement for the SELECT operation.
Then we execute that statement using the method
execute()
.Next, we pass the OID to the
pgsqlLOBOpen()
method.The output stream will depend on the MIME-type of the file.
Finally, we’ll call the
beginTransaction()
at the onset of the method; we do this because thepgsqlLOBopen()
method needs to be invoked within a transaction.
If we want to query a BLOB in the PostgreSQL database, we can simply pass the id as a URL parameter. An example would look like this: localhost:8080/flowerphp/index.ph?id=3
.
Here’s an example of what the output should look like:
Conclusion
PostgreSQL may not have an explicit BLOB data type, but it’s easy to both store and query binary data in PostgreSQL from an application. In this tutorial, we showed you how to query a BLOB in a PostgreSQL database using PHP. With our instructions and code examples, you’ll be able to build your own applications that query for BLOB data and handle the results.
Pilot the ObjectRocket Platform Free!
Try Fully-Managed CockroachDB, Elasticsearch, MongoDB, PostgreSQL (Beta) or Redis.
Get Started