Elegant code in PHP

Jorge Castro
Cook php
Published in
8 min readAug 10, 2019

One of the problems of PHP is not the language but how some developers do a poor job and PHP gives the freedom to do everything, especially bad code. It’s a common solution to use a framework, but it presents several issues and difficulties:

  • Most frameworks are painfully slow so they are not suitable for every situation.

This chart is old but it still marks some trend.

  • It requires to train the team in the use of this framework.
  • They bring new troubles.
  • Lots of Dependencies!. Dependencies are painful. We don’t simply download a library from the net and that’s it. We should keep it update, and some updates break our code (ahem, Wordpress) but those updates are required, so we are forced to work extra time. Dependencies works in the next basis = less is better
  • They add a lot of code, they bloat our code. Laravel, for example, adds +600 classes for only for a single Hello World. Symfony does a better job, but not for much.
  • And we are not free of bad code.

So, we will work in what it’s known as “vanilla” PHP.

For example, let’s say we want to create a web that shows a name.

example1.php

<?php$name=$_POST['name'];?>
<h1>Example</h1>
<?php if($name) {?>
<?=$name ?> is a nice name.
<?php } else { ?>
<form method="post">
<input type="text" name="name" value="">
<input type="submit" value="Send">
</form>
<?php } ?>

And it is the result:

  • Why?
  • It is because $_POST[‘name’] is undefined the first time we open the webpage (because we are not send anything yet).

The system works, but it shows an annoying warning.

Bad code

Now, let’s show the same but worse.

example1.php

<h1>Example</h1>
<?php if($_POST['name']) {?>
<?=$_POST['name'] ?> is a nice name.
<?php } else { ?>
<form method="post">
<input type="text" name="name" value="">
<input type="submit" value="Send">
</form>
<?php } ?>

We are saving a couple of lines of code but we are breaking usability, stability, and clarity, i.e. everything. Also, this code is not scalable.

  • Why?
  • We are reading $_POST[‘name’] two times, we are adding more code in between the HTML and what if something goes south? (in this case, $_POST raises a warning)
  • It is not scalable. What if our code requires 20 or 30 fields? Yes, it would be horrible to write.

So, let’s clear our code.

User Input

We could disable every warning (and error) on PHP’s INI file, but it is not the way to work. Errors and Warnings are our friends; they pinpoint us where there is something that must be fixed.

One solution is to use ISSET

if isset($_POST['name']) $name=$_POST['name'] else $name=null;

However, it’s easy to do this one:

$name=@$_POST['name'];

We could pick any of them, they work and they are clear. One problem less.

View

The second problem is the code, its horrible.

It is the definition of spaghetti code:

?>
<h1>Example</h1>
<?php if($name) {?>
<?=$name ?> is a nice name.
<?php } else { ?>
<form method="get">
<input type="text" name="name" value="">
<input type="submit" value="Send">
</form>
<?php } ?>

We are mixing logic with HTML. It calls for troubles.

There is a concept called 3-layer-architecture.

For our case, we don’t have a persistence (data access) layer. Then, we could separate our code in two.

Is it more code?. Yep but not so much.

Why?

  • Let’s say we have a design on HTML and we want to integrate.
  • Or if we have a web designer and he or she doesn’t know (or care) about PHP.
  • Or if we want to refactorize the UI, for example, to add changes to the UI without touching the code.

example2.php

<?php$name=@$_POST['name'];include "example2ui.php";

example2ui.php

<h1>Example</h1>
<?php if($name) {?>
<?=$name ?> is a nice name.
<?php } else { ?>
<form method="get">
<input type="text" name="name" value="">
<input type="submit" value="Send">
</form>
<?php } ?>

So, we separate our code in two. One is the “logic,” and the second is the view (HTML).

We are doing it fine but example2ui.php is still ugly. Ugly in the concept that we can’t hope a web-designer could work with it. Also:

Security

Let’s say our name is :

Mister < script >alert(‘hi’);< /script >

Why?. Fathers hippies or something like that.

It is the result:

It is a simple alert, but it opens the door to hackers. A simple alert is harmless, but what if this code sends information to a remote server.

example2ui.php

