Given two classes that extend Model which is an extension of Eloquent\Model that have the exact same copy-pasted method. What is the recommended way to extract this duplicate method? An abstract class with the method that extends Model that both classes can then extend or a Trait to sprinkle in the functionality? Both classes are named quite similar but different in their uses for our system. Naming recommendations are also appreciated.
Below are the classes but only pasted with the similarities. The SQL view class uses a SQL view to remove the need for the attributes, it allows it to play nice with other parts of the system.
getExpirationMessageAttribute
<?php
class SupplierDocument extends Model {
use HasFactory, Taskable;
protected $appends = ['days_till_expiry', 'expiration_status', 'expiration_message'];
public function owner() {
return $this->belongsTo(User::class, 'owner_id');
}
public function facilities() {
return $this->belongsToMany(Facility::class, 'supplier_document_facilities');
}
/**
* Document expiration status.
*
* @return string
*/
public function getExpirationStatusAttribute() {
if (! $this->load('type')->type->is_expirable) {
return DocumentStatusEnum::NotExpirable;
}
if (Carbon::parse($this->expires_at)->isPast()) {
return DocumentStatusEnum::Expired;
}
if (Carbon::parse($this->expires_at)->diffInDays(now()) <= $this->type->expiration_window) {
return DocumentStatusEnum::ExpiringSoon;
}
return DocumentStatusEnum::Active;
}
/**
* Document days till expiration.
*
* @return string
*/
public function getDaysTillExpiryAttribute() {
if ($this->expires_at) {
return Carbon::parse($this->expires_at)->diffInDays(Carbon::now()->toDateString());
}
}
/**
* Document expiration message.
*
* @return string
*/
public function getExpirationMessageAttribute() {
if ($this->expiration_status === DocumentStatusEnum::ExpiringSoon) {
if ($this->days_till_expiry > 1) {
return "Expiring in $this->days_till_expiry days";
} elseif ($this->days_till_expiry === 1) {
return 'Expiring in 1 day';
} else {
return 'Expires today';
}
}
if ($this->expiration_status === DocumentStatusEnum::Expired) {
return "Expired $this->days_till_expiry days ago";
} elseif ($this->expiration_status === DocumentStatusEnum::NotExpirable) {
return DocumentStatusEnum::NotExpirable;
}
return DocumentStatusEnum::Active;
}
}
<?php
class SupplierDocumentView extends Model {
protected $appends = ['expiration_message'];
protected $table = 'supplier_documents_view';
public function owner() {
return $this->belongsTo(User::class, 'owner_id');
}
public function facilities() {
return $this->belongsToMany(Facility::class, 'supplier_document_facilities', 'supplier_document_id');
}
/**
* Document expiration message.
*
* @return string
*/
public function getExpirationMessageAttribute() {
if ($this->expiration_status === DocumentStatusEnum::ExpiringSoon) {
if ($this->days_till_expiry > 1) {
return "Expiring in $this->days_till_expiry days";
} elseif ($this->days_till_expiry === 1) {
return 'Expiring in 1 day';
} else {
return 'Expires today';
}
}
if ($this->expiration_status === DocumentStatusEnum::Expired) {
return "Expired $this->days_till_expiry days ago";
} elseif ($this->expiration_status === DocumentStatusEnum::NotExpirable) {
return DocumentStatusEnum::NotExpirable;
}
return DocumentStatusEnum::Active;
}
}