Create a PHP/Ubuntu dev environment in Windows 10

Initial WSL, Ubuntu, Apache, PHP and MySQL installation

Windows Subsystem for Linux allows a development environment to be set up locally without the need for virtual machine hosts.

First, install the WSL feature. Click Start, type ‘Windows features’ and click the Turn Windows Features On or Off item. Tick the Windows Subsystem for Linux option and click OK. The feature will be install, then you will need to restart the PC.

Once the PC is restarted click Start and click Windows Store. Search for and install Ubuntu. Once installation is complete, click Start and click Ubuntu. Further installation will continue and once complete you will be prompted to choose a username and password, which will be the primary account on the Ubuntu installation.

Once installed, run the following commands to install the necessary applications.

sudo apt update
sudo apt upgrade
sudo apt install apache2
sudo apt install mysql-server
sudo apt install php7.2 php7.2-mysql php7.2-odbc php7.2-intl php7.2-json php7.2-curl php7.2-zip php7.2-gd php7.2-xml php7.2-mbstring php7.2-ldap php7.2-dev git unzip curl
sudo apt-get autoremove
sudo service apache2 start
sudo service mysql start
sudo chage -m 0 -M 99999 -I -1 -E -1 user
sudo usermod -g www-data user
sudo usermod -a -G [username],adm,cdrom,sudo,dip,plugdev,lxd,www-data user
sudo a2enmod rewrite
sudo -i
mysql
    --run
    GRANT ALL PRIVILEGES ON *.* TO 'user'@'%' IDENTIFIED BY '-password-' WITH GRANT OPTION;
    exit

Change a couple of MySQL settings if you have older databases that may use 0 dates, removing some of MySQLs newer SQL mode flags.

sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

Add the SQL mode setting at the end of the file.

sql-mode="ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

Note that services don’t start automatically, so once installed they need to be started manually.

Host configurations

Now you’ll have an environment running Ubuntu, MySQL, Apache2 and PHP. You can connect to these services using ‘localhost’ as the host. The next step is to create a folder on the PC that will host the PHP code for the applications. Create an ubuntu folder on the C: drive, then create a www subfolder in it. Once this has been done, go back to the Ubuntu window and type

sudo a2dissite 000-default.conf
sudo mv /var/www /var/www.old
sudo ln -s /mnt/c/ubuntu/www /var/www

Then setup some git repositories. This assumes that you have created a repository on a hosted service like bitbucket.org or github.com. You will need to replace the http://username@repo.host.com/location/to/repo.git text with the URL found under the clone option.

git config --global user.name "User Name"
git config --global user.email "email@example.com"
cd /var/www
mkdir html
cd html
git init
git remote add origin http://username@repo.host.com/location/to/repo.git
git config core.fileMode false
git pull origin master

The last step is to set up some virtual hosts. Please note that you will need to add the host names to your C:\Windows\System32\driver\etc\hosts file so that Windows can resolve these new host names to the local address.

sudo nano /etc/apache2/sites-available/html.conf

and paste in the configuration data

<VirtualHost *:80>
    ServerName app.development.local
    ServerAlias app
    ServerAdmin webmaster@localhost
    SetEnv APPLICATION_ENV "development"
    DocumentRoot /var/www/html
    <Directory /var/www/html>
        Options Indexes FollowSymLinks MultiViews
         AllowOverride All
        Order allow,deny
        allow from all
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/app-error.log
    CustomLog ${APACHE_LOG_DIR}/app-access.log combined
</VirtualHost>

Finally enabled the sites and restart the services to grab the new configuration details.

sudo a2ensite html.conf
sudo service apache2 restart
sudo service mysql restart

Shutting down

You can just exit sessions as required, but the Ubuntu session won’t accept the shutdown command. If you need to force a restart of the Ubuntu environment, run

sudo touch /var/run/reboot-required

at the command line, then log out of all sessions.

Composer

If you want to install Composer change to your home folder (cd ~) and follow the command line instructions at https://getcomposer.org/download/ then move the composer.phar file to a better location.

sudo mv composer.phar /usr/local/bin/composer

Now it can be run from any location by typing:

composer

Microsoft SQL connections

