Typed Drupal - A great combination of Drupal 8 and PHP7

Posted by Aditya Ghan on Oct 25, 2017 5:08:55 AM

(Note: This article is based on my talk on this subject at DrupalCon New Orleans as well as at various DrupalCamps)

We all know how great PHP7 (the latest version of PHP, released almost two years back) is, it’s a radical improvement over PHP 5.6 and it’s fast becoming the de-facto PHP version. There are loads of brand new features in it, like Scalar Type Hinting, Null Coalescing Operator, Return Type Declarations to name a few. Now, Drupal 8, the latest version of our beloved Drupal is out for at least two years, and it seems to me that the Drupal 8 and PHP 7 combo hasn’t got much attention which it deserves. This piece is my attempt to explain how we could leverage PHP7’s features to write some great drupal 8 code (and great code in general)

Let’s start with the term “Typed Drupal”, it means the typing features of PHP7 (Scalar Type Hinting, Return Type Declarations) are a great fit to Drupal 8, and we could use them in our Drupal 8 code for a more robust and bug-free experience. We will go through the typing features, but before it, let’s look at the pre-PHP7 type system which we are using now:

Type System of PHP

Traditionally PHP had a Weakly Typed / Loosely Typed system. A Weak type system is a system where type checking is loose, the datatype of a value is not strictly checked with the data type of the variable to which it is assigned, let’s look at an example below:

typeddrupal1

In the above example, compare_function is a function which expects two integer parameters, compares the two integers and says, which integer value is less / greater than the other. Please note that while calling the function, we are passing the first value as 10 and the second value as ‘foo’. Technically and aesthetically, the integer 10 and the string ‘foo’ cannot be compared, but this piece of code gives us the following output:

typeddrupal2

This is a problem, as the piece of code works perfectly well with no warnings or errors. We will assume everything is hunky-dory but the wrong unintended output will mess up something else in the execution flow and we have no easy way of knowing it, debugging it will be a nightmare. The code example shown above is a very simple example, working practical code is much complex and that makes matters worse.

The above behavior is called as Type Juggling and we need to get rid of it.

Enter PHP7!

Now is the ripe time to learn about the typing features of PHP7:

    1. Scalar Type Hinting - We can now use type hints for scalar types: int, float, string, and bool in our function arguments.
    2. Return Type Declarations - Return type declaration allows us to define type hints for a function’s return value. If return type declaration is made for a function, function’s return value must match of that the declared type.

See the below code snippet:

typeddrupal3

Here, adi_function accepts one parameter which is type hinted to ‘int’ (integer) and this function also defines its return type as ‘int’. This is how we could use the typing features in PHP7. Prior to PHP7, we were not able to define a return type of a function at all, and we could type hint a function argument for non-scalar types only (Arrays, Objects, Callables) only.

Now, if you are a Java or C++ programmer, you must be smiling smugly thinking how come such features were missing in PHP prior to PHP7. Well, PHP was not a hardcore programming language to start with, it was simply a preprocessor language for HTML where we could embed PHP scripts inside HTML to add some dynamism to the HTML pages. But now, PHP has evolved to a much more sophisticated and widely adopted programming language, it's the most widely used language to create web applications and there are a plethora of frameworks built on top of it. The current scope and scale of PHP demand a robust type system, which PHP7 introduced. but there is a catch:

Strict vs Weak Mode -

Weak mode

There are two ways you could use the typing features, in a Weak Mode or a Strict Mode. The weak mode is the default mode in which PHP7 operates. The weak mode will not enforce type checking, it will try to convert the type of the passed value to the type of the function argument. Consider this example:

typeddrupal4

Though Weak mode is the default mode in PHP7, you can make that more pronounced by using the directive declare(strict_types=0); as the first line of your code file. In the Weak mode, PHP will try to convert the type of the passed value to the data type of the function argument. In the above example, adi_function expects one integer parameter but we are passing it a string ‘1’. It converted the string ‘1’ into an integer and the function call worked giving us an output 1. However, there is a catch here too, see the below example:

typeddrupal5

Here, we passed the string ‘hey’ instead of the string ‘1’, this time, however, the function didn’t accept the string value and threw off the TypeError. In short, there are limits in which type juggling can happen in PHP7, even in the weak mode.

Strict mode

This is the only way for us to actually use the typing features, to use this mode, add the below line as the first line in your PHP file.

declare(strict_types=1);

After adding this line, all the functions calls which are made in this file will follow the strict mode, irrespective of where the function is defined.

See the below example:

typeddrupal6

Here, the function adi_function accepts one integer and we are passing it an integer, so everything is fine here. However, in contrast to the weak mode, here the system will NOT accept anything else apart from an integer value here, in the strict mode. The below snippet which worked in the Weak mode, will not work in the strict mode:

typeddrupal7

The system will throw a TypeError if there is a type mismatch.

The whole Strict vs weak mode concept was introduced to preserve PHP’s flexibility and dynamism, so in nutshell, PHP will not force you to follow type hinting but you would use the strict mode and take benefits of the new typing features. For example, if you are a library owner, you could type hint your entire function definitions and use strict mode internally while calling those functions. The consumer of your library will use your library can use it via the Weak mode or Strict mode, that’s left to him.

Advantages of Scalar Type Hinting -

Less Bugs

Using Type hints and Return type declaration can significantly reduce hard-to-find bugs related to type mismatch, as PHP7 will throw off a TypeError in case of a type mismatch, which by the way, you could handle in the same way as you handle exceptions.

Self - Documented Code

Using Type hints and Return type declarations would make your function definition more concrete. Just by looking at the function, I could get a complete idea of what the function does, which type of arguments it accepts and what are its return types.

Static Analyzers and IDEs may spot mistakes before execution

There are many smart static analysis tools which may spot typing mismatch as you code saving you time from future error correction. For example, if you are assigning a string value to an integer parameter, your IDE or static analyzers could spot the mistake then and there allowing you to correct it quickly.

Fewer Unit Tests

As you don’t need to worry about type mismatch in your code (PHP7 will throw off errors in case of a type mismatch), there is no need to write unit tests to check data types of the variables and return values, which reduces the number of unit tests.

No isset and empty checks -

There are some is_* functions in PHP which are used to check return values of the function or of variables. These are check functions which could be completely avoided thus reducing the total lines of code. Type hinting ensures that the return values of a function or function arguments are of a particular type and are not empty.

Some points to note:

Here are some points we need to keep in mind while using the Typing features in PHP7

  1. The only type conversions allowed is int to float, i:e Float parameter type can accept an integer value, even in the strict mode.
  2. NULL is still allowed as a default value for a type hinted function parameter.
  3. You cannot return NULL when you have given return types for a function

Conclusion

Drupal 8 development using Typing features of PHP7 provide a more robust development experience with many benefits as we have seen above. The current scope and scale of PHP demand a robust type system, which PHP7 introduces. I hope the above blog would help you kickstart ‘Typed Drupal’!.

Tags: Drupal