# Scalar Type Declarations and Return Types in PHP 7

> A practical look at how I use scalar type declarations and return type definitions introduced in PHP 7.

- Published: 2016-01-03
- Category: Languages
- Tags: PHP
- Reading time: 3 min read
- Source: https://www.muhammetsafak.com.tr/en/blog/scalar-type-declarations-and-return-types-in-php-7/
- Language: en-US
- Author: Muhammet Şafak

---
A few weeks have passed since I [moved to PHP 7](/en/blog/php-7-0-the-long-awaited-release-speed-and-type-declarations/). The performance gains were already on everyone's radar, but what really drew me in were the language-level features: scalar type declarations and return types. Once I started using them in my projects, I noticed just how much more expressive function signatures become.

In this post I'll walk through how I use both features, what difference `strict_types` mode makes, and a few things worth keeping in mind.

## What are scalar type declarations?

Since PHP 5, you could declare types for class names and arrays. PHP 7 extends this to scalar types: `int`, `float`, `string`, and `bool`.

```php
<?php

function toplam(int $a, int $b): int
{
    return $a + $b;
}

echo toplam(3, 5); // 8
```

Back when I wrote this kind of function in PHP 5, I'd just add a docblock for the parameter types; even [PHP 5.6's variadic parameters](/en/blog/php-5-6-new-features-variadic-functions-and-exponentiation-operator/) could only carry so much of that into the signature. Now I can put that information directly in the signature — IDE support improves, and anyone reading the code immediately knows what the function expects.

## Strict mode with `strict_types`

By default, PHP performs type coercion. If you pass `"5"` to a function that expects `int`, PHP will silently convert it to `5`. That behavior is occasionally convenient, but more often dangerous.

Adding the following declaration at the top of a file removes that flexibility:

```php
<?php
declare(strict_types=1);

function carpim(int $a, int $b): int
{
    return $a * $b;
}

carpim(4, "3"); // Throws TypeError
```

The `strict_types=1` declaration applies only to the file it appears in, not the entire application. This is an important detail: the file that matters is the one making the call — if the calling file has `strict_types` enabled, no coercion happens even when the file where the function is defined has it disabled.

I've made it a habit to add this declaration to every new file I write. It took a bit of adjustment at first — form data from users always arrives as strings, so you need to cast explicitly. But that's actually a good thing: you can now see exactly where your code performs type conversions.

## Return type declarations

You can also declare what a function returns, right in its signature:

```php
<?php
declare(strict_types=1);

function kullaniciBul(int $id): array
{
    // fetch user from the database
    return ['id' => $id, 'ad' => 'Ahmet'];
}

function aktifMi(int $id): bool
{
    return $id > 0;
}
```

This is especially useful for functions that return `bool`. Previously, without checking the docblock, you had to read the function body to answer "what does this return?"

### A note on the `void` return type

PHP 7.0 does not yet have a `void` return type — that arrives in PHP 7.1. For now, you can only annotate functions that actually return a value.

## Nullable types aren't here yet either

Similarly, the `?int` syntax is also a PHP 7.1 feature. If a function can return either `int` or `null`, you currently have to either leave out the return type declaration or document it via a docblock.

```php
<?php

// Workaround for nullable in PHP 7.0
// We can't write the return type, so we document with a docblock

/**
 * @return int|null
 */
function sonKayitId()
{
    // returns null if the table is empty
    return null;
}
```

This limitation is annoying, but I can wait for 7.1. What matters now is building the habit of writing type declarations.

## What has changed in practice?

After a few weeks of experience, here is what I can say: type declarations turn a function signature into a contract. I'm telling the person I'm working with — or my future self — "pass this type, get this type back." Error messages have also become far more readable; when you get a `TypeError`, you immediately know where the problem is.

On the other hand, retrofitting types onto an existing codebase needs to be done very carefully. Legacy code that relies on implicit coercion can blow up in unexpected places once `strict_types` is in the picture. The sensible approach is to use it immediately for new files and tread carefully with existing ones.

PHP 7 has taken a more useful step here than I expected. It's encouraging to see the language moving in this direction.
