MVC на phppatterns.com

whirlwind

TDD infected, paranoid
Автор оригинала: CatManZero
Это может быть и DataMapper. Но разве здесь он не играет роль модели с точки зрения MVC? Ведь этот класс содержит не только методы доступа к данным, но и элементы бизнес логики.
Вот как раз та часть которая из датамаппера абсолютна в MVC не нужна. Пользователю модели должно быть вообще наплевать где оно хранится да и хранится ли оно вообще где нибудь. Все что нужно знать - это интерфейс. Есть метод getAttributes? Круто - мы можем написать единый контроллер для отображения объекта любого класса модели. Есть метод save? Замечательно, это позволит формализовать действие редактирования всех объектов класса модели в одном контроллере. И т.п. Сокращение кода будет именно здесь, а не в том что в одном отдельном контроллере по сравнению с портянкой будет меньше кода (хотя так и будет в итоге).
 

CatManZero

Новичок
Автор оригинала: whirlwind
Вот как раз та часть которая из датамаппера абсолютна в MVC не нужна.
Наверное не нужна, особенно, если внутренне представление модели сильно отличается от того, как хранятся её данные в БД и т.п. Тут класс больше на active record чтоли смахивает...
Меня насторожило заявление HraKK-а, что это скорее контроллер, чем модель. Я просто хотел уточнить для себя, действительно ли это так?
 

HraKK

Мудак
Команда форума
CatManZero
Из класса не видя методов не понятно что это - Data Mapper или управляющий класс. Особенно смущает __construct.
 

Духовность™

Продвинутый новичок
Я имел в виду, что при текущем положении вещей я могу по своему желанию добавить любой атрибут в модель. И она это спокойно проглотит, потому что у тебя модель описана соглашением, что юзер содержит такие-то атрибуты. А должно быть требование - у юзера есть _только_ эти атрибуты и никакие другие. Чем больше в классах соглашений, тем хуже. Класс умеет требовать, но он не может работать по соглашению с человескими мыслями потому что mod_telepat для кода еще не изобрели
так что, я не пойму - надо сделать проверку на недопустимость добавления в класс иных свойств?

-~{}~ 12.11.08 13:03:

аааааааааап!
 

whirlwind

TDD infected, paranoid
Что значит допустимость или недопустимость добавления иных свойств? Ну-ка представим - есть модель человека. Разрешить или не разрешить добавление ему свойства типа хобот? Если разрешить, то останется ли это человеком? То есть сам факт разрешения говорит о том, что в определенное время работы кода нельзя с полной уверенностью сказать с чем мы имеем дело - с моделью человека или хоботатым мутантом.
 

whirlwind

TDD infected, paranoid
Мне вообще-то все равно как это будет реализовано. Для наших целей нужно добиться возможности получения списка атрибутов модели, не включая того, что там Вася Пупкин записал между делом в массив.
 

Духовность™

Продвинутый новичок
whirlwind
Тогда два решения:
1. Не пущать то, что заранее не определено как свойства модели
2. Отдавать список только тех аттрибутов, которые заранее определены.

Я вообще то не знаю, как тут идеологически правильно сделать. Но думаю што 1 вариант:
PHP:
class model
{
    private $model_attributes = array();
    private $data;

    public function __construct()
    {
        $this->model_attributes = array('user_name', 'user_age', 'user_sex');
    }

    public function __set($key, $value)
    {
        if (in_array($key, $this->model_attributes))
        {
            $this->data[$key] = $value;
        }
    }

    public function __get($key)
    {
        return isset($this->data[$key]) ? $this->data[$key] : null;
    }

    public function getAttributes()
    {
        return $this->data;
    }
}

$model = new model();
$model->user_name = 'Вася';
$model->user_age = 15;
$model->user_sex = 'male';
$model->hobot = TRUE; // йух - нет такого свойства

print_r($model);
 

whirlwind

TDD infected, paranoid
Во! Теперь норм. Только примеры свои верни, а то уже удалились и я не помню че там было.
 

Духовность™

Продвинутый новичок
примеры свои верни
а там ничего кроме тинтерфейса быдломодели не было :)

PHP:
Интерфкйс:
class user
{
    // Принимает массив данных вида 
    // 'id_user' => 12
    // 'user_name' = 'вася'
    // .....
    public function __construct($data) {}

