Skip to content

ADR: ORM Models

Status

To Validate

Context

The models are based on non standard functionality, a very old eloquent version and custom behaviour.

We want to standardise models and database to simplify functionality and structure. We also want to limit how much eloquent magic we use to limit divergence and simplify changes.

Decision

General Rules

  • Models MUST extend AppModel or a child

Relationships

  • Foreign keys SHOULD be represented with relationships on model. This makes it easy to navigate
  • Use adequate eloquent relationships HasOne, HasMany, BelongsTo, etc.

Model Integrity

  • A model MUST take care of its integrity. That includes initialisation and domain changes
  • Model intricacies SHOULD NOT be exposed, it SHOULD only expose state changes that make sense on the domain
  • Do not expose DB field getters and setters (it's not a DTO) but model domain changes (that might or might not be translatable to singular DB fields)
  • Example: ->flag($member, $reason) instead of ->setFlaggedBy($member); ->setFlaggedReason($reason); ->setFlaggedTimestamp($now)
  • A model SHOULD take care of related models that define its state
  • These are part of the internal intricacies that don't need to be exposed unnecessarily
  • Example: Related models used to store flagged status or state history
  • Internal models SHOULD be on an Internal named namespace
  • Internal models MUST use App\Domain\Model\Internal annotation mentioning what classes implement them (and are allowed to use them)
  • Example: #[Internal(CommentModel::class, CommentableTrait::class)]

Model Responsibilities

  • A model MUST NOT operate on multiple instances of itself, use Repositories
  • A model MUST NOT return Illuminate\Support\Collection or other ArrayAccess classes, use array

Timestamps

  • If model uses timestamps, it MUST use eloquent ones created_at, updated_at
  • MUST be of type DATETIME, not nullable and default to current_timestamp()
  • SHOULD NOT be set manually
  • SHOULD use ModelTimestampsTrait

Soft Deletes

  • If model can be soft deleted, it MUST use eloquent system with deleted_at
  • SHOULD implement StateChangeable
  • SHOULD use StateChangeableTrait and HasDeletedTrait
  • If model cannot be soft deleted but its children can, it MUST ensure propagation of soft deletes and restores
  • SHOULD implement SoftDeletable
  • SHOULD use SoftDeleteTrait

Consequences

Models are standardised and successfully implement SOLID principles while using Eloquent functionalities.

Impact

High

Driver

@Eudald Rossell Vivo

Contributors

[Team]

Accepted Date

[Pending validation]

Resources

Last modified by: Unknown