Маленький, конкретезированный вопрос по ООП.

Статус
В этой теме нельзя размещать новые ответы.

Camillo

Новичок
Маленький, конкретезированный вопрос по ООП.

Привет.

Всё пытаюсь освоить ООП. И возник небольшой вопрос.
Пусть у меня есть класс User, который описывает все свойства объекта "Пользователь" и реализует несколько методов, например метод add()

PHP:
class User
{

public function __construct($arData) {

  $this->id = $arData['id'];
  $this->username = $arData['username'];
  $this->email = $arData['email'];
  $this->password = $arData['password'];

}

public function add() {

  $insertArr = array(
    'username' => $this->username,
    'email' = > $this->email,
    'password' => $this->encode_password($this->password)
  );

  global $DB;
  $DB->query("INSERT INTO users ?a", $insertArr);
  $r = $DB->query("SELECT LAST_INSERT_ID() as user_id");
  $this->id = $r[0]['user_id'];

}

public function remove() {

  global $DB;
  $DB->query("DELETE FROM users WHERE id=?", $this->id);

}

private function encode_password($password) {
  return md5($password);
}

}
Всё бы в принципе и нормально, но каким образом мне теперь реализовать метод, который бы выдавал список всех пользователей из БД?
Проще всего конечно было бы сделать просто класс, связанный с таблицей и напихать туда самых разнообразных методов, например

PHP:
class User
{

function insert($arData);
function remove($id);
function select($arData);
function uniq($field, $data);

}
Всё хорошо, но очень хочется попробовать имеенно ОБЪЕКТНЫЙ подход в действии, т.е. представить пользователя именно как объект.
Как бы вы это реализовали? Как эту идею правильнее всего реализовать?

Спасибо!
 

Angerslave

Новичок
Во-первых, в PHP есть type-hint. То есть юзай function insert(User $user)
Во-вторых, выдели функциональность работы с пользователями в отдельный метод. Или, как вариант, делать что-то типа такого:
PHP:
<?php

$user = new User();
$user->nick = "nick";
$user->save();

$user = new User("nick");
$user->delete();
Оба подхода имеют право на существование.
 

tashkentchi

Новичок
В моем аналогичном классе есть метод create:

PHP:
public static function create(array $data)
Он создает нового юзера и возвращает соответствующий ему объект.

Удаление пользователя:

PHP:
public static function del($login)
Есть еще метод save:

PHP:
public function save()
После того, как присваиваю свойствам юзера новые значения, вызываю save() для их сохранения.

Получение массива юзеров:

PHP:
public static function select($where, $order = null, $limit = null)
 

Camillo

Новичок
Вот так?

PHP:
// Класс, реализующий объект пользователь
class User 
{

public function __construct($arrData) {

	if (!isset($arrData) || !is_array($arrData)) die();
	
	$this->id 			= $arrData['id'];	
	$this->username 	= $arrData['username'];
	$this->email 		= $arrData['email'];
	$this->password 	= $arrData['password']; 		
	
}

public function get_username() {
	return $this->username;	
}

// get_свой

public function set_username($username) {
	$this->username = $username;
	return true;
}

}

// Класс, реализующий набор действий, которые можно производить с пользователем(ями)
class UserManager
{
	
	public function add(User $obj) {
		global $DB;
		$DB->query("INSERT INTO users SET ?a", $obj);		
	}
	
	public function remove(User $obj) {		
		global $DB;
		$DB->query("DELETE FROM users WHERE id=?", $obj->id);
	}
	
	public function find_by_id($id) {
		global $DB;
		$result = $DB->query("SELECT * FROM users WHERE id=? LIMIT 1", $id);
		if (isset($result[0])) {
			$user = new User($result[0]);
			return $user; 		
		} else {
			return false;
		}		
	}
	
	public function find_all() {
		$out = array();
		$results = $DB->query("SELECT * FROM users");
		foreach ($results as $result) {
			$out[] = new User($result);
		}		
		return $out;
	}
	
}
-~{}~ 15.02.09 12:29:

tashkentchi, т.е. у тебя вся работа с пользователями реализована в одном классе, да?
 

Camillo

Новичок
Ну блин, просто я в поисках разумного подхода. :)
Дело в том, что каждый раз приступая к написанию типового приложение (работа с БД через формы + AJAX) - я заново изобретаю велосипед.

Хотелось бы сформулировать какой-нибудь "костяк" (если хотите, то "шаблон") и потом его использовать уже не задумываясь о структуре приложения вообще. Просто стучать по клавиатуре пальцами и лазать в мануал. :)

Хорошо, что я приложения пишу по принципу избыточной функциональности и исключительно для себя. В противном случае на поддержку я бы тратил всё своё время. :)

-~{}~ 15.02.09 12:43:

А какие есть ORM "движки" хорошо документированные с хорошими примерами?
 

Angerslave

Новичок
google://php orm

В основном про Propel и Doctrine говорят.

-~{}~ 15.02.09 15:50:

> Хотелось бы сформулировать какой-нибудь "костяк" (если хотите, то "шаблон") и потом его использовать уже не задумываясь о структуре приложения вообще.
Дык сделай абстракный класс, а потом конкретную реализацию наследованием забивай.

