Дизайн модели Zend Framework
Я создаю приложение в Zend Framework. Моя модель состоит из трех уровней: классов домена, классов отображения данных и сервисного уровня, который обеспечивает интерфейс для всех внешних коммуникаций. В настоящее время классы сопоставления данных используются только на уровне моего сервиса, а классы домена - это простые объекты php, содержащие только информацию, относящуюся к их домену. Очень грубый пример того, что я имею в виду....
//domain class
public class User{
// data and functions specific to the user domain
}
//service class
public class UserService{
// service contains an instance of the mapper class
protected $_mapper =
public function fetch($id){
return $this->_mapper->find($id);
}
}
//mapper class
public class UserMapper{
protected $_dbTable = new Zend_Db_Table('user');
public function find(){
return new User($this->_dbTable->find($id)->current());
}
}
Я бы извлек объект пользователя в контроллере, например итак
$user = $this->_service->fetch($id);
До сих пор это работало нормально, но теперь я хочу сделать это
$user = $this->_service->fetch($id);
$recipeCount = $user->getRecipeCount();
Новые данные поступают из другой таблицы, и я не хочу извлекать всю эту информацию из базы данных каждый раз, когда я загружаю пользователя, я хочу лениво загружать эту информацию при вызове функции getRecipeCount. Я предполагаю, что мой вопрос заключается в том, что было бы лучшей практикой для достижения этого? Что касается потребителя, то информация специфична для домена пользователя, поэтому я думаю, что ее следует называть из класса пользователя. Для достижения этой цели класс домена должен был бы содержать свой собственный экземпляр mapper, но разве это отрицает необходимость наличия класса обслуживания в первую очередь? Я действительно не хочу делать это каждый раз.
$recipeCount = $this->_service->getRecipeCount($user);
Любые мысли будут оценены по достоинству
2 answers
Учитывая объект пользователя, нет сомнений, что вы могли бы задать массу вопросов об этом пользователе: получить все его группы, получить все его сообщения, получить все его рецепты и т.д.
Заманчиво думать, что каждый из них должен представлять метод самого объекта пользователя:
$groups = $user->getGroups();
$posts = $user->getPosts();
$recipes = $user->getRecipes();
// etc
В этом случае ORM, подобный доктрине (#FTW!), может помочь управлять этими типами отношений, предоставить вам язык запросов, с помощью которого вы можете жадно загружать или лениво загружать граф пользовательских сущностей.
Но я подумайте, что здесь есть место для другого взгляда. Почему это должны быть методы самого объекта пользователя? Могут ли они вместо этого быть методами в классах сервисов/репозиториев:
$groups = $groupService->getGroupsByUser($user);
$posts = $postService->getPostsbyUser($user);
$recipes = $recipeService->getRecipesByUser($user);
// etc
Каждый из этих классов служб/репозиториев, вероятно, будет создан со своими собственными классами сопоставления для доступа к их базовым источникам данных. Таким образом, нет проблем с ленивостью/жадностью при создании/загрузке объекта пользователя. Если вы хотите получить связанные объекты, то продолжайте получать к ним доступ через соответствующий сервис/хранилище, именно тогда, когда вы этого хотите.
Не говорю, что это всегда должно быть так или иначе. На самом деле, говоря прямо противоположное: что оба подхода имеют свое место. Выбор того, какой из них использовать в каком контексте, предполагает как некоторый объективный анализ производительности, так и, вероятно, немалую долю личной эстетики.
Просто размышляю вслух. ИММВ.
Это похоже на место, где мне пригодились бы отношения таблиц, определенные в Model_DbTable_Users()
. Таким образом, вы могли бы просто выполнить запрос findDependentRowset()
для пользователей на любом уровне, который вы считаете подходящим. Хотя, похоже, вы, скорее всего, захотите перевести его на уровень обслуживания.