Шаблон DataMapper

player

Новичок
Шаблон DataMapper

Добрый день!

Прочитал статью http://wiki.agiledev.ru/doku.php?id=ooad:dp:data_mapper
Начал писать сам пример применения шаблона, и возник вопрос: что делать если есть классы User и UserMapper и теперь требуется при изменении имени пользователя посмотреть в базу (через маппер), существует ли такое имя уже в базе. Или другой пример - при создании нового пользователя нужно проверить мэйл-адрес на уникальность в базе.

Тут же сначала создается
$user = new User();
Потом присваиваются значения
$user->setEmail('[email protected]');
И сохраняется мапером
$userMapper->save($user);

Что делать? Не создавать же в методе setEmail() объект мапера, который чтото проверяет? А в контроллере это делать еще хуже.

Надеюсь на вашу помощь
 

korchasa

LIMB infected
Валидация - часть модели. Работа с базой - удел маппера. Как разделить проверку на эти части?
 

Black Raven

Новичок
А зачем валидировать при установке? Лок ставить на имя пользователя? Валидация нужна при сохранении помоему...
 

player

Новичок
Как разделить проверку на эти части?
Это и есть мой вопрос. То есть всетаки создавать в методе валидации объект маппера и запускать функцию validateUniqueEmail($email); ???
 

Духовность™

Продвинутый новичок
создавать в методе валидации объект маппера и запускать функцию validateUniqueEmail($email);
ИМХО
объект User ничего не должен знать о User_Mapper. Объект User представляет собой сущность, которая абстрагирована от БД и ОТ СРЕДСТВ РАБОТЫ С БАЗОЙ, т.е. и от маппера. Объект User должен уметь делать валидацию или иную логику, но базы он касаться не должен, т.к это уже другой слой приложения.

Меня тоже интересует вопрос топикстартера.


Раньше я писал так (если кому интересно): я создавал классы для проверки чего-либо, которые объединялись в объекте Validator_Chain. Поверка выглядела так:

PHP:
if (HttpRequest::isPost())
{
    // создали объект User из POST-данных
    $this->user = $this->user_mapper->createFromArray($this->request->user);

    // "реестр" валидаторов
    $validator = new Validator_Chain(DIR_LANG_VALIDATOR_MESSAGES, 'Registration');
    // проверяем "на пусто"
    $validator->add('user_login', new Validator_Simple_Var_Empty($this->user->user_login));
    // только a-z0-9
    $validator->add('user_login', new Validator_Simple_Char_Password($this->user->user_login));
    // В классе Validator_Simple_User_Login_Exists была проверка 
    // на существование юзера с логином $this->user->user_login
    $validator->add('user_login', 
                    new Validator_Simple_User_Login_Exists($this->user->user_login, $this->user->id));
          
    if ($err = $validator->getErrors())
        {
            $this->view->err = $err;

            $redirect = new Redirect();
            $redirect->setType('alert');
            $redirect->setMessage('post_errors');
            $this->view->setRedirect($redirect);
        }
        else
        {
            $this->user_mapper->save($this->user);
        }
    }
класс Validator_Simple_User_Login_Exists: http://phpclub.ru/paste/index.php?show=2359 и его parent: http://phpclub.ru/paste/index.php?show=2360

сейчас считаю это не очень удобным, но гибким подходом.

Как решается грамотно эта задача пока не знаю.
 

whirlwind

TDD infected, paranoid
Я валидаторы впрыскиваю в модель. Другое дело, что для проверки занят/не занят надо делать метод в маппере.
 

zerkms

TDD infected
Команда форума
triumvirat
реализовать абсолютно датамаппер "чисто", чтобы сущность не знала ничего о маппере непосредственно - довольно геморное занятие. более того, это "ограничение" дальше выливается в такую тонну костылей, что мало не покажется :)
 

korchasa

LIMB infected
Автор оригинала: player
Это и есть мой вопрос. То есть всетаки создавать в методе валидации объект маппера и запускать функцию validateUniqueEmail($email); ???
А если так:
Код:
class UserMapper {
...
function save($user) {
    $user->setIsEmailUnique = $this->isEmailUniqueFor($user);    
    $user->isValidate();
}
 

A1x

Новичок
у меня в маппере есть методы preInsert, preUpdate, onInsert, onUpdate .... ит.д. которые выполняются соответственно до и после и принимают объект в качестве параметра. Если в pre* методе происходит ошибка то само действие не выполняется
 

Духовность™

Продвинутый новичок
zerkms
ну ты предложи (напиши) какое-нибудь решение, что бы яснее все было


Моё второе ИМХО - такие вопросы - это от попытки засунуть код в "трёхуровневую" архитектуру МВС.
 

korchasa

LIMB infected
Автор оригинала: triumvirat
Моё второе ИМХО - такие вопросы - это от попытки засунуть код в "трёхуровневую" архитектуру МВС.
Т.е. изоляция бизнес логики (как назвать - модель или business layer не важно) это плохо?
 

zerkms

TDD infected
Команда форума
ну ты предложи (напиши) какое-нибудь решение, что бы яснее все было
не понял. я говорил о том, что на практике не получается так красиво, как говорит теория, потому что в жизни всё не так.
я в mzz орм писал трижды. последняя инкарнация, имхо, получилась очень неплохая, но со значительными отступлениями от теории.
тебе кажется, что это неправильно - напиши жизнеспособный вариант исключительно по канонам :)
 

player

Новичок
Я валидаторы впрыскиваю в модель. Другое дело, что для проверки занят/не занят надо делать метод в маппере.
То есть грубо говоря, чтобы не создавать объект маппера наглым образом прямо в методе $user->setUsername() оборачиваем ту же самую рутину в валидатор и так же вставляем в User :)
 
Сверху