Соответствующий шаблон для класса ActiveRecord

У меня есть класс ActiveRecord BaseModel и множество классов-моделей, которые наследуют его. И у меня есть класс Bookmark, который также унаследован от BaseModel. Кроме того, у меня есть классы Decorator -inherited, они реализуют специальный интерфейс для представления одиночной модели (метод getModelView(model)). Это некоторый псевдокод:

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())

Итак, все выглядит хорошо, пока я не хочу немного изменить этот вид для закладки. Я хочу добавить пользовательский заголовок для этого представления. И я не могу сделать его внутри декоратора, потому что он отображает его не только для закладок.

EDIT: Итак, проблема в том, что мне нужен шаблон декоратора, но у меня нет на что унаследовать, потому что конкретный TestDecorator использует специальные методы TestModel. Итак, теперь я сделал очень плохую реализацию, используя магические методы (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];
    }

}

Итак, это сработает, но с точки зрения структуры кода, удобочитаемости и стабильности это действительно плохое решение.

Ответы

Ответ 1

Модель не должна знать о представлении. Модели представляют собой необработанные данные, видимые со всех сторон одновременно. Представление представляет собой перспективу этой модели. Контроллер должен загружать модель в:

$model_view->render($model);

Затем оформить представление:

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

Только украшать на основе интерфейсов, а не типов.

Магические методы PHP велики, но они не должны использоваться для ActiveRecord, это противоречит "разделению проблем", в этом случае отделяя модель от механизма персистентности.

Вместо этого создайте объект ActiveRecord и подайте модель в.

$record->store($model);

Затем, если вам нужно изменить хранилище, снова просто украсьте механизм хранения:

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