In my current project I'm refactoring the code to get a DBAL. I have a class Entity
that is the base class for all classes that model a database table. So there are several classes that inherit from Entity
like Document
, Article
and so on.
abstract class Entity {
/** @var DatabaseRequest $dbReuest */
protected $dbRequest;
/** @var Login $login */
protected $login;
/* some methods like insert(), update(), JsonSerialize(), etc.
}
Since all these classes have the same constructor __construct( DatabaseRequest $dbRequest, Login $login )
and I don't want to throw around those two paramenters, I also made this:
class EntityFactory {
public function __construct( DatabaseRequest $dbRequest, Login $login )
{
$this->dbRequest = $dbRequest;
$this->login = $login;
}
public function makeEntity( string $class )
{
if ( $this->extendsEntity( $class ) ) {
$reflection = new \ReflectionClass( $class );
$construct = $reflection->getConstructor();
$params = $construct->getParameters();
return new $class( clone $this->dbRequest, clone $this->login );
}
throw new APIException( "Class $class does not extend " . Entity::class, JsonResponse::DEBUG );
}
}
You call the method like this: $factory->makeEntity( Document::class )
and this will give you an object of that class.
This way a change in in the Entity
constructor reduced the refactoring effort to a minimum. However, in class that extend Entity
I also defined some methods for the relationships between their tables. E.g.:
class DocumentAddressee extends Entity {
/* ... */
public static function createFromCustomer( Address $address )
{
$self = new DocumentAddressee( clone $address->dbRequest, clone $address->login );
/* transferring data from Address to $self */
return $self;
}
}
(According to verraes.net this is a legit use of static methods as named constructory ).
And methods like these happen quite some times (roughly 1-2 methods per foreign key in a table). Now I'd like to keep those methods, because I can easily access dependend data this way. But I'd also like to keep those constructors to the factory so I don't have to refactor all 100+ Entity-classes when the Entity construcor changes (this might happen if we'll decide to use a QueryBuilder in the future.
Is there already some kind of best practice to handle these methods? Should I propably handle those relationships within the factory or model those relationships in extra classes?