ОО подход к тривиальной проблеме

camka

не самка
ОО подход к тривиальной проблеме

К примеру есть класс продукта Product. У него есть свойства скажем ID, Name и Vendor_ID. Имею класс Поставщик. Vendor. У вендора есть ID и Name.

Внимание вопрос:

как было бы правильно и осуществить вывод продуктов с именет поставщика для каждого из них

Интересует стандартный ОО подход к решению проблемы.

есть 2 варианта.

1
PHP:
$product = new Product();
$vendor  = new Vendor();

//в цикле читаем все продукты
while ( $product->SelectAll(...))
{
      $vendor->init($product->Vendor_id);
      echo $product->Name.'  '.$vendor->Name;
}
В init происходит обращение к БД и выуживания свойств класса Vendor по айди.

Подход не нравится тем что в каждом цикле происходит обращение к БД для того чтобы выловить тока один Name вендора.

2.
Сделать в классе продукта атрибут Vendor_name и выуживать его уже в том же обращении к бд где происходит запрос на все продукты связав иннер джойном вендора и продукт. Но это уже как то не аккуратненько
 

tony2001

TeaM PHPClub
Я выходил из этой ситуации так:
Когда мне надо получить 1 такой объект, то это отдельный запрос.
Если много, то я делал один запрос и в цикле инициализировал эти объекты, передавая им в конструктор их свойства.
Не знаю, правда, насколько это корректно, но мне кажется достаточно логичным и удобным.
 

camka

не самка
2tony:
А откуда ты брал свойства их? из фетча?
то есть я так понял, что ты делаешь запрос к базе по всем продуктам(вариант для нашего примера). В том же запросе у тебя выдаются и имена вендора для каждого выбранного продукта.

а куда они идут после выборки из базы? в свойства продукта? выборка же происходит в методе класса продукта. Где они передаются в конструктор вендора? Где инициализируется объект вендора? В методе продукта?
 

tony2001

TeaM PHPClub
по порядку.
>А откуда ты брал свойства их? из фетча?
конечно.

>то есть я так понял, что ты делаешь запрос к базе по всем
>продуктам(вариант для нашего примера). В том же
>запросе у тебя выдаются и имена вендора для каждого
>выбранного продукта.
да

>а куда они идут после выборки из базы?
передаю в конструктор (можно в метод какой-то).
который уже распределяет приходящие данные по свойствам продукта.

>выборка же происходит в методе класса продукта.
это как вариант для одиночного вызова.
для множественного - этот метод я не юзаю.

>Где они передаются в конструктор вендора?
$obj = new Class($properties);

>Где инициализируется объект вендора?
можно в этом же цикле, если надо.
 

camka

не самка
Если не трудно можешь показать на примере. Я понял что у тебя все происходит так
PHP:
$query="select product.id as prodi, product.name as name, vendor.name as vendname from product inner join vendor on vendor_id=vendor.id";
$product=new product();

while($row=mysql_fetch_assoc($query))
{
        $product->init($row['$proid'],$row['proname']);
        $vendor=new vendor($row['vendname']);
}
если это так то это совсем не то что я имел .... ввиду

Короче я чего то недопонимаю
 

tony2001

TeaM PHPClub
что-то типа этого.

>Подход не нравится тем что в каждом цикле происходит обращение к БД для
>того чтобы выловить тока один Name вендора.
тебе это не нравилось - я предложил решение.
 

[VS]

Guest
Re: ОО подход к тривиальной проблеме

Автор оригинала: camka
К примеру есть класс продукта Product. У него есть свойства скажем ID, Name и Vendor_ID. Имею класс Поставщик. Vendor. У вендора есть ID и Name.
очень советую не привязывать OOP за уши туда, где оно не нужно.
сделай класс для получения данных в разных форматах и вариантах, причем уже готовых данных. Сколько запросов будет для этого сделано не интересует того кто вызывает функции класса. Более того, класс должен быть написан так, что-бы можно было бы написать другой класс с тем же интерфейсом, который хранит данные в файлах, в shm, и.т.д.

OOP предназначено для упрощения кода а не для усложнения.
 

camka

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

Хочется скрыть все обращения к БД в методах класса, чтоб интерфейс работы с объектами был предельно прост.

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

csa

Guest
для составных объектов (т.е. один содержит в себе еще несколько) я делал так:
- одним запросом (с джоинами) получал всю инфу для полей объектов (с применением алиасов в запросе, чтобы не перекрывались поля при формировании ассоциативного массива)
- передавал каждую строку (в виде массива) методу restore объекта-контейнера (который содержит в себе другие объекты)
- Restore из полученного массива выбирал свои поля и передавал этот массив всем вложенным объектам

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

