Simplified Web Development with JSON and the Twig Ternary Operator

Introduction

I’ve been looking at ways to simplify my code, make it easier to support, make it easier to use, and easier to maintain. I have found that JSON is an ideal way to store a large amount of data in databases, and Twig is an ideal templating engine to make use of JSON data.

Example JSON Representation

Here is a real example where we have a form that has a number of checkboxes that can be checked. In this case, you can check all of the checkboxes (except the no issues one).

Transport_Section

You could design your database to have a column for each checkbox, but that would be a unwise choice; since for example just this section has 6 checkboxes, and then you will need to process all 6 of those checkboxes and whether they are checked of not.

The better way to go is to store this in JSON format in the database. For the checkbox “I don’t have a driver’s license”, we could call that “License” and it can be either true or false (whether it is checked or not). For the checkbox “I will be riding with a friend to college”, we could call that “Friend”.

So I came up with the resultant format for the JSON to store in my database like so:

{
   "License": false,
   "Transit": true,
   "No_Issues": false,
   "Friend": false,
   "Car": false,
   "Other": true,
   "Other_Value": "skateboard"
}

Notice also for the “Other:” checkbox, I made it a boolean; and if it is true, there is a “Other_Value” object that stores the string value that gets entered. Essentially I use Javascript to check when the “Other:” checkbox is selected and then I will show a input field to enter the Other value, and I store that string.

Handling the JSON in the Controller

In my case, I use Symfony as my MVC framework to develop my forms and I have to first store the form booleans as a PHP array:

// Create transportation JSON.
$transport_json = array(
   "License" => $license_bool,
   "Transit" => $transit_bool,
   "No_Issues" => $trans_no_issues_bool,
   "Friend" => $friend_bool,
   "Car" => $car_bool,
   "Other" => $trans_other_bool,
   "Other_Value" => $trans_other_value
);

Then I use the standard PHP function json_encode to store the Transportation JSON data in my assessment object:

// Set the tranport JSON in the assessment.
$assess->setTransport( json_encode($transport_json) );

Also, you need to persist (uses Doctrine) the assessment object to the database:

// Save the assessment to db.
$em->persist( $assess );
$em->flush();

Then to pass the saved JSON back from the database and view in a Twig template, we use the standard PHP json_decode function to pass the JSON data as a parameter to the Twig assessment template:

return $this->render('default/viewIndNeedsAssess.html.twig', array(
        'stu' => $student,
        'assess' => $student->getIndneedForm(),
        'transport' => json_decode($student->getIndneedForm()->getTransport(), true),
        ...
));

Handling the JSON in Twig with Ternary Operator

Now finally since we can reference the “transport” JSON array in the Twig template, we can easily use the ternary operator to display a view of the completed form. In my case I wanted to show the form results in a html table within “td” elements, I wanted to show checkbox icons that show whether the form is checked or not.

Here is the Twig code I used to achieve the best results:

<td>
   <b>Transportation:</b>

    {{ transport['License'] ? '☑' : '☐' }}
      I don't have a driver's license

    {{ transport['Transit'] ? '☑' : '☐' }}
      I will be using the Kern Regional Transit / Taft Area Transit

    {{ transport['No_Issues'] ? '☑' : '☐' }}
      I have no transportation issues

    {{ transport['Friend'] ? '☑' : '☐' }}
      I will be riding with a friend to college

    {{ transport['Car'] ? '☑' : '☐' }}
      I have my own car

    {{ transport['Other'] ? '☑' : '☐' }}
      Other: {{ transport['Other_Value'] ?? '' }}</td>

Notice in the above ternary, I check if “transport[‘License’]” is true, if it’s true, then I show the code “☑” which is a checked checkbox.

And here is a screenshot with the final way the form looks when viewing a completed (submitted) form:

Transport_Final

Cut & Paste in Eclipse Removes Space

Introduction

