
Functions are fundamental to writing code, making it vital that you write them well to become a better PHP Developer.
Well-written functions make your code efficient, easy to read and reduce the chance of errors.
Here is a list of advice on writing good functions with PHP examples, as detailed in Robert C. Martin’s book titled Clean Code:

1. Functions should do one thing
As a rule of thumb, functions should have one level of abstraction.
If there is more than one level of abstraction, not only is your code doing too much. It is difficult to understand for the reader and allows the possibility for other programmers to misinterpret the important parts of the code.
Take a function, for example:
public function getCategoriesFromSongID(int $songId): array
{
$arrayOfCategories = [];
$songInformation = $this->getSong($songId);
foreach ($songInformation['categories'] as $category){
array_push($arrayOfCategories, $category);
}
return $arrayOfCategories;
}
This is doing multiple things:
- Getting song information using the song ID.
- Looping through the array of categories in the song information and saving it to an array.
We can split this into two functions like so:
public function getCategoriesFromSongID(int $songId): array { $songInformation = $this->getSong($songId); return $this->getCategoriesFromArray($songInformation['categories']); } private function getCategoriesFromArray(array $categories): array { $arrayOfCategories = []; foreach ($categories as $category){ array_push($arrayOfCategories, $category); } return $arrayOfCategories; }
2. Functions should be small enough to understand in a few minutes
A large function takes time to read through.
It likely has too many levels of abstraction and has a few sections of code which do different tasks.
This is an ideal candidate for a function doing too much.
As a rule of thumb, try to make your functions less than 30 lines of code.
3. Switch statements should be buried in an abstract factory where possible
Switch statements are dangerous.
And while they are unavoidable, it’s easy to break the SOLID principles of programming.
A switch statement used in a high level of the code does the following bad practices:
- Does multiple tasks
- Is Open for modification, which can lead to bugs.
Where possible, bury your switch statement using polymorphism to create an abstract factory.
That way, your switch statement does not need to be repeated anywhere.
4. Code should be readable from top to bottom by using the step-down rule
Your code should read in a sequential format, and the best way to do this is by starting each sentence by describing what your code does with a ‘To’:
- To take a payment, we must decide which payment to take
- To decide which payment to take, we must see what payment method the user has.
- To accept the specific payment method, we must check to see if the user has enough balance on their payment method.
- To complete the payment, we must take the payment amount from the user.
- To complete the payment, we must confirm that payment has been accepted.
This is a great way to plan out your class before you write it.
5. Use Descriptive Names
Function names should detail exactly what the function does.
To this best, use a verb/noun pair for the function and then the argument:
public function get writeField($name)
This tells us what the function is doing (writing to a field) and with what property ($name).
The goal is to prevent the reader from doing a double-take, and descriptive words do just that.
6. One argument for a function is ideal, any more gets messy
As you saw with writeField($name), it is easy to see what the function does just by reading the function.
But what about when you have two arguments in the function?
writeField($firstName, $lastName)
You can see that the rule to do one thing per function rule has been broken, as we are writing a field for the first and last name.
We also introduce the opportunity for accidental bugs. What if we call the function and enter in the last name as the first argument and the first name as the last.
This gets worse with three arguments:
writeField($firstName, $lastName, $createAccountFlag)
As we add more data the reader has the spend more time re-reading the function to understand what the function does.
A function which accepts three arguments or more, needs to be wrapped into its own class.
7. Functions should not do anything unexpected
There should be no side effects of a function.
Let’s say we want to see if a user has admin access to view an admin page:
public function $checkUsersAdminAccess(User $user): bool
{
if (null != $user->getAdminRights()) {
session_start();
return true;
}
return false;
}
What the function says we are doing is to check admin access of a user. Which we are doing. But we are also starting a session if the user does have admin access.
This is a side effect. It’s a part of the code that executes, which is not described in the function.
A better way to describe the function would be $checkUsersAdminAccessAndStartSessionIfAuthorized.
But this breaks the one function must do one thing rule.
8. Do not repeat yourself in functions
If you write functions which seem to be referencing the same code, write a function for it.
This is an example of repeated code:
public function getCategoriesFromAlbumID(int $albumId): array { $arrayOfCategories = []; $albumInformation = $this->getAlbum($albumId); foreach ($albumInformation['categories'] as $category){ array_push($arrayOfCategories, $category); } return $arrayOfCategories; } public function getCategoriesFromSongID(int $songId): array { $arrayOfCategories = []; $songInformation = $this->getSong($songId); foreach ($songInformation['categories'] as $category){ array_push($arrayOfCategories, $category); } return $arrayOfCategories; } public function getCategoriesFromArtistID(int $songId): array { $arrayOfCategories = []; $artistInformation = $this->getArtist($artistId); foreach ($artistInformation['categories'] as $category){ array_push($arrayOfCategories, $category); } return $arrayOfCategories; }
Where you can see the foreach loop is repeated throughout every function.
You put the repeated code into its own function.
public function getCategoriesFromAlbumID(int $albumId): array { $albumInformation = $this->getAlbum($albumId); return $this->getCategoriesFromArray($albumInformation['categories']); } public function getCategoriesFromSongID(int $songId): array { $songInformation = $this->getSong($songId); return $this->getCategoriesFromArray($songInformation['categories']); } public function getCategoriesFromArtistID(int $songId): array { $artistInformation = $this->getArtist($artistId); return $this->getCategoriesFromArray($artistInformation['categories']); } private function getCategoriesFromArray(array $categories): array { $arrayOfCategories foreach ($categories as $category){ array_push($arrayOfCategories, $category); } return $arrayOfCategories; }
Now you have more functions, but less repeated code.
9. Don’t be afraid to rewrite your function
Like with writing an essay, writing a function will be a bit messy when you first write it.
Once you get your thoughts down, spend the time to rewrite your function.
It will be more structured the second time you write it.
10. Error handling is one thing
A try catch statement which handles errors, should be ran as a function and nothing more.
Meaning the function should begin when the try statement starts and end when the catch/finally statement ends.
public function addListOfSongsToLibrary(array $listOfSongIds)
{
try{
foreach($listOfSongIds as $songId){
$this->addSongToLibrary($songId);
}
} catch(\Exception $e) {
$e->getMessage();
}
}