Nullable Types
Part of the Object Oriented Programming section of Coddy's PHP journey — lesson 64 of 91.
Sometimes a value legitimately might not exist. A user might not have a middle name, or a search might return no results. Nullable types let you explicitly declare that a parameter, return value, or property can be either a specific type or null.
Add a question mark ? before the type to make it nullable:
<?php
class User {
public ?string $middleName = null;
public function __construct(
public string $firstName,
public string $lastName
) {}
public function getFullName(): string {
if ($this->middleName !== null) {
return "$this->firstName $this->middleName $this->lastName";
}
return "$this->firstName $this->lastName";
}
}
$user = new User("John", "Doe");
echo $user->getFullName();
Output:
John DoeNullable return types work the same way. This is useful when a method might not find what it's looking for:
<?php
class UserRepository {
private array $users = [];
public function find(int $id): ?User {
return $this->users[$id] ?? null;
}
}
$repo = new UserRepository();
$user = $repo->find(1);
echo $user === null ? "Not found" : $user->firstName;
Output:
Not foundUsing nullable types makes your code's intent clear. When you see ?string, you immediately know that null is a valid value and should be handled. Without the question mark, passing null would cause a type error.
Challenge
EasyLet's build a contact management system that handles optional information gracefully using nullable types. Not everyone provides all their details, so your system needs to handle missing data elegantly.
You'll organize your code across three files:
Contact.php— Create aContactclass that represents a person in your contact list. Some information is required, but other details are optional:- Use constructor promotion for a required
$name(string) and an optional$phone(nullable string, defaulting tonull) - Add a nullable string property
$emailinitialized tonull - Create a method
setEmail(?string $email): voidthat sets the email property - Create a method
getContactInfo(): stringthat returns the contact's information in this format:"Name: [name]"followed by" | Phone: [phone]"only if phone is not null, followed by" | Email: [email]"only if email is not null
- Use constructor promotion for a required
ContactBook.php— Create aContactBookclass that stores and searches contacts. Include the Contact file. The class should:- Have a private array to store contacts
- Have a method
addContact(Contact $contact): voidthat adds a contact to the collection - Have a method
findByName(string $name): ?Contactthat searches for a contact by exact name match and returns the contact if found, ornullif not found
main.php— Include the ContactBook file. You'll receive three inputs: a name to add, a phone number (or the string"none"if no phone), and a name to search for.Create a
ContactBookand add a newContactusing the first two inputs. If the phone input is"none", passnullas the phone number.Then search for a contact using the third input. If found, print the contact's info using
getContactInfo(). If not found, print"Contact not found".
This challenge demonstrates how nullable types make your code's intent clear — when you see ?string for phone or email, you immediately know these fields are optional and might not have a value.
Cheat sheet
Use a question mark ? before a type to make it nullable, allowing it to accept either the specified type or null:
<?php
class User {
public ?string $middleName = null;
public function __construct(
public string $firstName,
public string $lastName
) {}
}
Nullable types work with properties, parameters, and return types:
<?php
class UserRepository {
public function find(int $id): ?User {
return $this->users[$id] ?? null;
}
}
Check for null before using nullable values:
<?php
if ($this->middleName !== null) {
return "$this->firstName $this->middleName $this->lastName";
}
return "$this->firstName $this->lastName";
Without the ?, passing null to a typed parameter or property causes a type error. Nullable types make it explicit that null is a valid value.
Try it yourself
<?php
require_once 'ContactBook.php';
// Read inputs
$nameToAdd = trim(fgets(STDIN));
$phoneInput = trim(fgets(STDIN));
$nameToSearch = trim(fgets(STDIN));
// TODO: Create a ContactBook instance
// TODO: Determine the phone value (null if input is "none", otherwise use the input)
// TODO: Create a new Contact with the name and phone
// TODO: Add the contact to the ContactBook
// TODO: Search for a contact using nameToSearch
// TODO: If found, print the contact's info using getContactInfo()
// TODO: If not found, print "Contact not found"
?>This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe $this KeywordMethodsPropertiesConstructor (__construct)Destructor (__destruct)Recap - Simple Calculator4Inheritance
Basic InheritanceThe parent:: KeywordMethod OverridingThe final KeywordAbstract ClassesRecap - Employee Hierarchy7Encapsulation
Public, Protected, PrivateAccess Modifiers in DepthGetters and SettersInformation HidingConstructor Promotion (8.0)Recap - Student Records System2Namespaces & Autoloading
Introduction to NamespacesThe use KeywordPSR-4 Autoloading StandardComposer AutoloaderRecap - Organized Project5Interfaces & Contracts
Introduction to InterfacesImplementing InterfacesMultiple Interface ImplementInterface vs Abstract ClassType Hinting with InterfacesRecap - Shape Calculator8Magic Methods
Magic Methods Introduction__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Object Cloning__serialize & __unserializeRecap - Custom Collection11Type System & Error Handling
Type DeclarationsNullable TypesUnion & Intersection TypesException ClassesCustom Exception HierarchyTry, Catch, FinallyRecap - Form Validator14Project: Library Management
Project OverviewBook and User Classes3Class Properties
Instance vs Static PropertiesConstants in ClassesStatic Methods & PropertiesPrivate & Protected PropertiesReadonly Properties (PHP 8.1)Recap - Bank Account Manager6Polymorphism
Method Overriding RevisitedPolymorphism via InterfacesType Hinting & Union TypesLate Static BindingRecap - Payment Processor9Traits
Introduction to TraitsUsing Multiple TraitsTrait Conflict ResolutionAbstract Methods in TraitsTraits vs Inheritance12Design Patterns Part 1
Intro to Design PatternsSingleton PatternFactory PatternObserver PatternStrategy Pattern