ООП. Разделение логики объектов

Nicki

Новичок
ООП. Разделение логики объектов

Я поискал по форуму, но ответа не нашел, хотя не исключено что он уже есть. Очень прошу помочь мне разобраться ссо следующей "задачей". Наверное вопрос из разряда ламерских, но все же. Я приведу пример из своей реализации. Это класс модуля Юзеры. Модуль производит управление профаилами зарегистрированных на сайте юзеров.

PHP:
abstract class Module
{
    protected $Dao  = null;         // ссылка на объект
    protected $User = null;         // ссылка на объект
    protected $Templator = null;    // ссылка на объект
    protected $Request   = null;    // ссылка на объект
    protected $moduleId    = 0;        // идентификатор модуля в таблице core_modules
    protected $moduleName  = '';       // кодовое имя модуля
    protected $errors      = array();  // массив с сообщениями об ошибках

    public function __construct()
    {
        $this->Dao = Core::getDao();
        $this->User = Core::getUser();
        $this->Templator = Core::getTemplator();
        $this->Request = Core::getRequest();
    }

public function isErrors()  { return (0 != sizeof($this->errors)? true:false); }
public function getErrors() { return $this->errors; }

/**
* Проверяет, возможность выполнить команду модуля текущим юзером
* @param string $commandName Имя команды модуля
* @return bool
**/
public function isHaveAccess($commandName)
{
    return $this->User->isHaveAccess($this->moduleName, $commandName);
}

/**
* Метод выполнения команд модуля
* @param string $commandName Имя команды модуля
**/
public abstract function executeCommand($commandName);
}

class Users extends Module
{
    protected $moduleName = 'users'; // внутреннее имя модуля
    public function __construct()
    {
        // вызов общего конструктора
        parent::__construct();
    }
function executeCommand($commandName)
{
    // если юзер не имеет права на выполнение команды модуля
    if (! $this->isHaveAccess($commandName)) header('Location: index.php');
    
    // выполнить команду
    switch ($commandName)
    {
        // регистрация нового юзера
        case 'reguser': include_once 'commands/reguser.cmd.php'; break;
        // послать письмо подтверждения регистрации
        case 'sendact': include_once 'commands/sendact.cmd.php'; break;

        // другие команды модуля
        ....
    }
}

/**
* возвращает данные юзера
* @param  Int     $userId     - ID юзера
* @return Array
**/
function getUserData($userId) {}

/**
* возвращает массив с данными юзеров удовлетворяющих условиям отбора
* @param  Array   $conditions - массив с критериями отбора
* @return Array
**/
function getUsersData($conditions) {}

/**
* добавляет данные юзера в БД
* @param  Array   $userData   - массив с данными регистрируемого юзера
* @return Int                 - идентификатор добавленного в БД юзера
**/
function insertUser($userData) {}

/**
* посылает юзеру письмо с ссылкой для подтверждения регистрации
* @param  String  $email  - имаил юзера
* @return bool
**/
function sendConfirmRegistration($email) {}

/**
* активирует профаил юзера подтверждая его регистрацию.
* @param  Array   $profileData    - данные необходимые для активации профаила
**/
function activateProfile($profileData) {}

/**
* удаляет юзера из БД
**/
function deleteUser($userId) {}

}
Вот насколько правильная/неправильная такая реализация модулей, подскажите пожалуйста. Может ктото чтото подобное использует? К примеру у меня возникают какие то сомнения, например, в том что это вообще правильный "объект", т.к. он больше смахивает все таки на библиотеку функций (для работы с записями юзеров в БД - для чего и нужен модуль)...
 

HraKK

Мудак
Команда форума
Да не понятно что ты хочешь. Как там было? А вопрос то в чем?(с)
он больше смахивает все таки на библиотеку функций (для работы с записями юзеров в БД - для чего и нужен модуль)...
А ты что хочешь?
 

Angerslave

Новичок
if (! $this->isHaveAccess($commandName)) header('Location: index.php');

После этой строчки выполнение функции продолжается, даже несмотря на отсутствие прав.

