Одна абстрактная сущность - один набор методов?

Духовность™

Продвинутый новичок
Одна абстрактная сущность - один набор методов?

Простите за не информативный заголовок, лучше не мог придумать =)

У меня сейчас возникла такая ситуация: я имею класс (классы или структурное программирование - не суть важно) для работы с заголиневшемся пользователем на САЙТЕ, фронтенд. Если абстрактно, то класс имеет такой интерфейс действий:

PHP:
$obj = new user();

if ($_COOKIE[....])
{
	// Авторизация
	$obj->checkUserByCookie($_COOKIE['cookie_user_email'], $_COOKIE['cookie_user_hash']);

		// тут мы вошли, в объекте хранятся данные пользователя, полученые из БД
		if ($obj->getIdUser() > 0)
		{
			// что-то делаем дальше с этим объектом
			$obj->exe('......');
		}

	// ...
Т.е. класс ориентирован на то, что все его методы выполнятся только в том случае, если имеются куки с логином/паролем. Такое бывает только в том случае, если от клиента посылаются "правильные" куки.

Но при построении административной части данный класс становится абсолютно бесполезным и некоторые его методы приходится копировать в виде структурного подхода. Например, метод

PHP:
public function getName()
{
    return $this->$userdata['name']
}
в административной части приходится переписывать как SQL запрос на извлечение имени:

PHP:
$db->query('SELECT name FROM ... WHERE id = ...')
Т.е. ситуация сложилась такая, что существующий класс якобы для работы с пользователем оправдывает себя только в среде с наличием куки и никак иначе.

Это собственно и вопрос - насколько разумно для одной сущности (пользователь) делать, скажем, два класса - класс, например, для фронтенда и класс бля бэкенда?
 

whirlwind

TDD infected, paranoid
Я думаю не разумно. Почему бы не сделать примерно так

PHP:
public function getName() 
{
    $this->loadFields(); 
    return $this->$userdata['name'];
}

function loadFields(){
    if ( $this->isLoaded ) return;
    // TODO: SELECT * FROM ...
}
-~{}~ 08.04.08 16:26:

И потом, у тебя checkUserByCookie( не в том месте находится. Куки это способ авторизации. Он у тебя может измениться при том, что модель юзера будет неизменной. Для авторизации я бы сделал интерфейс
PHP:
interface IAuthMod {
    function validateUser(User $user);
}
 

Духовность™

Продвинутый новичок
whirlwind
Вот ты пишешь
// TODO: SELECT * FROM ...
но для этого надо передавать id пользователя в метод. какой тогда смысл в классе, если он будет работать как простая функция?

-~{}~ 08.04.08 16:30:

Для авторизации я бы сделал интерфейс
возьму на заметку :)
 

whirlwind

TDD infected, paranoid
> но для этого надо передавать id пользователя в метод

Зачем? Нужно рассматривать объект как сущность, а не набор функций. Если у тебя сейчас вот этот код
PHP:
 $obj->checkUserByCookie($_COOKIE['cookie_user_email'], $_COOKIE['cookie_user_hash']);
все равно лезет в базу, значит он может получить ID или сразу все поля и выставить флажок isLoaded. Объект вполне может использовать внутренние механизмы класса, для того что бы привести себя в нужное состояние. Не обязательно каждый раз пинать объект, передавая ему все аргументы. В этом то и отличие от функций - состояние сохраняется.
 

Духовность™

Продвинутый новичок
я что-то не понял (

Если мы пишем

PHP:
function loadFields(){
    if ( $this->isLoaded ) return;
    // TODO: SELECT * FROM ...
}
то подразумеваем, что запрос SELECT * FROM ... использует некий id пользователя. Так вот этот id нужно как-то передать в объект, ибо метод checkUserByCookie я в бэкенде НЕ использую, как написал выше.

Охохо... как я за###лся.
 

whirlwind

TDD infected, paranoid
:) Ну так добавь метод который используешь. selectById, selectByEmail, etc... Неужели это сложнее, чем ломать голову по вопросу в первом посте?
 

crocodile2u

http://vbolshov.org.ru
/offtopic - даже не смотря на то, что тема и так в оффтопике...

Почему почти никто не использует фильртрацию пользовательских данных (это я насчет $_COOKIE['cookie_user_email'])? В пхп-5 появился отличный механизм - http://php.net/filter - избавляющий сразу от стольких проблем...
 

Beavis

Banned
crocodile2u
ну он ещё не доделанный... там даже длину строки проконтролировать нельзя
а так вообще, вещь удобная
 

crocodile2u

http://vbolshov.org.ru
Beavis
там можно и не только "длину строки проконтролировать". Можно, например, при желании, проследить, что ID был уникальным в твоей БД :)

