Imagine a piggy bank that holds coins but does nothing else — it can’t count them, can’t spend them, can’t exchange them. A Data Class is a class that holds data (fields) but has almost no behavior. Most of its methods are just getters and setters.
We count the fields and methods in a class, trait, or enum. Methods are classified as accessors (getters/setters/issers) if they follow naming conventions and have simple bodies. If the accessor ratio exceeds the threshold (default 70%) and the class has at least the minimum method count (default 3), it’s flagged as a Data Class.
This class just holds data — there’s no real behavior, just getters and setters.
class UserDTO
{
private string $name;
private string $email;
private int $age;
public function getName(): string { return $this->name; }
public function setName(string $name): void { $this->name = $name; }
public function getEmail(): string { return $this->email; }
public function setEmail(string $email): void { $this->email = $email; }
public function getAge(): int { return $this->age; }
public function setAge(int $age): void { $this->age = $age; }
}
Add behavior that works with the data — now it’s a real object with encapsulated logic.
class User
{
public function __construct(
private string $name,
private Email $email,
private Age $age,
) {}
public function changeEmail(string $newEmail): void
{
if (!$this->email->isVerified()) {
$this->email = new Email($newEmail);
}
}
public function isAdult(): bool
{
return $this->age->value() >= 18;
}
}
rules:
E0028:
max_getter_setter_ratio: 0.7
min_methods: 3
If Phanalist flags a class as a Data Class, your class is just a bag of data with no real behavior. Move the logic that operates on this data into the class itself — that’s the heart of object-oriented programming.