    // возвращает объект user по числовому идентификатору.
    public static function getObjectById($id_user) {}

    /**
    * Возвращает TRUE, если пользователь является админом.
    * В контексте объекта user всегда возвращает FALSE.
    */
    public function isAdmin() {}

    // ....

    /**
    * Обновляем данные пользователя.
    */
    public function update($data) {}

    /*
    * Удаление пользователя.
    */
    public function delete() {}

    /**
    * Устанавливает "активность" пользователя.
    * Применяется при подтверждении регистрации, 
    * а также при банах.
    */
    public function setActive($active) {}

    /*
    * Когда зарегестрированный пользователь вхожит в систему, 
    * обновляем его данные - время посещения и IP.
    */
    public function setActualInfo() {}
}
 

whirlwind

TDD infected, paranoid
Не, мы же MVC разбирали. Что там было у тебя с MVC тоже давай. С моделью пока больше ниче не делаем.
 

Духовность™

Продвинутый новичок
Что там было у тебя с MVC тоже давай
ничего толком не было. ты написал
Попробуй реализовать модель юзера. Контроллеры сами так и просятся: регистрация, редактирование, просмотр информации, краткая инфа в топике форума и т.п. и т.д. выбирай два на свое усмотрение
вот. Модель юзера мы наверно реализовали? Абстрактную такую. Теперь надо контроллер мне написать. Так? :)
 

whirlwind

TDD infected, paranoid
А, ну да. getObjectById => findById и у нас есть контроллер для View любой модели.
 

Духовность™

Продвинутый новичок
whirlwind
это типа как в activeRecord реализовать статический метод? Это в модели надо сделать или в контроллере?
 

whirlwind

TDD infected, paranoid
Нет. Просто getObjectById подразумевает что будет объект возвращен. Нам не нужно возвращать объект. Нужно этот же объект настроить на запись с указанным ID. Что бы не усложнять, оставляем в модели.
 

Духовность™

Продвинутый новичок
Нужно этот же объект настроить на запись с указанным ID.
Тогда почему он getObjectById должен называться? Т.е надо сделать метод, который будет брать данные из БД с указанным id?

PHP:
function getObjectById($id)
{
    if ($data == null)
    {
        $res = $db->query('SELECT * FROM users WHERE id_user = ?', $id);
        $data = $res->fetch_assoc();
    }
    
    return $data;
}
 

AmdY

Пью пиво
Команда форума
только его нужно заврапить в твою обёртку, чтобы можно было $obj->user_name
желательно всё же пользоваться при выборке полем model_attributes, чтобы не брать ненужные поля
 

Духовность™

Продвинутый новичок
AmdY
не знаю, это ли имел в виду whirlwind
PHP:
class user_model
{
    private $model_attributes = array();
    private $data;

    public function __construct()
    {
        $this->model_attributes = array('user_name', 'user_age', 'user_sex');
    }

    public function __set($key, $value)
    {
        if (in_array($key, $this->model_attributes))
        {
            $this->data[$key] = $value;
        }
    }

    public function __get($key)
    {
        return isset($this->data[$key]) ? $this->data[$key] : null;
    }

    public function getAttributes()
    {
        return $this->data;
    }

    function getObjectById($id)
    {
        if ($data == null)
        {
            $res = $db->query('SELECT '.implode(', ', $this->model_attributes).' * FROM users WHERE id_user = ?', $id);
            $data = $res->fetch_assoc();
        }

        return $data;
    }
}

$model = new user_model();
$model->user_name = 'Вася';
$model->user_age = 15;
$model->user_sex = 'male';
$model->hobot = TRUE; // йух - нет такого свойства

// тут получим данные пользователя $id,
// определенные в $this->model_attributes
$data = $model->getObjectById($id);

print_r($model);
 

whirlwind

TDD infected, paranoid
Для простоты совмещаем model и data mapper

PHP:
class model {

   ...

   function findById($id) 
   { 
            $res = $db->query('SELECT '.implode(', ', $this->model_attributes).' * FROM users WHERE id_user = ?', $id); 
            $this->data = $res->fetch_assoc(); 
    }

}
 
Сверху