За последние 24 часа нас посетили 19294 программиста и 1649 роботов. Сейчас ищут 904 программиста ...

class.News [всем спасибо, идеи по прежнему принимаются]

Тема в разделе "Прочие вопросы по PHP", создана пользователем Koc, 28 июн 2009.

  1. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    Есть новости и категории. Мне нужно создать API для получения этих новостей. Не могу придумать, как это лучше сделать. Пока есть такой вариант:

    PHP:
    1. <?
    2. class News:
    3.  
    4. getNews(array or string $fields, int $from, int $length, str $orderBy, str $orderType)
    5. /*
    6. возвращает в виде массива список новостей кол-вом $length начиная с $from отсортированных в соотв. с условиями. Из всех категорий.
    7. все аргументы - опциональны (по умолчанию будет что-то). $fields - поля, которые нужно вернуть (типа id, content, content_short, link_to_full)
    8. */
    9.  
    10. getNewsById(int $id, array or str $fields)
    11. // возвращает одну новость по ее IDшнику в базе. Привет, кэп!
    12.  
    13. getNewsByCategory(int $category_id, array or string $fields, int $from, int $length, str $orderBy, str $orderType)
    14. // тоже самое, что и getNews, но только из одной категории.
    15.  
    16. // ...
    17. /*
    18. как-то мне это не нравится. Длинные названия, много аргументов, везде префикс getNews.
    19. Было б прикольно сделать че-то типа
    20. */
    21. $news = new News;
    22. $news->select()->byId(3)->get();
    23. $news->select()->byCategory(5)->from(0)->length(10)->get();
    24. $news->select()->from(20)->length(10)->orderBy('id')->orderType('desc')->get();
    25. // но это тоже сомнительно.
    26.  
    Как быть? Что посоветуете?
     
  2. kostyl

    kostyl Guest

    PHP:
    1.  
    2. <?php
    3. //Одна новость
    4. $OneNew = new News($iId);
    5. //Несколько
    6. $News = new NewsCollection();
    7. $News->SetPage($iFrom, $iCount);
    8. $News->FilterCategory($iCatId);
    9. $News->Desc('id');
    10. //Ихмо мне удобнее через строчку писать, да у меня 22'', но все равно ИХМО лучше смотриться, чем длиннющая строка....
    11.  
     
  3. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    можно даже так, без дополнительной переменной
    PHP:
    1. <?
    2. $news = NewsCollection::create()
    3.     ->setPage(30, 10)
    4.     ->filterCategory(4)
    5.     ->order('id', 'desc');
    6.  
    7. $tpl->l('news', $news); // assign array to template
    8.  
    но каким образом я должен объяснить классу, что после order нужно делать запрос на выборку и возврат не экземпляра класса NewsCollection а именно массива?
    Тем более, что order можно оставить простой и тогда filterCategory должен возвращать массив.

    Имхо тут нужен еще метод get, который бы был завершающим и возвращал массив. (и возможно делал бы деструкт объекта)
     
  4. kostyl

    kostyl Guest

    Koc
    Тут всего навсего нужен Active Record. Тогда пока ты создаешь объект со всеми твоими вызовами у тебя внутри формируется только запрос. Потом при обращении к любому из свойств будь то просто или в foreach(это еще один намек на интерфейсы Countable и Iterator, которые я бы тоже реализовал), запрос будет вызываться и заполнять свойства. И вообще рекомендую сделать отдельную коллекцию для любых классов. Тобишь наследуешь от нее, задашь таблицы и свойства и все. И пофиг новости у тебя или пользователи или еще что...
     
  5. kostyl

    kostyl Guest

    блин, Lazy Load... Или как там? Чето я запутался вообще
     
  6. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    kostyl
    у меня есть в одминке ManagerCommon и ListerCommon в них всякие методы getRows, parseRows.
    Покопаюсь по поводу итератора. Недавно в какой-то книженции читал о нем.
     
  7. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    короче говоря как можно отследить обращение (а именно присвоение) к объекту?

    PHP:
    1. <?php
    2.  
    3. class NewsCollection
    4. {
    5.     private $param1 = 'e';
    6.     private $param2 = 'f';
    7.    
    8.     function __construct()
    9.     {
    10.        
    11.     }
    12.    
    13.     public function setParam1($param)
    14.     {
    15.         $this->param1 = $param;
    16.     }
    17.    
    18.     public function setParam2($param)
    19.     {
    20.         $this->param2 = $param;
    21.     }
    22.    
    23.     public function get()
    24.     {
    25.         return array('p1' => $this->param1, 'p2' => $this->param2);
    26.     }
    27. }
    28.  
    29. $n = new NewsCollection;
    30. $n->setParam1('a');     // установить параметр, но get не вызывать
    31. $c = $n->setParam2('b');    // установить параметр и вернуть метод get
    32. unset($n);
    33.  
    34. $n = new NewsCollection;
    35. $c = $n->setParam1('a'); // установить параметр и вернуть метод get
    36.  
     
  8. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Не использовать публичных переменных, только методы.
     
  9. kostyl

    kostyl Guest

    Да конечно, а нахера тогд нужны методы __get и __set ?
     
  10. kostyl

    kostyl Guest

    PHP:
    1.  
    2. <?php
    3.     /**
    4.      * Осуществляет доступ к свойству
    5.      * @param string $sPropertyName имя свойства
    6.      * @return mixed значение свойства
    7.      */
    8.     public function __get($sPropertyName)
    9.     {
    10.         if (array_key_exists($sPropertyName, $this->_arProperties)) {
    11.             if (!$this->_bIsLoaded) {
    12.                 $this->Reload();
    13.             }
    14.             return $this->_DBResult->{$this->_arProperties[$sPropertyName]};
    15.         }
    16.         else {
    17.             throw new SObjectCollectionException(__METHOD__ . '=>Property ' . $sPropertyName . ' does not exsists');
    18.         }
    19.     }
    20.  
     
  11. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    я слышал о магических методах, но опять-таки это - обращение к несуществующему свойству.
    PHP:
    1. <?
    2. $news = new NewsCollection;
    3. // ... установка параметров-условий
    4. $tpl->l('news', $news->list); // тут мы обращаемся к несуществующему полю list, вызывается метод __get, в нем выполняется запрос к БД, возврат результата в виде массива
    5.  
    НО: мы все равно обращаемся к полю, а чем это лучше вызова еще одного метода?.

    да, можно сделать и так:
    PHP:
    1. <?
    2. $tpl->l('news', NewsCollection::create()
    3.     ->setPage(30, 10)
    4.     ->filterCategory(4)
    5.     ->order('id', 'desc')
    6.     ->list); // assign array to template
    7.  
    но тогда уж логичнее писать так:
    PHP:
    1. <?
    2. $tpl->l('news', NewsCollection::create()
    3.     ->setPage(30, 10)
    4.     ->filterCategory(4)
    5.     ->order('id', 'desc')
    6.     ->get()); // assign array to template
    7.  
    и не нужно использовать магические методы
     
  12. kostyl

    kostyl Guest

    Koc
    Ну как хочешь. Смотря как в шабонизаторе у тебя будет. Мой шабонизатор слабоват. Он нихеране умеет, поэтому
    я обычно передаю в шаблон уже другой массив. Обработанный и все такое, тоесть чистый html. Поэтому я этот массив формирую не в классе, а в коде пробегая по коллекции в цикле, где надо преобразовывая что надо. А потому валю массив в шабонизатор и пусть он сам разбирается...
     
  13. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    Вот тут Ti пишет:
    это хорошо. Я смогу реализовать это посредством интерфейса IteratorAggregate. Но я не уверен, что мне нужно будет делать foreach. Как заставить выполняться запрос не только при использовании foreach но и по присвоению?
     
  14. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    я использую phparser

    короче тема интересная, но пока сделаю с методом get() по которому будет происходить запрос.

    kostyl
    спасибо, что обратил мое внимание на Collection и предложил разделить на несколько классов (News для одной, NewsCollection для массива).


    Если у кого-то есть пожелания-предложения - велком.
     
  15. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Это дает возможность создавать произвольные свойства, а в API все должно быть четко задано. Для этого даже interfaces есть =)
     
  16. kostyl

    kostyl Guest

    Koc
    [vs]
    Я имел в виду сделать класс Collection. Потом сделать класс NewsCollection и унаследовать его от Collection.
    Collection оперирует свойствами. NewsCollection - декларирует лишь поля в базе данных, например в конструкторе, в помощью parent::AddField('Name', 'sname') тоесть метода предка. __get и __set описаны в предке. Я так имел в виду.
     
  17. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    kostyl
    Торможу...)
     
  18. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    только вот я не учел, что getNewsBy ... легче реализовать чем динамическое навешивание фильтров.
     
  19. kostyl

    kostyl Guest

    Koc
    ну да через __call
     
  20. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    та не. Вся сложность в том, что fields, которые я буду получать - динамически задаются.

    К примеру можно написать
    get('id', 'title') // Это все в одной таблице, легко
    get('id', 'category_url') // тут мне нужно лезть в таблицу-связку для того, что б узнать к какой категории находятся новости (вложенный запрос) и еще в таблицу rewrites для получения nice_url для категории (join)

    То есть мне нужен или ORM или хотя б генератор запросов.

    а если до этого я еще поставил фильтр по категории? Жуть короче. Я в расстерянности.
     
  21. kostyl

    kostyl Guest

    Koc
    ну у меня уже все пашет, потому что у меня куча классов... Допустим по твоим проблемам у меня каждая коллекция содержит два объекта запроса. Тоесть у меня отдельный класс запроса, который динамически может напичкиваться всякой дрянью и в итоге выполняться. Ну поэтому все вместе работает почти ка ОРМ.
    Я считаю, что это должно инкапсулироваться в классе и ни в коем случае не маячить снаружи.
     
  22. Если быть точным, тебе нужен Criteria. в принципе, можно что нить похожее написать, не таща к нему весь правильный ОРМ.
     
  23. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    флоппик
    thanx, бум смотреть.

    а еще проблема, которую я не учел:
    новость находится в нескольких категориях. Указав в get: title, cat_titles мне нужно вернуть заголовок новости и массив названий категорий. Одним запросом никак?


    могу сделать запрос, который выдаст:
    id|заголовок|заголовок категории
    1|Заголовок|раздел 1
    1|Заголовок|раздел 3
    3|Midway продали без торга|раздел N
    5|Обновления Steam, TF2, Portal, Episode One и Two|раздел 1
    5|Обновления Steam, TF2, Portal, Episode One и Two|раздел 3

    но мне нужно как-то объеденить эти заголовки категорий в массив.
     
  24. kostyl

    kostyl Guest

    Пробежись рекурсивно по результату
     
  25. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    вы любите быдлокод? Да, капитан

    класс еще не дописан. Нужно подправить логику выдачи cat_ids, cat_titles, cat_urls
    и пока не обрабатывается ситуация когда нужны и категории и url's

    Это ужасно? Часть кода потом вынесу в абстрактный класс (в основном сеттеры).