camka

не самка
То есть обращение к базе происходит в теле программы а не в методе. Как то неприлично получается. По идее нам должно быть глубоко нас..ть на то откуда берется дата.
Захотел получить список продуктов. Вызвал метод СелектОлл(). Тебе скажем подобием рекордсета выдается заново инициализированный объект продукта для каждото продукта из списка поочереди.
Но тут вмешивается грубый вендор о котором мы знаем тока айди. Тут приходится инициализировать объект класса вендор чтобы его имя узнать .
 

.des.

Поставил пиво кому надо ;-)
camka если уж так хочется именно с ООП то первый твой способ, имхо самый верный.. для того чтобы его ускорить.. правильно наверное было бы ввести в реализацию класса вендор некоторые вспомогательные методы, которые бы не допускали бы такую загрузку базы.
хотя серьезно.. вот ты говоришь
То есть обращение к базе происходит в теле программы а не в методе. Как то неприлично получается. По идее нам должно быть глубоко нас..ть на то откуда берется дата.
по моему классу vendor должно быть наплевать откуда берутся данные. Ну а если ты уж работаешь с базой в методах, тогда можешь и кэширование этих самых запросов в нем же реализовать.
 

csa

Guest
примерно вот так:
PHP:
class Container {
  .....
function Restore($d)
{
   $this->field1 = $d['field1'];
   $this->field2 = $d['field2'];

   foreach($this->childs as $child)
      $child->Restore($d);
}
}


$set = $db->select("SELECT .. FROM ... LEFT JOIN ....");

while($row = $set->fetchAssocArray() ){
   $obj =& new Container;
   $obj->Restore($row);
   $obj_set[] = $obj;
}
т.е. у твоих продукта и вендора есть методы Restore, которые инициализируют поля объекта соответствующими полями массива.
так что этим объектам плевать, чьим рекордсетом их инициализируют, так как их инициализируют массивом
 

camka

не самка
Ну а если ты уж работаешь с базой в методах, тогда можешь и кэширование этих самых запросов в нем же реализовать.
Я так понимаю, кэширование это всех вендоров в рам качать. А если мне надо тока 2 продукта. А вендоров у меня 100000. Стыдно будет и негуманно.
 

csa

Guest
у меня используются вложенные объекты, но никто не мешает запихивать массив в несколько простых объектов, главное чтобы у каждого из них был Restore, а в SELECT'е были прописаны уникальные алиасы на выбираемые поля
 

csa

Guest
Автор оригинала: camka
Я так понимаю, кэширование это всех вендоров в рам качать.
зачем?
PHP:
function GetVendorName($id)
{
  static $cache=array();

  if(empty($cache[$id])){
     $cache[$id] = $db->getone("select name ... where id=$id");
  }
  return $cache[$id];
}
 

[VS]

Guest
Автор оригинала: camka
У меня в каждом классе (вендор, продукт) пользуется класс БД, я думаю, что его вполне реально было бы заменить на любой другой. (Спорно)
очень спорно.
не нужно использовать везде класс БД.
Напиши класс который будет выполнять только нужные тебе функции БД, и отдавать готовые массивы/структуры.
 

Vasya

Guest
IMHO, в листинге продуктов тебе нужны vendor_name & vendor_id
поэтому вынимаешь их джойном и суешь в продукт. А если юзер ткнет на имя вендора и захочет посмотреть на расширеную инфу по вендору., тогда и надо вынимать всю инфу по вендору. То бишь, в любом случае, в товаре должна быть ССЫЛКА на вендора, а не весь вендор.
 

csa

Guest
Автор оригинала: Vasya
То бишь, в любом случае, в товаре должна быть ССЫЛКА на вендора, а не весь вендор.
обрати особое внимание на
PHP:
$vendor->Name
в первом постинге
 

camka

не самка
Знающие товарищи подкинули следущий вариант. Оцените

ja by voobshe sdelal 5 klassov :

1. abstract database access class ... nazovem ego DataBase ... imeet metod chenit tipa Connect, Disconnect, Select(zapros) 2. ProductSelector - nasleduetsa iz DataBase ... ispolzuet roditelskij Select i vozvrashaet pachku objektov tipa Product 3. VendorSelector - nasleduetsa iz DataBase ... ispolzuet roditelskij Select i vozvrashaet pachku objektov tipa Vendor 4. Product - soderzit toka atributy ... metody esli i est to k baze dannyh ne otnosatsa 5. Vendor - takzhe

vozmozhny varianty
 
Сверху