triumvirat
Он ставится по умолчанию в 5-ке. Правда, в некоторых версиях работает с багами - но у меня на продакшн успешно работает версия из php-5.2.5

Единственный большой недостаток, который я вижу на данный момент - отсутствует нормальная поддержка юникода: ждем php-6.

Приношу извинения тем, кто прочитал следующее:

"у меня на продакшн успешно работает версия из php-5.3" - имел в виду 5.2.5. Просто в последнее время читаю про (и сам пробую писать на) пхп-5.3
 

jonjonson

Охренеть
Текущего посетителя проще сделать синглетоном.
PHP:
$visitor =& Visitor::getInstance();
if (!$visitor->isGuest()) {
    $visitor->getName();
}
В части же своей реализации Visitor может использовать UsersFactory и User. :)
PHP:
// получение объекта user по id
$user = UsersFactory::findById(HttpRequest::intPost("id", 0));
// получение авторизации на основе login
$user = UsersFactory::findByLogin(HttpRequest::strPost("login", ''));
// если пользователь не найден, то возвращаем false
if (!$user) {
    ...
}
Причём для правки информации других пользователей скорее нужен отдельный класс, опять же использующий для реализации UsersFactory и User.
 

whirlwind

TDD infected, paranoid
Предлагаю все классы сделать синглтонами. Так проще и это позволяет закрыть классы как от изменений, так и от расширений.
 

kode

never knows best
PHP:
class Auth{

private $login;
private $password;

public $errors = array();

function __construct($login=null,$password=null){
$this->login = ($login)?$login:$_COOKIE['user_login'];
$this->password = ($password)?$password:$_COOKIE['user_password'];
}

function check(){
if(empty($this->login) or empty($this->password)){
$this->errors[] = "Empty login or password";
return false;
}

//Проверяем БД
......
return true;
}

public function getUser(){

}


}

$auth = new Auth();

if($auth->check()){
$user = $auth->getUser();
}
 

Духовность™

Продвинутый новичок
kode
Спасибо. Понял.

whirlwind
Ну так добавь метод который используешь. selectById, selectByEmail, etc... Неужели это сложнее, чем ломать голову по вопросу в первом посте?
я сделал метод setId - он устанавливает ID пользователя. Теперь это выглядит примерно так:

Во фронтенде:
PHP:
    // Авторизация
    $obj->checkUserByCookie($_COOKIE['cookie_user_email'], $_COOKIE['cookie_user_hash']);

        // тут мы вошли, в объекте хранятся данные пользователя, полученые из БД
        if ($obj->getIdUser() > 0)
        {
            // что-то делаем дальше с этим объектом
            $obj->exe('......');
        }
А в бекенде, когда я получаю ID пользователя я просто передаю в объект этот ID

PHP:
$obj->setIdUser(555);
$obj->exe('......');
так наверно можно сделать, да?.... )
 

kode

never knows best
Автор оригинала: triumvirat
kode
Спасибо. Понял.
Можно сделать разные типы авторизации (например через БД, на основе различных других способов)

Также оформить можно по разному, сделать абстрактный Auth с

getUser() и требованием check(), либо интерфейс с check и getUser. Авторизировать классом User не надо, тут всё в маштабирование упирается...

getUser надеюсь ты понял о чём я :)

public function getUser(){
if($this->check()){
return new User($this->login);
}
return false;
//можно
//throw new Exception('User not authorized');

}
 
Сверху