MacLochlainns Weblog

Michael McLaughlin's Technical Blog

Site Admin

Archive for the ‘PHP’ Category

MySQL PNG Files

with one comment

LAMP (Linux, Apache, MySQL, Perl/PHP/Python) Architecture is very flexible. All the components can be positioned on the same server or different servers. The servers are divided into two types. The types are known as the Application or database tiers. Generally, the application tier holds the Apache Server, any Apache Modules, and local copies of Server Side Includes (SSI) programs.

In many development environments, you also deploy the client to the same machine. This means a single machine runs the database server, the application server, and the browser. The lab for this section assumes these configurations.

Before you test an installation, you should make sure that you’ve started the database and Apache server. In an Oracle LAMP configuration (known as an OLAP – Oracle, Linux, Apache, Perl/PHP/Python), you must start both the Oracle Listener and database. MySQL starts the listener when you start the database. You must also start the Apache Server. The Apache Server also starts an Apache Listener, which listens for incoming HTTP/HTTPS requests. It listens on Port 80 unless you override that setting in the httpd.conf file.

The URI reaches the server and is redirected to an Apache Module based on configuration information found in the httpd.conf file. Spawned or child processes of the Apache Module then read programs into memory from the file system and run them. If you’ve uploaded a file the locally stored program can move it from a secure cache location to another local area for processing. The started programs can run independently or include other files as libraries, and they can communicate to the database server.

Working though PHP test cases against the MySQL database for my AlmaLinux installation and configuration, I discovered that the php-gd library weren’t installed by default. I had to add it to get my PHP programs to upload and display PNG files.

The log file for applying the php-gd packages:

The balance of this page demonstrates how to upload, store, and manage Text (Character Large Data Streams) and BLOBs (Binary Large Objects). It provides MySQL equivalent instructions to those for manaing LOBs in an Oracle database. As covered in Chapter 8 in my Oracle Database 11g PL/SQL Programming book.

Before you begin these steps, you should have already installed Zend Server Community Edition. If you haven’t done so, please click here for instructions.

If you find any problems, please let me know. I’ll be happy to fix them.

Written by maclochlainn

December 28th, 2022 at 10:59 pm

AlmaLinux Install & Configuration

without comments

This is a collection of blog posts for installing and configuring AlmaLinux with the Oracle, PostgreSQL, MySQL databases and several programming languages. Sample programs show how to connect PHP and Python to the MySQL database.

I used Oracle Database 11g XE in this instance to keep the footprint as small as possible. It required a few tricks and discovering the missing library that caused folks grief eleven years ago. I build another with a current Oracle Database XE after the new year.

If you see something that I missed or you’d like me to add, let me know. As time allows, I’ll try to do that. Naturally, the post will get updates as things are added later.

mysqli Strict Standards

with 2 comments

Six years ago I wrote a common lookup post to illustrate the effectiveness of things used throughout your applications. Now, I’m updating my student image with a more complete solution to show how to avoid update anomalies.

In the prior post, I used a while loop in PHP, like the following:

do {
      ...
} while($stmt->next_result());

Using PHP Version 7.3.8 and MySQL 8.0.16, that now raises the following error message:

Strict Standards: mysqli_stmt::next_result(): There is no next result set. Please, call mysqli_stmt_more_results()/mysqli_stmt::more_results() to check whether to call this function/method in /var/www/html/app/library.inc on line 81

You can see this type of error when you set the following parameters in your file during testing:

ini_set('display_errors',1);
ini_set('display_startup_errors',1);
error_reporting(E_ALL);

You can read more about error handling at this web page. The new and strict compliance standard for mysqli managing rows is:

do {
      ...
} while($stmt->more_result());

As always, I hope this helps those looking for an answer.

Written by maclochlainn

September 14th, 2019 at 10:30 pm

Posted in LAMP,MySQL,MySQL 8,mysqli,PHP

Tagged with ,

MySQL Update in mysqli

without comments

Somebody didn’t like the MySQLi Update Query example on the tutorialspoint.com website because it use the procedure mysqli_query style. Here’s a simple example of using the object-oriented method version. More or less, instead of query it uses the more intuitive execute() method.

The update_member function contains the logic and below it is a call to the test the function. It relies on a MySQLCredentials.inc file that contains the hostname, user name, password, and database name. You can create create member table, like my example in MySQL 8, or any other table in your MySQL database.

