Which Types Can `readonly` Properties Have in PHP 8.1?
PHP

Which Types Can `readonly` Properties Have in PHP 8.1?

Symfony Certification Exam

Expert Author

October 10, 20235 min read
PHPSymfonyPHP 8.1Readonly PropertiesSymfony Certification

Which Types Can readonly Properties Have in PHP 8.1?

As a Symfony developer preparing for the certification exam, understanding the capabilities of readonly properties introduced in PHP 8.1 is crucial. These properties enhance data integrity and encapsulation, directly impacting how you design your applications and manage state. This article will delve into the types of properties that can be declared readonly, their practical applications in Symfony, and how they can streamline your code.

What are readonly Properties?

readonly properties in PHP 8.1 allow you to create properties that can only be written once, either at the time of object construction or through initialization. After their initial assignment, these properties become immutable, preventing any further modifications.

This feature enhances the robustness of your code by ensuring that once a value is set, it remains unchanged throughout the object's lifecycle. This immutability can significantly reduce bugs and unexpected behavior, especially in complex Symfony applications.

Types of readonly Properties in PHP 8.1

Fundamental Types

readonly properties can encompass a variety of fundamental types, including:

  • int
  • float
  • string
  • bool

For example, consider a simple Symfony entity representing a user:

class User
{
    public readonly int $id;
    public readonly string $name;
    
    public function __construct(int $id, string $name)
    {
        $this->id = $id;
        $this->name = $name;
    }
}

Here, the id and name properties are declared as readonly, ensuring they can only be set during instantiation.

Complex Types

readonly properties can also be complex types, including:

  • Arrays
  • Objects
  • Interfaces
  • Callable

For example, if you have a class that manages a collection of products, you might define a readonly array property:

class ProductCatalog
{
    public readonly array $products;
    
    public function __construct(array $products)
    {
        $this->products = $products;
    }
}

In this case, the products property can hold an array of product objects, but cannot be modified after the initial assignment.

Nested Types

You can also declare readonly properties that are themselves composed of other readonly properties or complex types. This is particularly useful in Symfony entities that represent complex relationships.

Consider an order entity that includes a readonly property for a customer:

class Customer
{
    public readonly string $name;
    public readonly string $email;

    public function __construct(string $name, string $email)
    {
        $this->name = $name;
        $this->email = $email;
    }
}

class Order
{
    public readonly Customer $customer;

    public function __construct(Customer $customer)
    {
        $this->customer = $customer;
    }
}

In this scenario, the customer property is a readonly instance of the Customer class, ensuring that the customer information remains consistent throughout the order's lifecycle.

Practical Applications in Symfony

Understanding which types readonly properties can have is vital for Symfony developers. Let's explore some practical scenarios where readonly properties can improve your Symfony applications.

Immutability in Value Objects

Immutability is a core principle in domain-driven design. By utilizing readonly properties, you can create value objects that represent concepts such as money, dates, or addresses without the risk of their state changing unexpectedly.

class Money
{
    public readonly int $amount;
    public readonly string $currency;

    public function __construct(int $amount, string $currency)
    {
        $this->amount = $amount;
        $this->currency = strtoupper($currency);
    }
}

The Money class ensures that both amount and currency cannot be altered after instantiation, making it a reliable representation of monetary values throughout your application.

Configuration Objects

In Symfony, you may encounter scenarios where you need to define configuration settings. By using readonly properties, you can create configuration objects that are safe from unintended changes:

class DatabaseConfig
{
    public readonly string $host;
    public readonly string $username;
    public readonly string $password;

    public function __construct(string $host, string $username, string $password)
    {
        $this->host = $host;
        $this->username = $username;
        $this->password = $password;
    }
}

This pattern allows you to encapsulate configuration settings in a clear and maintainable way, ensuring that the values remain constant throughout the application’s runtime.

Symfony Services

When creating services in Symfony, you often need to pass dependencies via the constructor. Utilizing readonly properties enhances the clarity of your services, as it explicitly defines the immutability of the injected dependencies:

class UserService
{
    public function __construct(
        private readonly UserRepository $userRepository,
        private readonly LoggerInterface $logger,
    ) {}

    public function createUser(string $name): void
    {
        $user = new User($name);
        $this->userRepository->save($user);
        $this->logger->info("User created: {$user->name}");
    }
}

In this example, userRepository and logger are readonly dependencies that cannot be modified after the service is constructed, promoting strong encapsulation.

Benefits of Using readonly Properties

Using readonly properties offers several advantages in Symfony applications:

Improved Data Integrity

By defining properties as readonly, you ensure that the state of your objects remains consistent throughout their lifecycle. This reduces the likelihood of bugs caused by unintended modifications.

Enhanced Code Clarity

readonly properties signal to developers that these values are immutable, improving the readability and maintainability of the code. Other developers can quickly understand the intended use of these properties.

Simplified Testing

Immutable objects are typically easier to test because their state doesn't change. This leads to more predictable behavior and fewer side effects, making tests more reliable.

Compatibility with Doctrine

When using readonly properties in Doctrine entities, you can define your domain model clearly while still leveraging Doctrine's capabilities. The properties can be mapped to database fields while ensuring they remain immutable in your application logic.

Conclusion

Understanding which types readonly properties can have in PHP 8.1 is essential for Symfony developers. This feature enhances your ability to create robust, maintainable applications by enforcing immutability and improving data integrity. By leveraging readonly properties in value objects, configuration classes, and services, you can streamline your code and reduce potential errors.

As you prepare for your Symfony certification exam, embrace the readonly properties feature, and experiment with its applications in your projects. Mastery of this concept will not only help you pass the exam but also make you a more proficient Symfony developer in your professional endeavors.