Functional Programming in PHP7. Higher Order Functions

I’ve decided to bring my notes out of Evernote and present them on a blog. I’ve been keeping programming notes for a while but it is only recently that I’ve decided to share them. Call it lack of confidence or whatever but I’m now ready for the Internet to review my work.

This post is based on some notes I made on functional programming with PHP7. It is a beginners level ‘functional’ post, but you’ll need to be quite advanced with more proceedural PHP to start. That’s where I was when I made these notes so I figure that best suits any readers.

The aim: is to look at two principles and see them working in some code. These two principles are

  • Static types
  • Higher order functions

Traditional PHP is normally more of a dynamically typed language meaning types are not required until runtime. This is still the case in PHP7 but we can make PHP more statically typed by enforcing static typing with

1
declare(strict_types=1);

By enforcing strict types any deviation from this now results in fatal php errors (1). Here is an excellent and thorough look at types in programming.

First of all we’ll make a function called toAll which is statically typed in the following way

1
2
3
4
// toAll :: (string -> ()), array -> ()
function toAll(callable $action, array $array): void {
}

Because functions in PHP7 are first class objects they can take and return functions themselves. Statically typing means telling PHP what we are passing in and what we are expecting out. Here you can see that we are passing in a callable object and an array. As we will not be returning anything from the function we use VOID because we are not using the return statement.

This is the complete function. For every item in the array we call callable, passing in the array item as an argument.

1
2
3
4
5
6
// toAll :: (string -> ()), array -> ()
function toAll(callable $action, array $array): void {
foreach($array as $elem) {
$action($elem);
}
}

The next function is a true higher order function because it returns another function. The important thing to notice is the use keyword which points at the file pointer which in turn points at the fwrite function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// writeToFile :: string, string -> (string -> ())
function writeToFile(string $path, string $mode = 'w'): callable {
if(is_dir($path)) {
throw new \Exception('File must not be a directory!');
}
$_fp = fopen($path, $mode);
if(!($_fp && is_resource($_fp))) {
throw new \Exception('Error opening file!');
}
return function ($contents) use ($_fp) {
fwrite($_fp, "$contents\n");
};
}

Setting things up like this allows us to use this in the following way.

1
2
3
4
5
6
7
8
9
10
11
12
13
$writer = writeToFile('file_to_write_to.txt');
$writer('<p>First Paragraph</p>');
$writer('<p>Second Paragraph<p>');
// change the mode to append
$appender = writeToFile('file_to_write_to.txt', 'a');
// use the toAll function we made to apply to each element of the array
toAll($appender, ['Functional', 'PHP', 'Rocks!']);
// apply the string to upper to each element of the array, then apply to the appender
toAll($appender, array_map('strtoupper', ['Functional', 'PHP', 'Rocks!']) );

We end up with a text file with the following in it

1
2
3
4
5
6
7
8
<p>First Paragraph</p>
<p>Second Paragraph</p>
Functional
PHP
Rocks!
FUNCTIONAL
PHP
ROCKS!

It is possible to see how this style of programming opens many possibilities over the more procedural or OO style often associated with older versions of PHP.

Five Reasons to use a NoSql Database

Yesterday I had a job interview. It was the first of two parts and it was done over the phone. On my CV I had put my experience with Mongodb which was based around some dashboard code written to monitor clicks on a website. I’ll dig that out and post it when I get chance because it was pretty cool. Anyway I digress … One of the questions I was asked was about Mongo was in what circumstances would I use it over a normal relational database.

In the heat of the interview I failed badly and couldn’t think of any particular reason. After I put down the phone I sat thinking and was able to come up with one reason. I was really not satisfied with only one, so I went away and looked up some others. Here they are, five reasons to use NoSql.

  • NoSql databases are schemaless meaning significant benefits when creating, upgrading and changing structure and data. Tables are known as collections and rows as documents. Documents can be significantly different in the same collections meaning a ‘dangerous’ amount of flexibilty. Makes it super easy to collect data when you don’t have all the data and you don’t need to enforce contraints.

  • Changing the structure of a collection doesnt mean lots of downtime while backups are made and new columns added. It takes a lot of time to add a new column to a table with millions of records.

  • Data is stored as Json and queried with Json meaning clean and semantic questions that make sense and don’t get confusing with horrible joins. Just look at this query on Stackoverflow. Yikes.

  • Speed. High speed delivery of Json with built in entity level caching out of the box in many cases.

  • It’s different. Just bear with me here. I’m a big fan of thinking outside the box and looking at different ways of doing things because more often than not, we hold old established views on things that need revsiting from time to time. Thinking differenty about the fundamentals is healthy. Ask more questions!

Bonus

I was so exited about the feelings this stirred up ! (honestly) that I fired up node and installed Mongodb. Can you guess what this does?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Retrieve
var MongoClient = require('mongodb').MongoClient;
// Connect to the db
MongoClient.connect("mongodb://localhost:27017/exampleDb", function(err, db) {
if(err) { return console.dir(err); }
var collection = db.collection('test');
var docs = [{mykey:1}, {mykey:2}, {mykey:3}];
// insert
collection.insert(docs, {w:1}, function(err, result) {
// find
collection.findOne({mykey:1}, function(err, item) {
// do something with the item !
});
});
});

That’s quite lovely right?