<?php
/*
||  Function Name: update_member
*/
function update_member($account_number, $member_type, $credit_card_number, $credit_card_type) {
 
  // Include the credentials file if omitted.
  include_once("MySQLCredentials.inc");
 
  // Assign credentials to connection.
  $mysqli = new mysqli(HOSTNAME, USERNAME, PASSWORD, DATABASE);
 
  // Check for connection error and print message.
  if ($mysqli->connect_errno) {
    print $mysqli->connect_error."<br />";
    print "Connection not established ...<br />";
  }
  else {
    // Initial statement.
    $stmt = $mysqli->stmt_init();
 
    /* Disabling auto commit when you want two or more statements executed as a set.
    || ------------------------------------------------------------
    ||  You would add the following command to disable the default
    ||  of auto commit.
    ||  ------------------------------
    ||   $mysqli->autocommit(FALSE);
    || ------------------------------------------------------------
    */
 
    // Declare a static query.
    $sql = "UPDATE   member\n"
         . "SET      member_type = ?\n"
         . ",        credit_card_number = ?\n"
         . ",        credit_card_type = ?\n"
         . "WHERE    account_number = ?\n";
 
    /* Prepare statement.
    || ------------------------------------------------------------
    ||  Please note that the bind_param method is a position 
    ||  rather than named notation, which means you must provide
    ||  the variables in the same order as they are found in
    ||  the defined $sql variable as "?".
    || ------------------------------------------------------------
    ||  print($sql);
    ||  print("Member Type:      [1][".$member_type."]\n");
    ||  print("Credit Card No:   [2][".$credit_card_number."]\n");
    ||  print("Credit Card Type: [3][".$credit_card_type."]\n");
    ||  print("Account Number:   [4][".$account_number."]\n");
    || ------------------------------------------------------------
    */
    if ($stmt->prepare($sql)) {
      $stmt->bind_param("ssss",$member_type,$credit_card_number,$credit_card_type,$account_number); } 
 
    // Attempt query and exit with failure before processing.
    if (!$stmt->execute()) {
 
      // Print failure to resolve query message.
      print $mysqli->error."<br />";
      print "Failed to resolve query ...<br />";
    }
    else {   
      /*  Manually commiting writes when you have disabled the
      ||  default auto commit setting, explained above.
      || ------------------------------------------------------------
      ||  You would add the following command to commit the 
      ||  transaction.
      ||  ------------------------------
      ||   $mysqli->commit();
      || ------------------------------------------------------------
      */
    }
  }
}
 
// Test case
update_member('US00011', '1006', '6011-0000-0000-0078', '1007');
?>

I put this logic in a function.php file. If you do the same, you can run the test case like this from the command line:

php function.sql

As always, I hope this helps.

Written by maclochlainn

September 14th, 2019 at 6:20 pm

Apache on Fedora 30

with one comment

There was an option during the Fedora 30 Workstation installation to add the Apache Web Server, but you need to set it to start automatically. Unfortunately, there was no option to install PHP, which I thought odd because of how many web developers learn the trade first on PHP with a LAMP (Linux, Apache, MySQL, Perl/PHP/Python) stack. You see how to fix that shortcoming in this post and how to install and test PHP, mysqli, and pdo to support MySQL 8.

Before you do that make sure you install MySQL 8. You can find my prior blog post on that here.

You set Apache to start automatically, on the next boot of the operating system, with the following command:

chkconfig httpd on

It creates a symbolic link:

Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.

However, that command only starts the Apache server the next time you boot the server. You use the following command as the root user to start the Apache server:

apachectl start

You can verify the installation with the following command as the root user:

ps -ef | grep httpd | grep -v grep

It should return:

root      5433     1  0 17:03 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache    5434  5433  0 17:03 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache    5435  5433  0 17:03 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache    5436  5433  0 17:03 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache    5437  5433  0 17:03 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache    5438  5433  0 17:03 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache    5442  5433  0 17:03 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND

and, then verify the listening port with the following command as the root user:

netstat -tulpn | grep :80

It should return the following when both the Apache server is listening on port 80 and the Oracle multi-protocol server is listening on port 8080:

tcp6       0      0 :::80                   :::*                    LISTEN      119810/httpd        
tcp6       0      0 :::8080                 :::*                    LISTEN      1403/tnslsnr

You can also enter the following URL in the browser to see the Apache Test Page:

http://localhost

It should display the test page, like this:

You can also create a hello.htm file in the /var/www/html directory to test the ability to read an HTML file. I would suggest the traditional hello.htm file:

<html>
<body>
Hello World!
</body>
</html>

You can call it by using this URL in the browser:

http://localhost/hello.htm

It should display the test page, like this:

Now, let’s install PHP. You use the following command as a privileged user, which is one found in the sudoer’s list:

yum install -y php