<h1>Example</h1>
<?php if($name) {?>
<?php echo htmlentities($name); ?> is a nice name.
<?php } else { ?>
<form method="post">
<input type="text" name="name" value="">
<input type="submit" value="Send">
</form>
<?php } ?>

We added htmlentities(), so our view is safe.

However, our view is still spaghetti.

And what if we have 20 or 30 variables and 30 or 40 pages. Our solution is not scalable at all. Why? Because it is prone to mistakes. What if we forget to use hmtlentities() (20 variables x 30 pages = 600 changes to commit a mistake).

View (revisited)

We must do something about our view. First, our view must be safe, and second, our view must be easy to write and to maintain. The solution is to use a template library, and we will use the next one:

BladeOne is a standalone version of Blade Template Engine that uses a single PHP file and can be ported and used in different projects. It allows you to use blade template outside Laravel.

NOTE: So far it’s apparently the only one project that it’s updated with the latest version of Blade 5.8 (March 2019). It misses some commands missing but nothing more.

NOTE about questions, reports, doubts or suggestings:

✔ If you want to open an inquiry, do you have a doubt, or you find a bug, then you could…

View on GitHub

How to install it? It could be installed via composer, but it could be downloaded. It is a simple file.

Let’s say we don’t want to use Composer (it is recommended); then we could download this file:

https://github.com/EFTEC/BladeOne/blob/master/lib/BladeOne.php

It is our third version:

example3.php

<?php
include "BladeOne.php"; // our file downloaded from Internet.
$name=@$_POST['name'];$blade=new \eftec\bladeone\BladeOne();
$data=['name'=>$name]; // data to send from our logic -> view
echo $blade->run('example',$data);
  • It includes our library
  • It reads the information from POST.
  • Then it creates a new instance of the class BladeOne
  • Also, we collect our information. What we should show.
  • Finally, we join our “view” (called example that corresponds to the file /view/example.blade.php) with our data.

And our view

/view/example.blade.php (we need to create a folder called view)

<h1>Example</h1>
@if($name)
{{$name}} is a nice name.
@else
<form method="post">
<input type="text" name="name" value="">
<input type="submit" value="Send">
</form>
@endif

This view doesn’t contain any PHP code but it uses some sort of new annotation:

  • @ to call some methods defined by Blade.
  • { { } } to escape (htmlentities()) a variable
  • { !! !! } to show a variable un-escaped.

It is based on Larave’s Blade language. It’s quite simple: some conditionals, show some value, loop another value, include this and these. It is not a programming language, so a smart web designer could learn it in a weekend.

It is our result:

Fine but ugly. So, let’s modify our view.

4th version:

example3.php (it’s the same than the 3rd version)

<?php
include "BladeOne.php"; // our file downloaded from Internet.
$name=@$_POST['name'];$blade=new \eftec\bladeone\BladeOne();
$data=['name'=>$name]; // data to send from our logic -> view
echo $blade->run('example',$data);

/view/example.blade.php

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<div class="container">
<div class="row">
<div class="col">
<div class="card">
<div class="card-header">Example</div>
<div class="card-body">
@if($name)
<div class="alert alert-primary" role="alert">
{{$name}} is a nice name.
</div>
@else
<form method="post" class="form-inline">
<input type="text" class="form-control col-3" name="name" value="">&nbsp;&nbsp;
<input type="submit" class="btn btn-primary" value="Send">
</form>
@endif
</div>
</div>
</div>
</div>
</div>

It is our result:

What is the extra work?

  • Adding our library costs to download the file, include the file, 3 new lines and edit the template.
  • Our whole project consists of 3 files (and one folder). BladeOne will generate a new file (and a new folder), so the total is 4 files and 2 folders.

So, it doesn’t mean to work extra, even this lazy cat could do it.

Final Question

Oh wait, is it not MVC?.

Yes, it is a basic version of MVC:

  • example3.php is the CONTROLLER
  • /view/example.blade.php is the VIEW
  • and $data is the MODEL (some people call MODEL the data access layer).

And it is also 3-layer friendly. And it complies with SRP. And it’s also KISS. Nice.

Note

Programming is exactly like surfing. We must follow the flow (What we call architecture, pattern or other names)

We could use a framework.

Easy but not cool.

We could do a spaghetti code.

And it is valid for every language.

Note: Also published on

--

--