What does the term Plain Old PHP Object (POPO) exactly mean?

Plain Old {Insert Language Here} Object is an simple approach that says you don't always need to use an extensive class, or inheritance chain, to store data or perform logic. It allows you to simplify the understanding of your structure by encapsulating details, not deriving details or creating dependencies on other sources.

A simple use case could be a DTO or Entity that encapsulates user fields:

class User  {
    public $firstName;
    public $lastName;
}

Versus a more extensive object that implements an interface or extends a Base class or both.

interface UserInterface {

    public function getName();
    public function setName($name);

}

class User extends Model implements UserInterface {

    public function getName()
    {
        ...
    } 

    public function setName($value) {
        ...
    }

}

According to Wikipedia, a named class is considered a plain object if it does not implement any interfaces or extend any preexisting classes.

I recommend looking at Shaunak Sontakke's answer for use cases.


POPO is as an object of a simple class. When you make it as a stdClass object it's not a strict contract of what you would have in that object. stdClass object can be easily abused by other developers.

Consider below points while making a POPO:

  • All member variables are private. Accessor methods should be used vs direct member access.
  • Public accessor methods ( getters / setters )
  • Public toArray(), toJson() like methods for easy access, easy storage/persistence
  • Constructor accepting array of values that need to be set.
  • It should not have any business logic
  • Avoid any kind of validation in this object
  • Don't worry about implementing an interface for POPO. [Optional]
  • If you need method chaining, return $this from your setters. [Optional]
  • Probably a __toString() method [Optional]

When to use it:

Consider use of POPO in these cases:

  • To transfer data across the boundary. Like transferring data from Model to Controllers or from controllers to View or from one application to other application. In this case it would behave like Data Transfer Object (DTO). More details - DTO vs Value Object vs POCO
  • If we have a json data, we could bind that json data and map it to a POPO. So we exactly know what's there in json field. This will also ensure that our json data has a consistent structure always. It will also prevent abuse of JSON structure.
  • If there are too many parameters for a function, we could use "Introduce Parameter Object" refactoring to replace all those parameters with a POPO containing those members.
  • For mapping a database composite type

POPO is a PHP variant of POJO that was coined by Martin Fowler

eg:

class CPerson {

private $m_strNameFirst;
private $m_strNameLast;
private $m_fltHeight;
private $m_fltWeight;

public function __construct( $arrmixValues ) {
    $this->setNameFirst( $arrmixValues['name_first'] ?? NULL );
    $this->setNameLast( $arrmixValues['name_last'] ?? NULL );
    $this->setHeight( $arrmixValues['height'] ?? NULL );
    $this->setWeight( $arrmixValues['weight'] ?? NULL );
}

public function toArray() : array {
    return [
        'name_first' => $this->getNameFirst(),
        'name_last'  => $this->getNameLast(),
        'height'     => $this->getHeight(),
        'weight'     => $this->getWeight(),
    ];
}

public function getNameFirst() {
    return $this->m_strNameFirst;
}

public function setNameFirst( $strNameFirst ) {
    $this->m_strNameFirst = $strNameFirst;
}

public function getNameLast() {
    return $this->m_strNameLast;
}

public function setNameLast( $strNameLast ) {
    $this->m_strNameLast = $strNameLast;
}

public function getHeight() {
    return $this->m_fltHeight;
}

public function setHeight( $fltHeight ) {
    $this->m_fltHeight = $fltHeight;
}

public function getWeight() {
    return $this->m_fltWeight;
}

public function setWeight( $fltWeight ) {
    $this->m_fltWeight = $fltWeight;
}

}

Tags:

Php