Только непонятно, класс называется Users, но у него есть конструктор... То есть будет что-то вроде $Vasya = new Users(); ? Плюс, что-то действительно является функцией, а что-то - методом объекта. Наверное, следует выбрать - либо мы полностью ориентируемся на объекты, либо пишем всё статическими методами и тогда у нас действительно получится библиотека функций.
 

Nicki

Новичок
У меня после того как проходит проверка прав юзера на выполнение команды, т.е.
if (! $this->isHaveAccess($commandName))
происходит редирект на первую страницу, а там уже присваивается по дэфолту имя модуля и имя команды которые разрешено использовать всем.

Angerslave
Почему продолжается? Может exit; добавить после header()?
А вот по остальному я и прошу мне немного помочь.

Наверное, следует выбрать - либо мы полностью ориентируемся на объекты, либо пишем всё статическими методами и тогда у нас действительно получится библиотека функций.
Вот я бы хотел сделать на объектах а не библиотеках. Конструктор в данном объекте (и всех других модулях) фактически ничего не делает - просто запускает конструктор предка (класс Module), в котором присваиваются свойства, а именно получаются ссылки на объекты Db, Шаблонизатора, Запроса и Юзера в текущей сессии (в котором и хранится инфа о доступных юзеру правах выполнения команд). Подскажите что убрать, что добавить?
У меня есть предположение что я засунул сюда сразу логику объекта, который должен отвечать за выполнение команд модуля, и логику, собственно управления пользователями, которые регистрируются/зарегистрированны на сайте. Плюс еще мне кажется нужно выделить объект Юзер и объект Юзеры - или как то так... ну вот к примеру сейчас есть метод getUserData() который возвращает данные только одного юзера, и метод getUsersData(), который уже возвращает данные нескольких юзеров. Мне кажется это нужно разделить на 2 объекта, а не писать все в одном. Так ли это?
 

Angerslave

Новичок
Nicki, можно exit, можно die, можно return и показать дулю на экране...
По поводу реализации - тут, думаю, можно разделить котлеты и мухи. Пусть будет класс, экземпляры которого будут представлять юзера и будет какой-то статический класс-библиотека для добавления/перемещения/ещё чего-нибудь юзеров. Можно, дополнительно, посмотреть как реализована работа с пользователями в известных фреймворках/CMS.
 

Nicki

Новичок
Я попробовал выделить сущьность описывающую зарегистрированого юзера. Т.к. при регистрации юзера происходит добавление учетной записи я назвал класс User_Profile, и объединил в нем возможные операции с профаилом юзера. Вот что у меня получилось. Если можно подскажите что поменять или добавить нужно, может метод confirm() тут лишний?

PHP:
class User_Profile {
    private $id;
    private $password;
    private $email;    
    private $nick;    
    private $avatar;
    private $timezone;
    private $isConfirmed;
    private $dateReg;
    private $sex;        
    
    function __construct($id) {
        $this->load($id);
    }
    
function set($name, $value) {}
function get($name) {}
    
// загружает данные юзера из бд
function load($id) {}
// обновляет данные в бд
function update() {} 
// добавляе данные в бд
function add() {}
// ставит флаг подтверждения регистрации
function confirm($confirmCode) {}
}
Получается что теперь регистрацию юзера можно делать так:
PHP:
$Profile = new User_Profile;
$Profile->set('email', $email);
$Profile->set('nick', $nick);
$Profile->set('password', $pass);
// ... еще необходимые set();
$Profile->add();
или лучше так сделать?
PHP:
$Profile = new User_Profile;
$Profile->add($email, $nick, $pass);
И вот по поводу удаления профаила... его тоже можно возложить на плечи объекта User_Profile или это уже не его обязанность, а какого то менеждера профаилов? Вот, например, если так
PHP:
$Profile = new User_Profile;
$Profile->delete($id);
 

Angerslave

Новичок
Лучше тогда в конструктор передавать $id. А при добавлении передавать null.
 

Altex

Новичок
Лучше вообще сначала почитать про ООП, ORM, паттерны, рефакторинг и так далее. То, что автор пытается использовать в виде User_Profile называется Active Record, а я бы на месте автора делал бы лучше с помощью Mapper'а. Вобщем поиск и гугл поможет, или хотя бы википедия.
 
Сверху