Соответствующий шаблон для класса 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.