Pull to refresh

Return types of PHP methods or what a method must return

Probably, for many developers the idea of this article will be obvious and it is fine.

Over the years in the development of applications in PHP, sometimes I come across methods, even from popular small libraries, which sometimes return strange or unexpected data types.

Sometimes on code review, I can see methods that return anything but the right data structure or type.

This is an example of how not to do this

The method returns object or boolean, for what?

<?php
//...
private function getObject(int $id) 
{
  $object = Model::find($id);
  if (empty($object)) {
     return false;
  } 
  return $object;
}

Why does the method return int if we expect a string?

<?php
//...
private function getSomeString(string $string) 
{
  if (empty($string)) {
     return 0;
  }
  //some manipulations with the string $myString
  return $myString;
}

etc.

A method should return the only type that is expected from the method or nothing if it is void.
The method should not return different data types when different conditions are triggered.

Key thing is that if the method returns different types it can break executable code that expects specific data type from that method.

For simple data types, everything is clear

If we expect from the method certain data type, so the method should return expected type:

<?php
//...
private function isAdmin(): boolean
{
  if ($this->roleId === User::ADMIN_ROLE) {
  	return true;
  }
  return false;
}
<?php
//...
private function getTitle(int $id): string 
{
  $post = Post::find($id);
  if (empty($post)) {
     return '';
  }
  return $post->title;
}


 For more complex types, the method has to stick to one data type structure.

If the method should return object, so return object or null if it is not found
<?php
//...
private function getPost(int $id): ?Model
{
  $post = Post::find($id);
  if (empty($post)) {
     return null;
  }
  return $post;
}

But

For array or collection types the circumstances are a little different.

Method which returns such type should return array or collection in any case

So, if we expect from the method array, we must get array even the array is empty:

<?php
//If today is monday returns discount list
private function getMondayDiscounts(): array 
{
  $discounts = [];
  
  if (date('w') === '1') {
    $discounts = Discount::getDiscounts();
  }
  
  return $discounts;
}

So, if we expect from the method collection type, we must get a collection. 
The method returns collection with user or empty collection if that users not found:

<?php
//Get all users where role is admin
private function getUsers(): array 
{
 return User::where('roleId', User::ADMIN_ROLE)->get();
}

Scenario for Exceptions.

The Exception should be thrown if the method found an error during the task execution, not to be confused with the lack of data

In our case below Exception is triggered if smtp key is not exist in config file, but if the method just returns null although in reality key is not exist this is misleading to the developer who will use method.

<?php
//...   
private function smtpGetConnection(): SenderService
{
  $smtpKey = Config::get('smtpKey');
   
  if (empty($smtpKey)) {
    throw new Exception\SmtpConnection('Key connection is not found!');
  }
  
  return new SenderService($smtpKey);
}

In conclusion, practices described above are not the last truth, there are situations when this approach for return types is not suitable.

But in general this approach makes the code cleaner and more logical, that brings less errors or bugs.

Thank you!

Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.