Before you test the installation of PHP in a browser, you must restart the Apache HTTP Server. You can do that with the following command as a privileged user:

sudo apachectl restart

After verifying the connection, you can test it by creating the traditional info.php program file in the /var/www/http directory. The file should contain the following:

1
2
3
<?php
  phpinfo();
?>

It should display the PHP Version 7.3.8 web page, which ships with Fedora 30:

The next step shows you how to install mysqli and pdo with the yum utility. While it’s unnecessary to check for the older mysql library (truly deprecated), its good practice to know how to check for a conflicting library before installing a new one. Also, I’d prefer newbies get exposed to using the yum utility’s shell environment.

You start the yum shell, as follows:

yum shell

With the yum shell, you would remove a mysql package with the following command:

> remove php-mysql

The command will remove the package or tell you that there is no package to remove. Next, you install the php-mysqli package with this command:

install php-mysqli

You will then be prompted to confirm the installation of the php-mysqli library. Finally, you exit the yum shell with this command:

> quit

If you want to see the whole interactive shell, click on the link below.

You need to restart the Apache HTTP listener for these changes to take place, which you do with the same command as shown earlier:

sudo apachectl restart

I wrote the mysqli_check.php script to verify installation of both the mysqli and pdo libraries. The full code should be put in a mysqli_check.php file in the /var/www/html directory for testing.

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
<html>
<header>
<title>Static Query Object Sample</title>
<style type="text/css">
  /* HTML element styles. */
  table {background:white;border-style:solid;border-width:3px;border-color:black;border-collapse:collapse;}
  th {text-align:center;font-style:bold;background:lightgray;border:solid 1px gray;}
  td {border:solid 1px gray;}
 
  /* Class tag element styles. */
  .ID {min-width:50px;text-align:right;}
  .Label {min-width:200px;text-align:left;}
</style>
</header>
<body>
<?php
  if (!function_exists('mysqli_init') && !extension_loaded('mysqli')) {
    print 'mysqli not installed.'; }
  else {
    print 'mysqli installed.'; }
  if (!function_exists('pdo_init') && !extension_loaded('pdo')) {
    print '<p>pdo not installed.</p>'; }
  else {
    print '<p>pdo installed.</p>'; }
?>
</script>
</body>
</html>

You can test it with the following URL from the local browser:

http://localhost/mysqli_check.php

It should print the following to the web page when you’ve successfully install the mysqli and pdo libraries:

mysqli installed.
pdo installed.

If you plan to use PHP to display and render graphics, you need to install php-gd library. You can do that with the yum utility and this prior blog post explains it. Don’t forget to restart the Apache HTTP Server after you add the php-gd library.

For example, one of my sample PHP programs loads a PNG image into a BLOB column as raw binary text. Then, the program reads it and renders it with PHP to produce the following web page.

As always, I hope this helps those looking for a complete solution without cost.

Written by maclochlainn

August 16th, 2019 at 12:26 pm

Convert JSON with PHP

without comments

Sometimes I get poorly thought or just naive questions. That is naive questions because they didn’t read the documentation or don’t understand the semantics of a given programming language. The question this time said they tried to implement what they found on a web page but their sample json_decode function example failed after they followed directions.

Surprise, it didn’t fail because they followed directions. They overlooked part of the example because they didn’t understand how to read a nested array in PHP. The actual example sets up an array of JSON objects, then print_r to read the Array, but the student tried to read it in a foreach loop. Naturally, their sample program raised an error because the base object was an Array not a String, and their target JSON object was nested inside the base Array.

I rewrote the example file to simply convert a JSON structure to an associative array, as follow:

<?php
  // Assign a JSON object to a variable.
  $someJSON = '{"name":"Joe","moniker":"Falchetto"}';
 
  // Convert the JSON to an associative array.
  $someArray = json_decode($someJSON, true);
 
  // Read the elements of the associative array.
  foreach ($someArray as $key =--> $value) {
    echo "[" . $key . "][" . $value . "]";
  }
?>

When you call the program, like this

php test.php

It displays

[name][Joe][moniker][Falchetto]

As always, I hope this helps those looking to display a JSON structure in PHP.

Written by maclochlainn

May 6th, 2019 at 8:45 pm

Posted in JSON,PHP,Uncategorized

MySQL 5.7.* and mysqli

without comments

After installing MySQL 5.7.22 and PHP 7.1.17 on Fedora 27, you need to install the mysqli library. You need to verify if the mysqli library is installed. You can do that with the following mysqli_check.php program:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html>
<header>
<title>Check mysqli Install</title>
</header>
<body>
<?php
  if (!function_exists('mysqli_init') && !extension_loaded('mysqli')) {
    print 'mysqli not installed.'; }
  else {
    print 'mysqli installed.'; }