I do a lot of Symfony PHP development, and I use Eclipse as my IDE. I’ve been using Eclipse for many years, so I don’t want to switch to PHPStorm, even though it’s one of the most popular IDEs used with Symfony and PHP development.

This article is about a problem of auto indentation when using Eclipse to edit code.

The Problem

The problem I experienced, was when I was cutting and pasting a variable in a foreach loop or in a variable definition, the IDE would automatically remove the space(s) to the right of where I pasted.

For example, let’s take this example code:

foreach( $bad as $val ){

Then I would double-click the “$bad” variable and do a paste and paste “$employ”, and the IDE automatically deletes the space right after “$employ” and the “$employ” and “as” combine. So it ends up looking like this:

foreach( $employas $val ){

So you should realize the problem. What it is trying to do is auto indentation.

Fixing the Problem

Regardless whether you are using PHP or C++ or another language, you would do the same thing. In Eclipse, do the following steps:

  1. Select Window > Preferences.
  2. In the Preferences dialog, select PHP (or language you need to change) > Editor > Typing.
  3. In the Typing area and “When pasting” group, uncheck “Adjust indentation”.
  4. Click Apply.

Below is a screenshot for reference:

Auto_indentation

 

Specify Route with Parameters in Twig

Introduction

Twigis an extremely powerful PHP templating l anguage. For a student petition application (using Symfony framework) I was working on at Taft College, I needed to redirect to a route passing 2 parameters to use within the route controller. This is a post describing how to do that.

TWIG File

In my Twig file, I have a Table that shows various information from the petition. In one of the TD elements, I needed a “Change Program” link which would redirect to the change program controller passing in the student’s Banner ID (Banner is an Ellucian software product for Higher Education) and the student ID (the student identifier in my system).

The following Twig code shows how I achieved that:


<td><a href="{{ path('submitPetChangeProgram', {'banID':stu.getBanId, 'stuID':stu.getStuId}) }}">Change Program</a>
</td>

The “path” method specifies the route name to use, and I have in this case 2 parameters: banID, stuID. In the above code stu is a student object (passed in from controller), and both getBanId and getStuId are methods of the Student Doctrine Entity.

Controller File

The controller file uses routing annotations to take care of routes. Below is the routing annotation I used:

/**
* @Route("/submitPetChangeProgram/{banID}/{stuID}",
* defaults={"banID" = 0,"stuID" = 0},
* name="submitPetChangeProgram")
*/
public function submitPetChangeProgramAction($banID, $stuID, Request $request){

Each of the parameters banID & stuID are optional, and the “defaults” keywords sets the default values. Now you can directly use $banID and $stuID variables directly in your controller.

 

Installing OCI8 on RHEL

Introduction

If you plan to use PHP to connect to an Oracle database, then you’ll want to install OCI8, which is a pecl extension for Oracle. You can also use PDO_OCI as mentioned in The Underground PHP and Oracle Manual, however Oracle does not contribute to PDO_OCI; if you look this up (for example on stackoverflow), you’ll find a number of users have had various problems getting PDO_OCI to work. So installing OCI8 is highly recommended!

Stop Apache

Run the following command to stop Apache:

sudo service httpd stop

Install Instant Client

Go to Oracle’s instant client download page, and select the link for you Linux architecture. You’ll have to click on the “Accept License Agreement” radio button, and you’ll have to download it somewhere and then transfer it to your Red hat Enterprise Linux Server (RHEL). RHEL distro doesn’t have a GUI, but just CLI, so the easiest way might be to transfer via scp. Download the latest version and both the “basic” and “devel” RPMs.

After copying the instant client RPMs to your home directory, run the following commands to install the RPMs:

sudo rpm -Uvh oracle-instantclient12.1-basic*
sudo rpm -Uvh oracle-instantclient12.1-devel*

You then need to set the ORACLE_HOME environment variable:

cd ~
vi .bashrc
ORACLE_HOME=/usr/lib/oracle/12.1/client64
export ORACLE_HOME
:wq!

Install Pear & Devel

In order to install OCI8, you first need to get pecl. Also pecl will need the development packages. Run the following commands:

sudo yum install php70u-pear php70u-devel

Install OCI8

At this point you should be ready to install OCI8:

pecl install oci8

Observe the output carefully, and make sure no errors are shown. If any errors are shown, you might have to review the above to make sure you haven’t missed anything, also you might want to read through The Underground PHP Oracle Manual.

Then when oci8 is installed, you now need to edit the PHP config file to add the compiled oci8.so file:

sudo vi /etc/php.ini
extension=oci8.so

Add “extension=oci8.so” at the very bottom of the file.

Verifying OCI8 is Installed

First restart Apache:

sudo service httpd restart

Then create a phpinfo() file in your Apache Document root folder, so you can access it via web browser. Then open in any browser, and then search for “oci8”. Make sure that it is enabled.

Apache & Symfony on RHEL

Introduction

For a Symfony (an mvc framework) based project that I’m currently working, I’ve had to install Apache (2.2) and Symfony 3 (and PHP 7) on Red Hat Enterprise Linux (RHEL). This blog outlines the steps I had to go through. This may be helpful for someone in the future.

Install/Configure Apache

Installing Apache on RHEL is as simple as running the following command:

yum install httpd

You need to prepend the above command with “sudo” if you don’t have admin privileges (which is typical).

Once installed, you’ll need to edit the config file:

vi /etc/httpd/conf/httpd.conf

If you notice when using vi that comments are shown with a incredibly hard to read dark blue color, then you’ll want to edit your “~/.vimrc” file to at least add “:color desert”. You can read more about it in my vim runtime control blog article.

Edit the httpd.conf file to at least make these changes:

ServerAdmin youremail@somedomain.com
...
# Use hostname if dns can be used, otherwise use IP address.
ServerName machine.host.name:80
#ServerName 192.168.0.10:80

That’s enough config until we install Symfony. Use “:wq!” to save the changes.

Install PHP 7.0

By default, RHEL would install PHP 5.x (probably PHP 5.3 at this time), and this may not actually work for most modern PHP frameworks. PHP 7.0 has about a 2 times performance increase over PHP 5.x and it’s becoming readily adopted. Thus it’s highly recommended to install PHP 7.0 these days.

To install PHP 7.0 on RHEL, you’ll need to enable the EPEL and IUS repositories. Use the following commands (run in your home directory) to first install EPEL:

wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm
sudo rpm -Uvh epel-release-*.rpm

Then install the IUS repo:

wget https://centos6.iuscommunity.org/ius-release.rpm
sudo rpm -Uvh ius-release*.rpm

When you’re using yum to search for PHP 7.0 items to install, you need to search for “php70u”. This identifies PHP 7 verses PHP 5, which is simply “php”. Now to install PHP 7 and some of the requirements needed for Symfony (and other PHP frameworks), run the following command:

sudo yum install php70u-cli php70u-json php70u-ldap php70u-mbstring php70u-pdo php70u-mysqlnd php70u-xml php70u-process

After running the above command, run “php -v” to verify it shows PHP version 7.

Install MariaDB

You should probably now be using MariaDB instead of MySQL. If you’re not sure why MariaDB is preferable, read the MariaDB article on Wikipedia. On RHEL, you’ll need to add a repository file. First go to: https://downloads.mariadb.org/mariadb/repositories/ and follow the instructions by selecting a Linux Distro and selecting the latest stable version of MariaDB.

Copy the text generated and paste it into the repo file that you will create with vi:

sudo vi /etc/yum.repos.d/MariaDB.repo

Save the file in vi (“:wq!”), then run the following command:

yum install MariaDB-server MariaDB-client

After install, start the service:

sudo service mysql start

Verify it starts correctly. If it doesn’t, try to figure out why before proceeding. Then change the root password to something more secure (especially if this is going to be a production machine). Use the following command, where newpassword is what you want to change the new password to:

sudo mysqladmin -u root password newpassword

Install Composer

Composer is a dependency management software for PHP, and is needed for Symfony and many other PHP frameworks. Run the following commands:

cd ~
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('SHA384', 'composer-setup.php') === '92102166af5abdb03f49ce52a40591073a7b859a86e8ff13338cf7db58a19f7844fbc0bb79b2773bf30791e935dbd938') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"composer

This creates a “composer.phar” in your home directory. You need to copy it to the “/usr/local/bin” folder to make it globally available:

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

Run the command “composer” to verify it works.

Install Symfony Binary

Now install the latest Symfony binary. Don’t use the Symfony available with yum, since that is typically really old. Change to your home directory and run the following:

cd ~
sudo curl -LsS https://symfony.com/installer -o /usr/local/bin/symfony
sudo chmod a+x /usr/local/bin/symfony

Now, change to your Apache root web folder:

cd /var/www/html

Then let’s create a new Symfony project. This is a sample project that you can try out, and get to know how Symfony works:

symfony new testproject

Note: If for some reason “symfony” doesn’t run, you may need to run it from the absolute path or run with “sudo” or even using both. i.e. “sudo /usr/local/bin/symfony new testproject”.

The above creates the folder “testproject” under “/var/www/html”. Normally, you run the above commands as a system user not as the “apache” user, so you need to change the user:group of the folder and files. Do this recursively:

sudo chown -R apache:apache testproject

Also set some special permission on the var folder:

sudo setfacl -R -m u:"apache":rwX -m u:apache:rwX var
sudo setfacl -dR -m u:"apache":rwX -m u:apache:rwX var

Let’s go back to update the Apache config.

Apache Config

We need to update the DocumentRoot and Directory directives to the Symfony web folder we created above. The web folder will be under testproject, i.e. “testproject/web”. So make the following changes to the Apache config:

sudo vi /etc/httpd/conf/httpd.conf

DocumentRoot "/var/www/html/testproject/web"
...
<Directory "/var/www/html/testproject/web">
...
    Options Indexes FollowSymLinks MultiViews
...
    AllowOverride All
...
</Directory>

The above changes are needed also for mod_rewrite. Start the Apache server:

sudo service httpd start

Make sure it starts with “[OK]” normally, if not check the logs in “/var/log/httpd/”.

Verify Symfony Requirements

There were a large number of configuration items just performed, so it’s probably a good idea to check the Symfony requirements to verify everything you’ve installed is correct and no further changes are needed. There is a “symfony_requirements” script in the bin folder to achieve this specific purpose. From the “/var/www/html/testproject” folder run:

php bin/symfony_requirements

You should get a green [OK] if everything is fine, otherwise it prints out anything that you need to address.

RHEL SELINUX & IPTABLES

Most likely if you installed Apache fresh, then SELINX won’t be configured for the web folders, and quite possibly iptables are configured. Run the command “sudo iptables -S” to check the iptables configuration. If there is anything other than ACCEPT, and nothing specific to port 80, then most likely this will block your web port. Run “sudo iptables -F” to flush the tables.

The easiest way to quickly disable SELINUX is using “setenforce permissive”.

I’m not giving guidelines here on how to setup iptables or SELINUX, as for a production environment, a lot of thought should be put into correct configuration, and I only intend to show how to use Symfony here.

Checking Everything

Presuming your Apache server is running (run a “sudo service restart” if it is not), you should be able to use wget to check if everything is working “locally”:

cd ~
wget 192.168.0.10

This should copy an “index.html” to your home folder. Use “vi index.html” to check the contents. If you get errors, you need to investigate the problems.

After checking locally, use another machine and enter the hostname or IP address in the URL field of a browser. You should get a Symfony Welcome! message.