Vagrant development environment for PHP

As a developer, I work on projects that require a variety of software, each tuned to different configurations. The easiest way to achieve this is to set up a virtual machine and configure that as per the need of the project. This allows me to keep my host machine clean, and share the virtual machine with other developers on the project.

In this blog, I’ll describe the configuration of a Vagrant machine that I’ve setup for PHP web development. Here’s a link to the box on vagrant cloud.

Vagrant configuration

Recommended configuration

The vagrant box runs Debian 10 Buster. It uses,

  1. 2 dedicated CPU cores
  2. 1560 MB of RAM from the host machine.

Port configuration

Following is the port configuration for the vagrant box,

Other configuration

  • Added vagrant user to www-data and adm group, in order to handle Apache permissions and view application logs.
  • SSH agent forwarding has been enabled.

Installed software

Listed below are software that have been installed on the system,

  1. Apache 2.4.38
  2. MariaDB 10.3.18
  3. htop, ncdu, curl, git, unzip
  4. PHP 7.3 and extensions
  5. Composer 1.9.1 (globally)
  6. Redis 5.0.3
  7. Node 12.14. 1 and npm 6.13.4 (via nvm)

Software configuration

  1. The base directory for Apache2 is configured to /vagrant/code. The vagrant user has been added to the www-data group to handle permission issues.
  2. Apache2 mod_rewrite module has been enabled.
  3. MariaDB has been configured with the following users,
    • Username: root / Password: T0P!33L
    • Username: admin / Password: C00La!d
  4. Following changes have been made to MariaDB configuration,
    • Increased innodb_buffer_pool_size to 768MB
    • Set innodb_file_per_table to 1.
    • Set max_allowed_packet to 256MB for MySQL, and 192MB for mysqldump
    • Enabled slow query logging. Long query time has been set to 5 seconds. Slow logs will be written to /var/log/mysql/mysql_slow.log.
  5. All PHP extensions required to run Laravel 6 have been installed. In addition, the tidy, xdebug, redis, and yaml extensions have been installed.
  6. Following changes have been made to PHP configuration file,
    • upload_max_filesize and post_max_size have been set to 20MB.
    • memory_limit has been set to 256MB.
    • Enabled error logging for both Apache and CLI.
  7. For Redis, maxmemory has been set to 256MB.
  8. Composer bin folder has been added to the PATH via .bashrc

PHP debugging support

Debugging support for PHP has been added via Xdebug and tested using VSCode with the PHP Debug extension.

Consider a sample VSCode project – debugging, created under /vagrant/code/debugging. This project has a file called index.php. Following is the configuration that needs to be put under the VSCode launch file. (/vagrant/code/debugging/.vscode/launch.json).

Following is the configuration for Xdebug,

Future improvements

I currently have the following things in mind,

  • The box is set to use 1536MB of RAM, and I might have to tweak this a little higher.
  • Test debugging support for applications run via the PHP server and on the PHP CLI
  • Install and setup XHProf and XHProf UI.

I plan on keeping this box up-to-date for the foreseeable future. I’m open to suggestions on how this box can be improved, and made more useful for PHP developers to quickly start their development.

Handling JSON request in PHP

I’ve been working with PHP and jQuery AJAX quite a bit lately. Along with sending form data to PHP page through AJAX, I’ve written restful web services in PHP that receive data in JSON format.

In general when you are sending data through jQuery AJAX to PHP, you don’t have to specify a contentType. Depending on your type ‘GET’ or ‘POST’, PHP will nicely wrap your content into either the $_POST or $_GET global arrays. When you don’t specify a contentType the default contentType is taken as application/x-www-form-urlencoded; charset=UTF-8’.

Following is the request headers from an AJAX call without contentType specified,

To further test this, I set up the following PHP code on my server,

The response that for the above request case was,

If we put the jQuery AJAX type property as ‘POST’ we will have the following request header,

Nothing much changes. The action is specified as POST and the data is no longer a part of the request header. The response from the server is following,

Obviously, PHP has no issues parsing content of type – application/x-www-form-urlencoded; charset=UTF-8. As soon as it sees that contentType, it checks the action and packs the data nicely into either $_GET or $_POST.

Let’s now talk about JSON data. In general, restful web services accept data of type JSON. When sending data via JSON the contentType for jQuery AJAX is application/json; charset=UTF-8

This is the request header,

When PHP receives this data and looks at the content type, it’s not quite sure how to process it, so it leaves it alone. In this case the action – ‘POST’ or ‘GET’ doesn’t matter. You’ll notice that $_POST or $_GET both, are empty arrays. Now, it’s up to you to read this data and parse it.

The code above, reads the data from PHP’s input stream. Since we have passed a JSON string, we decode it, which converts it to a PHP array and stores it in $app_json. If the data you send is not in a correct JSON format, $app_json will have false.

When we echo our response, we get the following on the client side,

I set up a small project to illustrate what has been written here. You can find it over on my github page Continue reading “Handling JSON request in PHP”

get_results PHP function not working on CentOS

There are instances where the PHP function – get_results will not work on CentOS (this maybe the case with other Linux based operating systems as well). I faced this issue while deploying a project on CentOS which was originally developed on Windows. All my INSERT, UPDATE and DELETE database statements were working properly, but bulk SELECTstatements had issues. Closer inspection narrowed down the problem to the get_results function.

I came across this on the get_results PHP documentation page –

I was able to determine if mysqlnd driver was installed using this post on StackOverflow as reference. As expected, it wasn’t.

Here’s the relevant php code from the StackOverflow post –

Now that I new that we needed to install the mysqlnd driver, here are the steps that I followed to get the mysqlnd driver working on CentOS,

After installing the mysqlnd driver the get_results function worked just fine.

Tree view based file explorer for the web using jQuery.

This post assumes that the reader has a basic understanding of PHP, jQuery and jQuery $.post

Recently I had to implement a windows-esque tree view based file explorer for one of my projects at work. I ended up using this wonderful jQuery plugin to help me. In this blog I’ll be going through some basic code to get it working using PHP on the server side.

To whet your appetite, here’s what we’ll be achieving in this blog post – A complete tree view based file explorer that feeds from a folder on the server’s file system.

File tree view

So let’s get started!

To be able to render a proper tree using the aciTree plugin, we’ll need to send JSON from server in the following format –

Here’s the list of things that we’ll be doing –

  1. Server Side Code
  2. HTML
  3. JavaScript/jQuery code to communicate with the server.
  4. Basic event handling for the aciTree plugin.

1. Server side code

Let’s move onto the PHP code. Our job is to read the files from the specified folder and return a JSON structure that resembles what’s shown above. If you look closely you’ll observe that the JSON above is basically an array of objects of with properties as – id, label, inode, icon, open

The following class is exactly similar to that of the class received via JSON. We’ll be returning an array of NodeList objects from the server.

Now to read the list of files and folders from a location on the server –

Some code to handle the request that we will be making from the client side and then echoing the output in JSON format –

Okay so we have the PHP code in place. Next order of things –

  1. Server Side Code
  2. HTML
  3. JavaScript/jQuery code to communicate with the server.
  4. Basic event handling for the aciTree plugin.


The following HTML goes inside the body tag-

Next, the JavaScript/jQuery to get the aciTree plugin working. This should be put inside the document’s ready handler –

3. jQuery code to communicate with the server

4. Event handling for the aciTree plugin

And finally a simple event handler for the aciTree that is triggered whenever a node in the tree is selected –

You can find the whole code here and a working copy of the project here.