?>
</script>
</body>
</html>

You test preceding PHP program with the following URL in a browser:

http://localhost/mysqli_check.php

If the mysqli program isn’t installed, you can install it as follows by opening the yum interactive shell:

[root@localhost html]# yum shell
Last metadata expiration check: 1:26:46 ago on Wed 22 Aug 2018 08:05:50 PM MDT.
> remove php-mysql
No match for argument: php-mysql
Error: No packages marked for removal.
> install php-mysqlnd
> run
================================================================================================
 Package                 Arch               Version                   Repository           Size
================================================================================================
Installing:
 php-mysqlnd             x86_64             7.1.20-1.fc27             updates             246 k
Upgrading:
 php                     x86_64             7.1.20-1.fc27             updates             2.8 M
 php-cli                 x86_64             7.1.20-1.fc27             updates             4.2 M
 php-common              x86_64             7.1.20-1.fc27             updates             1.0 M
 php-fpm                 x86_64             7.1.20-1.fc27             updates             1.5 M
 php-json                x86_64             7.1.20-1.fc27             updates              73 k
 php-pdo                 x86_64             7.1.20-1.fc27             updates             138 k
 php-pgsql               x86_64             7.1.20-1.fc27             updates             135 k
 
Transaction Summary
================================================================================================
Install  1 Package
Upgrade  7 Packages
 
Total download size: 10 M
Is this ok [y/N]: y

After you type y and the return key, you should see a detailed log of the installation. Click the link below to see the yum installation log detail.

After you install the mysqli library, you exit the yum interactive shell with the quit command as shown:

> quit
Leaving Shell
The downloaded packages were saved in cache until the next successful transaction.
You can remove cached packages by executing 'dnf clean packages'.

You can now retest by re-running the mysqli_check.php program with the following URL:

http://localhost/mysqli_check.php

Image processing is not generally installed by default. You should use the following yum command to install the PHP Image processing library:

yum install -y php-gd

Or, you can use dnf (Dandified yum), like:

dnf install -y php-gd

Click the link below to see the yum installation log detail.

If you encounter an error trying to render an image like this:

Call to undefined function imagecreatefromstring() in ...

The php-gd package is not enabled. You can verify the contents of the php-gd package with the following rpm command on Fedora or CentOS:

rpm -ql php-gd

On PHP 7.1, it should return:

/etc/php-zts.d/20-gd.ini
/etc/php.d/20-gd.ini
/usr/lib/.build-id
/usr/lib/.build-id/50
/usr/lib/.build-id/50/11f0ec947836c6b0d325084841c05255197131
/usr/lib/.build-id/b0/10bf6f48ca6c0710dcc5777c07059b2acece77
/usr/lib64/php-zts/modules/gd.so
/usr/lib64/php/modules/gd.so

Then, you might choose to follow some obsolete note from ten or more years ago to include gd.so in your /etc/php.ini file. That’s not necessary.

The most common reason for incurring this error is tied to migrating old PHP 5 code forward. Sometimes folks used logic like the following to print a Portable Network Graphics (png) file stored natively in a MySQL BLOB column:

  header('Content-Type: image/x-png');
  imagepng(imagecreatefromstring($image));

If it was stored as a Portable Network Graphics (png) file, all you needed was:

  header('Content-Type: image/x-png');
  print $image;

As always, I hope this helps those looking for a solution.

Written by maclochlainn

August 23rd, 2018 at 11:47 am

Oracle 12c and PHP

without comments

This answers “How you connect PHP programs to an Oracle 12c multitenant database. This shows you how to connect your PHP programs to a user-defined Container Database (CDB) and Pluggable Database (PDB). It presupposes you know how to provision a PDB, and configure your Oracle listener.ora and tnsnames.ora files.

CDB Connection:

This assumes you already created a user-defined c##plsql CDB user, and granted an appropriate role or set of privileges to the user. Assuming the demonstration database Oracle TNS Service Name of orcl, you would test your connection with this script:

<?php
  // Attempt to connect to your database.
  $c = @oci_connect("video", "video", "localhost/orcl");
  if (!$c) {
    print "Sorry! The connection to the database failed. Please try again later.";
    die();
  }
  else {
    print "Congrats! You've connected to an Oracle database!";
    oci_close($c);
  }
?>

PDB Connection:

This assumes you already created a user-defined videodb PDB, and video user in the PDB, and granted an appropriate role or set of privileges to the video user. Assuming the user-defined videodb PDB uses an Oracle TNS Service Name of videodb, you would test your connection with this script:

