From the course: Functional Programming with PHP

Functions as data, part 1 - PHP Tutorial

From the course: Functional Programming with PHP

Start my 1-month free trial

Functions as data, part 1

- [Instructor] I mentioned in a previous video that functional programming treats functions as first class citizens. Meaning that we can treat functions in a very similar way to other types, such as strings, numbers, or objects. In this video, we're going to take a look at what this means for our code and a few useful things we can do with it. First of all, if you're not using the exercise files, now's a good time to create a directory to hold your example code. Just create an empty directory called functional-php or something like that and open it up in the editor of your choice. I'm going to create a new file called functions_as_data.php, and this is where we'll write the code for this video. So, for our examination of first class functions, let's start off with the fact that there are two main ways to define a new function in PHP. The first is by starting off with the function keyword like this, function my_function, and then inside we have the function body. The other way is by defining functions in the same way that we'd define any other type. And here's what that looks like. We can say $my_function equals function, and then the function body. Now, when we define a function like this, we can call it by just adding parentheses after it. Like my_function parentheses, but we can also do something like this. We can say, my_function_2 equals my_function. And then, what we can do, is call my_function_2 just by adding parentheses after it and it will behave exactly like our original my_function, my_function_2, parentheses. If you want to run this and see for yourself, just open up a terminal and make sure it's in our functional-php directory that we created, and then just run it with php functions_as_data.php. So, we can see right here that functions in PHP already behave like other types. And this is true, too, if we add arguments to the function. For example, if we say name, then we can say, "Hello name," and then add a name in here. And if we run our code again, we see that it works just as well that way, even though the function that we just made the change to was my_function and the function we're calling is my_function_2, because we said here that my_function_2 is equal to my_function. So again, as we've seen here, we can define functions using the same syntax that we use when defining other types, such as numbers or strings. And just like with these other types, we can do interesting things when assigning. For example, we can do stuff like using a ternary operator to dynamically change a function's definition. And one possible application of this is for mocking out pieces of our code during development. If we have a piece of code that's especially time intensive, such as network or database operations, or a piece of code that's destructive, such as a piece of code that deletes a whole database, it can really get in the way of our development if we have to test the code around it. So, what we can do is define a mocked out version of our function that returns some fake data, and use first class functions to determine when we should use the fake version and when we should use the real version. So, don't worry if that doesn't make sense just yet. We're going to go through it piece by piece and see what this looks like in code. So, what we're going to do first is define our network operation function. In the real world, this function would probably do something like fetch data from an API. So, we'll call our function fetch_data_real, and then define it with no arguments. And then, inside this function body here is where the time intensive operations would take place. But in order to keep this example simple, we're just going to print something to the console saying "Fetching data." Now, let's define a stub function that will return fake data. The idea here is that we could use this fake data for development without having to wait for whatever lengthy operations the real function has to complete. We'll call this function fetch_data_fake, and again define it with no arguments. And inside this function, let's say that the data we're supposed to be fetching is a person's data from a database. So, what we're going to do is just return some fake person data, which looks something like this. Name, Jane Doe, age, we'll say 35, and job, programmer. So now, we have our real fetch data function, which in the real world would actually fetch data from a database or something, and our fake fetch data function. Now, we need to define the function that decides between the two. But in order to do this, what we're going to do is define some sort of environment variable. We'll call it environment, and we'll set it equal to either dev or prod. For now, we'll just set it to dev. So now, what we're going to do, is we're going to define the actual function that we'll use elsewhere in the code base. We'll just call it fetch_data. And then, what we're going to do is based on the value of this environment variable that we defined up here, we're going to say if environment equals dev, then we're going to set fetch_data to fetch_data_fake. Otherwise, we'll set it to fetch_data_real. And that's all there is to it, really. We can now call fetch_data with parentheses after it, and it will return this fake data that we defined inside of here. So, if we say print_r fetch_data and run our code, we see that since the environment is equal to dev up here, fetch_data is equal to fetch_data_fake. If we were to set the environment variable to prod, for example, and run our code. It would print fetching data down here since now fetch_data is equal to this fetch_data_real function that we defined. And that's really all there is to it. Obviously, in a real application, our code would look a little different. But for illustration purposes, this example is fine. And there are many other applications for this sort of function assignment, too. For example, if you wanted to do stuff like A B test different implementations of a function.

Contents