If you need to use connections to MS SQL servers in the test environment follow the Ubuntu and PHP related steps at https://www.microsoft.com/en-us/sql-server/developer-get-started/php/ubuntu/step/2.html. Don’t use the steps that install the SQL Server software itself, only the drivers are required.

sudo apt install php-dev php-pear build-essential libaio1
sudo pecl channel-update pecl.php.net
sudo pear channel-update pear.php.net
curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list | sudo tee /etc/apt/sources.list.d/mssql-tools.list
sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install mssql-tools
sudo apt-get install unixodbc-dev
sudo pecl install sqlsrv pdo_sqlsrv
cd /etc/php/7.2/mods-available
sudo nano sqlsrv.ini

Add two lines to the ini file then save and exit.

extension=pdo_sqlsrv.so
extension=sqlsrv.so

Then run the create links to load this config file last.

cd /etc/php/7.2/apache2/conf.d
sudo ln -s /etc/php/7.2/mods-available/sqlsvr.ini 90-sqlsrv.ini
cd /etc/php/7.2/cli/conf.d
sudo ln -s /etc/php/7.2/mods-available/sqlsvr.ini 90-sqlsrv.ini

Oracle SQL connections

The Oracle SQL driver allows connections to the Drive database. Being Oracle, it’s more complex than alternatives. The instructions below are an amalgamation of details from https://gist.github.com/hewerthomn/81eea2935051eb2500941a9309bca703https://www.oracle.com/technetwork/articles/dsl/technote-php-instant-12c-2088811.htmlhttps://pecl.php.net/package/oci8https://stackoverflow.com/questions/47833041/unable-to-load-dynamic-library-oci8-so-php-7-2/47833414 and https://github.com/ulsdevteam/Oracle-cake2

Download the Oracle instantclient-basiclite-linux.x64 and instantclient-sdk-linux.x64 ZIP files from the Oracle site (you may need to register) – https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html. Extract these files and copy them to the C:\ubuntu\oracle. Then in the WSL console

mkdir /opt/oracle/instantclient_XX_X
cp -R /mnt/c/ubuntu/oracle/instantclient_XX_X_basiclite/* /opt/oracle/instantclient_XX_X
cp -R /mnt/c/ubuntu/oracle/instantclient_XX_X_sdk/* /opt/oracle/instantclient_XX_X
rm /opt/oracle/instantclient_XX_X/libclntsh.so
rm /opt/oracle/instantclient_XX_X/libocci.so
cp /opt/oracle/instantclient_XX_X/libclntsh.so.XX.X /opt/oracle/instantclient_XX_X/libclntsh.so
cp /opt/oracle/instantclient_XX_X/libocci.so.XX.X /opt/oracle/instantclient_XX_X/libocci.so
sudo nano /etc/ld.so.conf.d/oracle-instantclient.conf

Add the following line to the new file

/opt/oracle/instantclient_19_3

Save the file and load the new library, then install the PECL package

sudo ldconfig
sudo apt install php-dev php-pear build-essential libaio1
sudo pecl channel-update pecl.php.net
sudo pear channel-update pear.php.net
sudo pecl install oci8

When prompted, enter the instantclient and location

instantclient,/opt/oracle/instantclient_XX_X

Once the PECL build is complete, edit the php.ini files

sudo nano /etc/php/7.2/apache2/php.ini
sudo nano /etc/php/7.2/cli/php.ini

and add

extension=oci8

at the end of the extensions section. Check that oci8 has loaded

php -m | grep 'oci8'

If successful, Apache needs a restart

sudo service apache2 restart

If there are loading issues with the OCI8 extension you can investigate the issues by running (note that the directory with the date name will change depending on the version).

ldd /usr/lib/php/20170718/oci8.so

Mcrypt extensions for OAuth style webservices

If the mcrypt extension is required

sudo apt install php-dev libmcrypt-dev php-pear
sudo pecl channel-update pecl.php.net
sudo pecl install mcrypt-1.0.1
sudo nano /etc/php/7.2/apache2/php.ini
add
extension=mcrypt
sudo nano /etc/php/7.2/cli/php.ini
add
extension=mcrypt

Conclusions

Now you can enjoy a local development environment that doesn’t required a connection to a network resource for development. Note that this article was created for WSL1, WSL2 improves some performance enhancements but the above configuration should still work.