In this PHP article, we will be discussing the single responsibility principle as it applies to PHP classes and objects, we'll also look at PHP examples of the single responsibility principle (SRP).

We will consider the single responsibility principle in limited terms (of PHP), for an in-depth look at the single responsibility principle, you can read uncle Bob's article on SRP.

What is the Single Responsibility Principle?

Now that we know a little more about SRP, we can think about what causes a class to change. From a PHP perspective, the most likely change is probably a change in business rules. There might be other reasons for low level languages, like hardware changes, but for the most part, we'll think of change in PHP as a change in business requirements.

With that in mind, we can rephrase the single responsibility principle as:

The single reason for change principle.

In other words: our classes should have only one reason for change (if we implement the single responsibility principle on them)

SRP example in PHP: Render an HTML input element

Let's look at an example of a PHP class which we use to render an HTML input. Our class in called HTMLInput which has a method render to return an HTML input element.

Our HTMLInput class is simple enough, but what if we wanted to add attributes to our input, we could update our render method to accept an associative array $attributesArray.

Our HTMLInput class now renders an input element with attributes, but does it have more than one reason for change? What if the attributes array has a style key which we use to render inline styles?

Our HTMLInput class would have two possible reasons for change:
  1. The way in which an input element is rendered.
  2. And the way in which attributes are generated.
So how do we update our HTMLInput class to have one reason for change only i.e to conform with the single responsibility principle?

SRP in Yii framework: The InputWidget

Let's look at an example of the single responsibility principle in Yii framework, you can learn more about Yii PHP framework here.

The Yii framework has an InputWidget class similar to our HTMLInput class, and a corresponding renderInputHtml method.

The BaseHtml class provides a set of static methods for generating commonly used HTML tags. The InputWidget class uses the renderInputHtml method to render it's attributes.

The InputWidget class is not responsibile for generating the tag attributes.

SRP in Laminas's MVC layer (Zend Framework): The FormLabel

Let's look at another SRP example, this time using the FormLabel class as an example, you can learn more about Laminas MVC here.

The FormLabel class has an openTag method to generate an opening label tag, which uses the createAttributesString method to generate the tag attributes.

The AbstractHelper class in Laminas provides base functionality for all form view helpers, which implements the createAttributesString method. In Laminas's MVC layer, the FormLabel class does not take responsibility for the tag attributes.

It outsources that responsibility to the AbstractHelper class.

If our HTMLInput class conformed to SRP, we'd have to refactor our code to outsource the attribute generation method to a separate class.

Key Takeaways

  • Our examples shown clearly separate responsibilities between classes, though not obvious when you start thinking about your classes, grouping responsibilities together may become easier with experience.
  • In general, implementing the single responsibility principle in PHP would depend on your business rules, with emphasis on the possible causes for change in your classes and the likelihood of those changes actually occurring.
  • The key ingredient for the single responsibility principle would be deciding how to group responsibilities, how do you think about separating responsibilities when designing your classes?

Further Reading

This article is part of a series on SOLID in PHP, the follow up to this article is The Open-Closed Principle.