<?php
  // Attempt to connect to your database.
  $c = @oci_connect("video", "video", "localhost/videodb");
  if (!$c) {
    print "Sorry! The connection to the database failed. Please try again later.";
    die();
  }
  else {
    print "Congrats! You've connected to an Oracle database!";
    oci_close($c);
  }
?>

Line 3 above uses the TNS Service Name from the tnsnames.ora file, which is also the SID Name from the listener.ora file after the slash that follows the localhost. That’s the only trick you should need.

You should note that because the tnsnames.ora file uses a video service name, the connection from the command line differs:

sqlplus video@video/video

Hope this helps those trying to sort it out.

Written by maclochlainn

December 10th, 2017 at 12:42 pm

Posted in Oracle,Oracle 12c,PHP

Fedora LAMP Steps

without comments

I posted earlier in the year how to configure a Fedora instance to test PHP code on a local VM. However, I’ve got a few questions on how to find those posts. Here’s a consolidation with links on those steps:

  1. Go to this blog post and install the httpd and php libraries with the yum installer.
  2. In the same blog post as step 1 (you can put the sample PHP code into the /var/www/html directory for testing), connect to the yum shell and remove the php-mysql library and then install the mysqlnd library.
  3. Go to this blog post and install the php-gd libraries, which enable you to render PNG images stored as binary streams in MySQL.

As always, I hope that helps.

Written by maclochlainn

December 9th, 2015 at 9:44 am

LAMP php-gd Libraries

with one comment

Everything seemed complete after configuring my standalone MySQL instance to a LAMP installation, but last night I started playing with the image files. It turns out that I failed to install the php-gd library.

There’s very little feedback when you try to troubleshoot why you can’t read an image. In fact, the error message for reading the BLOB from MySQL was only available on the local Firefox browser:

The image "http://localhost/ConvertMySQLBlobToImage.php" cannot be displayed because it contains errors.

The fix requires root to install the php-gd library with the yum utility:

yum install php-gd

You’ll need to answer y to one question during the installation:

Loaded plugins: langpacks, refresh-packagekit
mysql-connectors-community                                  | 2.5 kB  00:00     
mysql-tools-community                                       | 2.5 kB  00:00     
mysql56-community                                           | 2.5 kB  00:00     
pgdg93                                                      | 3.6 kB  00:00     
updates/20/x86_64/metalink                                  |  16 kB  00:00     
Resolving Dependencies
--> Running transaction check
---> Package php-gd.x86_64 0:5.5.22-1.fc20 will be installed
--> Processing Dependency: libt1.so.5()(64bit) for package: php-gd-5.5.22-1.fc20.x86_64
--> Running transaction check
---> Package t1lib.x86_64 0:5.1.2-14.fc20 will be installed
--> Finished Dependency Resolution
 
Dependencies Resolved
 
================================================================================
 Package         Arch            Version                 Repository        Size
================================================================================
Installing:
 php-gd          x86_64          5.5.22-1.fc20           updates           89 k
Installing for dependencies:
 t1lib           x86_64          5.1.2-14.fc20           updates          164 k
 
Transaction Summary
================================================================================
Install  1 Package (+1 Dependent package)
 
Total download size: 252 k
Installed size: 629 k
Is this ok [y/d/N]: y
Downloading packages:
(1/2): php-gd-5.5.22-1.fc20.x86_64.rpm                      |  89 kB  00:00     
(2/2): t1lib-5.1.2-14.fc20.x86_64.rpm                       | 164 kB  00:01     
--------------------------------------------------------------------------------
Total                                              157 kB/s | 252 kB  00:01     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction (shutdown inhibited)
  Installing : t1lib-5.1.2-14.fc20.x86_64                                   1/2 
  Installing : php-gd-5.5.22-1.fc20.x86_64                                  2/2 
  Verifying  : php-gd-5.5.22-1.fc20.x86_64                                  1/2 
  Verifying  : t1lib-5.1.2-14.fc20.x86_64                                   2/2 
 
Installed:
  php-gd.x86_64 0:5.5.22-1.fc20                                                 
 
Dependency Installed:
  t1lib.x86_64 0:5.1.2-14.fc20                                                  
 
Complete!

After the installation, you can run the info.php program, which contains the following:

1
2
3
<?php
  phpinfo();
?>

You’ll find the following gd library display in the result from the info.php program:

Linux_php_gd_library

After retesting, we get both large text and blob files displayed in the web page:

LAMPBlobTextPage

As always, I hope this helps others. Especially, those who are working with your LAMP stack implementation of images.

Written by maclochlainn

March 31st, 2015 at 6:20 pm