UnstableFractal
UnstableFractal

Reputation: 1422

Appropriate pattern for ActiveRecord class

I've got an ActiveRecord BaseModel class and a lot of classes-models which inherit from it. And i've got a class Bookmark, which is inherited from BaseModel as well. Also, i've got Decorator-inherited classes, they implements special interface to represent single model ( getModelView(model) method). This is some pseudo-code:

TestModel inherits BaseModel
    getName:
        return this.name

BookmarkModel inherits BaseModel
    BaseModel model

    getBookmark:
        return this.model

TestDecorator inherits BaseDecorator implements SingleModelViewInterface:
    getView(model):
        return 'view' //html-view of model

BookmarkDecorator inherits BaseDecorator
    getBookmarksView(BookmarkModel[] bookmarks):
        foreach(bookmarks > bookmark):
            decorator = Relation::getDecoratorByModel(bookmark->getEntityType())
            decorator->getView(bookmark->getBookmark())

So, everything looks good, until i want to change that View for bookmarked model a bit. I want a to add a custom title for that view. And i can't make it inside decorator, because it renders it not only for a bookmarks.

EDIT: So, the problem is - seems that i need a decorator pattern, but i dont have anything to inherit from, because concrete TestDecorator using TestModel speical methods. So now i've done some really bad realization, using magic methods (PHP):

class BookmarkedModel {

    /** @var BaseEntityModel*/
    private $model;

    public function __construct(BaseEntityModel $model) {
        $this->model = $model;
    }

    public function getName() {
        return 'Bookmark '.$this->model->getName();
    }

    public function __call($name, $arguments) {
        return call_user_func_array(array($this->model, $name), $arguments);
    }

    public function __get($name) {
        return $this->model->$name;
    }

    public function __set($name, $value) {
        return $this->model->$name[$value];
    }

}

So it will work for now, but in terms of code structure, readability and stability it's really bad decision.

Upvotes: 15

Views: 622

Answers (1)

y o
y o

Reputation: 1163

The model should be unaware of the view. Models represent the raw data seen from every angle at once. The view is a perspective of that model. The controller should feed the model to the view:

$model_view->render($model);

Then decorate the view:

$bookmark_view->render($model); // bookmark_view wraps a model_view,
// returns 'Bookmark '.$this->model_view->render($model)

Only decorate based on interfaces, not types.

PHP's magic methods are great, but they should not be used for ActiveRecord, this goes against "separation of concerns", in this case separating the model from it's persistence mechanism.

Instead make an ActiveRecord object and feed the model to it.

$record->store($model);

Then if you need to modify storage, again just decorate the storage mechanism:

$log_record->store($model); // wraps $record, logs a message prior to database storage.

Upvotes: 2

Related Questions