Например, я себе 2 заготовки - List и Item сделал. ZF также позволяет (в документации это подробно расписано) наследоваться от DbTable и инициализироваться типа как в ORM. Короче, вариантов много, нужно только поискать и приложить голову.
 

AmdY

Пью пиво
Команда форума
не думаю, что нужно стремиться к ORM, это слишком ограничивает и самому написать с первого-второго-третьего раза невозможно.
 

x-yuri

Новичок
Camillo чем плох твой первый вариант - если в классе будет много бизнес-логики, то она смешается с кодом доступа к БД. Если разделить эти две вещи (в отдельные классы), то легче будет менять бизнес-логику (вся бизнес-логика будет в отдельном классе) и можно будет добавить/изменить источник данных (это уже просто невозможно без вышеописанного разделения)

Хотелось бы сформулировать какой-нибудь "костяк" (если хотите, то "шаблон") и потом его использовать уже не задумываясь о структуре приложения вообще. Просто стучать по клавиатуре пальцами и лазать в мануал.
время от времени его все равно надо будет менять. Можно разве что положиться на других людей (разработчиков ORM, CMS, CMF), но все равно будут какие-то изменения (ведь постоянно появляются новые возможности)

-~{}~ 16.02.09 00:28:

Camillo т.е. оба подхода имеют место быть, но для части ситуаций второй - лучше. Первый лучше за счет меньшего количества классов и кода, т.е. проще (как для реализации, так и для использования). Выбирай за тобой ;-)
 

Духовность™

Продвинутый новичок
в конструктор в рамках этой задачи не надо пихать какие-то данные.

никаких гет_юзернейм. Все данные должны лежать в определенном массиве, например, в $this->data. Получать и устанавливать через __get() и __set()

прот паттерн одиночку читал?

путь лучше возвращает объект типа Object_List. Object_List у меня примерно так сделан: http://phpclub.ru/paste/index.php?show=2262

т.е. будет

PHP:
    public function find_all() {
        $out = Object_List();
        $results = $DB->query("SELECT * FROM users");
        foreach ($results as $result) {
            $out->add( new User($result) );
        }        
        return $out;
    }
 

x-yuri

Новичок
в конструктор в рамках этой задачи не надо пихать какие-то данные
Camillo потому что в разных ситуациях будут указываться разные поля. Проще их с помощью оператора присваивания задавать, а не через конструктор

никаких гет_юзернейм. Все данные должны лежать в определенном массиве, например, в $this->data. Получать и устанавливать через __get() и __set()
если будешь под каждый метод писать get/set-методы, будет много тупого кода. Можешь предоставить непосредственный доступ к полям, если не собираешься какие-то промежуточные преобразования проводить. А если такое понадобиться, то всегда сможешь добавить

прот паттерн одиночку читал?
в случае с БД не вижу особой необходимости, если не в лом в каждом методе писать global

путь лучше возвращает объект типа Object_List
не вижу никаких преимуществ
 

HraKK

Мудак
Команда форума
Читаем про, MVC, ActiveRecord, Lazy Initialization ну и желательно Рефакторинг Того-Самого
 

HraKK

Мудак
Команда форума
Он сейчас это сам изобретает. Как внедрит посмотрит сам и решит - надо или нет. Я же не сказал что это маст хев?
 

Духовность™

Продвинутый новичок
в случае с БД не вижу особой необходимости, если не в лом в каждом методе писать global
разницы, естественно, НИКАКОЙ. Это просто идеология.

не вижу никаких преимуществ
мы оперируем объектами как понятиями. когда нам нужно произвести операции со всеми объектами, то лучше это делать в рамках объекта, который представляет собой коллекцию объектов.
 

x-yuri

Новичок
разницы, естественно, НИКАКОЙ. Это просто идеология.
triumvirat так а зачем советовать, если разницы нету? Ты же не просто предложил альтернативный вариант?

мы оперируем объектами как понятиями. когда нам нужно произвести операции со всеми объектами, то лучше это делать в рамках объекта, который представляет собой коллекцию объектов
чем лучше?
 

Духовность™

Продвинутый новичок
triumvirat так а зачем советовать, если разницы нету?
разница в том, что сингелтон - это паттерн проектирования.
а global - частная особенность языка
человек учится программировать с помощью объектов. так давайте и будем вариться в рамках ООП. Использование global, 20 раз уже говорили, это плохая практика.

Например тем, что если объект обладает методом foo(), то мы можем создать в классе Object_List метод getFooList() который будет возвращать список объектов, неважно в какой форме, обработанный этой самой foo()

PHP:
class Object_List ....
{
    function getFooList()
    {
        $data = array();
        foreach ($this->data as $object)
        {
            $data[] = $object->foo();
        }
        return $data;
    }
}
или мы можем создать метод Object_List::findByParams() и искать среди списка объектов необходимый нам объект по каким-либо параметрам.
 

Angerslave

Новичок
x-yuri
Отстой global в том, что если в одном "прекрасном" методе будет строчка global $db; $db = null;, то ты замучаешься дебажить. Пример, естественно, утрирован, но если где-то будет изменяться внутреннее состояние объекта напрямую, то геморра при поиске ошибки будет ещё больше.
 
Статус
В этой теме нельзя размещать новые ответы.
Сверху