Проблема в проектировании ООП. Запись и список записей

Духовность™

Продвинутый новичок
Проблема в проектировании ООП. Запись и список записей

Здравствуйте.
У меня проблема случилась в проектировании.
Я не знаю, насколько я правильно поступил.

У меня есть класс record (запись) который инициализируется с числовым параметром - ID записи. Соответственно в конструкторе класса record идет 1 SQL запрос на выборку всех данных касательно этой записи.

Делаю вот класс list - список записей. И нужно мне в классе сделать метод для выборки всех записей.

Есть два пути реализации этого метода:

1. Выбрать все ID записей, потом пройтись циклом и сделать массив объектов record:

PHP:
while ($id_record = get())
{
    $records[] = new record($id_record);
}
и потом с этими объектами манипулировать.

Это ОЧЕНЬ плохой способ с точки зрения использования БД - получается 1 + N запросов. Но это хороший стиль программирования (надеюсь).

2. Вариант II менее ресурсоемкий. Вместо того, что бы вытаскивать ID записи, мы делаем нормальную выборку:

[sql]SELECT * FROM records[/sql]

однако в этом случае я не могу использовать все преимущества класса record, вся концепция летит к чертям.

Что посоветуете?
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Вариант номер три, который я обьяснял тебе же, делаешь класс RecordSet, который делает SELECT * FROM records
и имеет метод, ->getRecord(id) который возвратит тебе _объект_ типа Record. Сам класс RecordSet можно еще и сделать итеративным (aka поддерживающим интерфейс ArrayAccess или ArrayIterator, etc) чтоб крутить его форичем.
 

Духовность™

Продвинутый новичок
флоппик
не, тут либо я не понимаю, либо ты не так понял.

который делает SELECT * FROM records
и имеет метод, ->getRecord(id)
но мы в итоге к тому и приходим от чего ушли:
получается 1 + N запросов
что бы вывести список записей, т.к мой
класс record (запись) инициализируется с числовым параметром - ID записи. Соответственно в конструкторе класса record идет 1 SQL запрос на выборку всех данных касательно этой записи.
 

Подрыв мозга

Новичок
1. НИКОГДА не помещайте в конструктор объета ресурсоемких вычислений, а уж тем более выброку из базы данных (если только это не синглетон). Конструктор должен выполняться мгновенно. Почему? Если завтра я захочу создать объект в одном месте, а выборку сделать в другом, то это будет невозможно.

2. Все выборки из базы должны быть в статических методах (Record::findByID()б Record::findAll()): это типичный шаблон Active Record: http://www.martinfowler.com/eaaCatalog/activeRecord.html

3. Все уже придумано до нас - просто надо прочесть: Мартин Фаулер, Архитектура корпоративных программных приложений
 

Духовность™

Продвинутый новичок
Подрыв мозга
Хорошо? спасибо. Прочту обязательно.

А как мне с моей задачей поступить?

Вижу такой вариант:
- убрать выборку из конструктора в отдельный метод - getData($id_record)
- создать метод setData($data)
- получить список записей из БД
- создать массив объектов путем
PHP:
while ($data = get())
{
    $record = new record();
    $records[] = $record->setData($data);

}
 

Подрыв мозга

Новичок
Автор оригинала: triumvirat
А как мне с моей задачей поступить?
Ну почти. Небольшие поправки:

1) getData сделать статическим
2) А вот вместо setData() как раз-то и стоит использовать конструктор


PHP:
class Record
{
	public var $id = 0;
	public var $value = "";

	public static function findByID($id)
	{
		// Здесь делаем выборку ассоциативного массива из базы с помощью ващего любимого класса базы данных
		// ПРИМЕРНО так:
				
    	$data = mysql_fetch_array(mysql_query("SELECT * FROM record WHERE ID = " . (int)$id));		
		return new Record($data);
	}
	
	public static function findAll()
	{	
		$result = array();
		$rows = mysql_query("SELECT * FROM record");
    	while($data = mysql_fetch_array($rows))
    	{
    		$result[] = new Record($data);
    	}
    	return $result;		
	}
	
	public function __construct(array $data)
	{
		$this->id = (int)$data["ID"];
		$this->value = $data["Value"];
	}
}
Или использовать уже готовые решения в популярных фреймворках
 

Подрыв мозга

Новичок
Тогда используйте Gateway, Data Mapper, Transaction Script и куча еще всего: http://www.martinfowler.com/eaaCatalog/. Возьмите готовые решения, где все эти шаблоны уже реализованы. Книгу Архитектура корпоративных программных приложений на русском языке можно найти и скачаь за 5 минут (я вам этого не говорил). Обсуждение феймворков для работы с данными поищите на этом же форуме.
 

foto12

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

function getById ($id=0) {
if ($id == '0')
return false;

$where = "WHERE id = ".implode (" OR id = ", $id)
$select = "SELECT * FROM Table ".$where;

$get_select = mysql_query($select);

... А потом заносим все данные в массив и возвращаем 'return'


}
 

foto12

Новичок
А если так? это считается ООП ?

PHP:
class Sel_data
{
var $id=array();

function Sel_data ($id){
   $this->id = $id
}

function getById () {
 if(is_scalar($this->id)) $this->id = array($this->id);
 
if (!sizeof($this->id) 
      return false;

   $where = "WHERE id = ".implode (" OR id = ", $this->id)
   $select = "SELECT id, Name FROM Table ".$where;
   
   $get_select  = mysql_query($select);
   while ($data_arr = mysql_fetch_object($get_select)) {
      $one['id'] = $data_arr->id;
      $one['name'] = $data_arr->Name;
      $return[] = $one;
   }
return $return;

}
}

а потом вызываем
$id = array("1","2","10","13");

$data = new Sel_data($id);
выводим данные:
printf("<pre>%s</pre>", print_r($data->getById(), true));
 
Сверху