За последние 24 часа нас посетили 18142 программиста и 1650 роботов. Сейчас ищут 1608 программистов ...

API форума

Тема в разделе "Решения, алгоритмы", создана пользователем Alost, 29 сен 2009.

  1. Koc

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

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    У него понятнее и не нужно для каждого condition/operators создавать объект [​IMG]. Хотя если есть желание - выкладывай.
     
  2. kostyl

    kostyl Guest

    Не, я обещал когда допилю - еще не допилил, но уже скоро ))
     
  3. Frozen

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

    С нами с:
    20 окт 2008
    Сообщения:
    540
    Симпатии:
    0
    Адрес:
    Москва
    это не тараканы, это уже грибы какието.
     
  4. Simpliest

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

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    От прослойки БД требуется всего 3 вещи

    Уметь делать запросы.
    Уметь использовать биндинг (они же prepared statements).
    Иметь возможность наследоваться от него.

    Вот это
    PHP:
    1. <?php
    2.  $result = Registry::get('Db')
    3.    ->query()
    4.    ->select('*')
    5.    ->from('Posts as Post')
    6.    ->join('Users as User', 'Post.UserID = User.ID')
    7.    ->where('Post.TopicID = %d', $this->argv['TopicID'])
    8.    ->compile()->run();
    9. ?>
    10.  
    Не имеет никаких преимуществ перед обычным

    PHP:
    1. <?php
    2. $query  = "SELECT * FROM Posts as Post
    3.        JOIN Users as User
    4.        ON Post.UserID = User.ID
    5.        WHERE Post.TopicID = ?";
    6. $stmt = DB::prepare($query); // MySQLi::prepare($query);
    7. $stmt->bind('s', $this->argv['TopicID']);
    8. $stmt->exec();
    9.  
    10.  ?>
    P.S. А сама идеология алиасов "Posts as Post" - меня убила. Зачем было именовать таблицы в множественном числе, чтобы потом приводить к единственному? :) Особая форма извращений?
     
  5. [vs]

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

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    kostyl
    Это Ц.
     
  6. Koc

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

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    Simpliest
    профит у билдера есть. Смотри сюда. Вот тут билдер бы помог хорошенько.
     
  7. kostyl

    kostyl Guest

    Simpliest
    Прослойка БД и билдер совсем разные вещи, не надо путать.
     
  8. sorteros

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

    С нами с:
    28 авг 2009
    Сообщения:
    54
    Симпатии:
    0
    SQL - это всё-таки полноценный язык. И делать над ним какую-то надстройку, какой-то билдер - это, извините меня, только самолюбие своё потешить. "Чистый" SQL гораздо лучше читаем, какие бы надстройки вы не сделали. ИМХО.
     
  9. Simpliest

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

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Нет. Смысла 0.
    Во-первых, убери копипаст в огромном количестве из кода.
    Во-вторых, у тебя есть два варианта -
    * моделей мало и они простые, но меняются часто, связей редко больше 1й. Соответственно выборки редко имеют больше 1го join и 3х условий в where - билдер тут, как зайцу стопсигнал.
    * моделей много, они сложные, но меняются редко, связей может быть и 3, и больше - билдер тут как швабра в истребителе (иметь можно, но бесполезно).

    Случаи, когда билдер бы помог это редкие исключения
    * моделей много, они сложные, и меняются часто.

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

    Да! Есть такие задачи - это написание самой ORM :)
    Но если ты используешь ORM, то билдер тебе и даром не нужен. У тебя должен быть прозрачный маппинг

    PHP:
    1. <?php
    2. $model->filter('id', function ($val) {return $val >5});
    3. echo $model;
    4. ?>
     
  10. Simpliest

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

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Однозначно.
    Универсальный билдер вне ORM - это непродуманное усложнение кода.
     
  11. kostyl

    kostyl Guest

    sorteros
    Это и ежу понятно, что чистый легче читаем, а билдер для того и служит чтобы собирать.
    Он ничё не должен, каждый делает как удобно, а то что там кто то умный написал - так это не постулаты...
     
  12. Simpliest

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

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    А это ваши личные комплексы, что кто-то умный вам написал.

    Я вам говорю, исходя из личного опыта. В свое время за 8 месяцев с нуля написал порядка 6Мб говнокода. (при том что копипаста там было не 30% кода как у вас, а чуть более 6%)
    Билдер вне ОРМ не дает никаких удобств и преимуществ.
    Билдер в ОРМ - для вас не должен быть виден, иначе ОРМ для вас бесполезен.

    Удобно говнокодить лапшу копипастом,
    вроде такого
    - делайте.
    Возможно, когда-нибудь прозреете.
     
  13. [vs]

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

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Билдер - часть внутренней архитектуры. Поэтому к обсуждаемому API форума отношения не имеет. Пользователю API не нужно думать о OMR с билдерами, ему нужен набор удобных методов для работы с форумом.
     
  14. Koc

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

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    Simpliest
    я вот не пойму как рефакторить этот код.
    У нас есть новости, разделы, к которым прикреплена новость (одна в нескольких), есть nice_url для новости, nice_url для разделов. Одновременно все сразу это не нужно. Где-то нужен список заголовков и краткого содержания новостей из категории такой-то, где-то одна новость, отфильтрованная по id и категории со ссылками, в которые она входит.

    Как это правильно реализовать, что б без повторяющихся кусков кода в том числе?
     
  15. Simpliest

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

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Для начала определись что тебе нужно.

    nice_url? ЧПУ что ли? а каким боком он относится к новости?

    Один метод.
    Второй метод.

    Это все что нужно?
     
  16. Simpliest

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

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Касательно кода. У тебя сложости из-за того, что ты выполняешь запрос фактически во время его формирования.

    Сначала определись, что за запрос у тебя будет. Затем вызови в одном месте

    PHP:
    1. <?php
    2. $query = ''
    3. ....
    4. $result = $DB::query($query);
    5. ....
    6. return $result;
    7. ?>
     
  17. Koc

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

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    ЧПУ. У каждой новости может быть своя ссылка. У каждой категории - тоже.

    Метод1, метод2... Я тоже так думал сделать. Но что если нужно будет фильтровать по категории, дате и пользователю? Да еще только те, которые не разу не редактировались. Будем писать метод 993: getNewsByUserNameMonthCategoryNotEditedOnce? Или напишем
    PHP:
    1. <?
    2. NewsCollection::instance()
    3. ->filterBy(array(
    4.     'user' => 'Alex',
    5.     'date' => '2009-12',
    6.     'categoryId' => 4,
    7.     'edited' => false
    8. ))
    9. ->get('date', 'title', 'nice_url', 'content_short');
    10.  
    11. Вот обсуждение [url=http://www.php.ru/forum/viewtopic.php?t=19636]http://www.php.ru/forum/viewtopic.php?t=19636[/url]
     
  18. Simpliest

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

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Це не має значення. ЧПУ не має ніякого відношення до фільтрації.
     
  19. Simpliest

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

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Дело в том, что 3,4,5 методов для наиболее типичных вариантов - это нормально.

    Но когда у тебя их (параметров фильтрации) становится больше - тебе придется рефакторить код. (Что самое интересное в этом случае ЧПУ станет не нужным и неэффективным)
    Это будет эффективнее попытки объять необъятное, поскольку у тебя уже будут готовые закономерности и требования к коду. Которые ты, на этапе проектирования, мог не видеть.

    Аналогия с профайлингом и оптимизацией - полная. Не имея конкретного решения оптимизировать нечего.

    В твоем случае решение может существенно упроститься, если ты будешь отдельно получать новости и отдельно категории.
    И только потом их объединять.
    Плюс прежний совет в силе - отделить формирование запроса от его выполнения.
     
  20. nimistar

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

    С нами с:
    30 май 2007
    Сообщения:
    919
    Симпатии:
    0
    Да, да, да - в жопу билдер :)

    Апи давай! :)
     
  21. Koc

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

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

    Возможно будет какое-то простое ЧПУ, на основе роутинга, без "супер"-уникальных ссылок.

    возможно ты и прав

    черт его знает. Я вообще хотел одним запросом получать и новости и категории в которых они а потом пыхом фильтровать. А формирование запроса и так частично отделено, сначала формируется и только в самом низу query.

    Но не перестает меня донимать мысль, что все было б просто круто с генератором:
    PHP:
    1. <?
    2. // ...
    3. if ($this->filter[categoryId])
    4.     $sql->leftJoin(self::TABLE, self::TABLE_NEWS2CAT, 'news_id=category_id')
    5.     $sql->andWhere('category_id=?i', $this->filter[categoryId])
    6. // ...
     
  22. Simpliest

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

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Я говорил про конкретный твой код.

    Да как-то некузяво оно отделено. И далеко не везде.

    с 99й по 277ю строки - сплошное спагетти-шаманство.
    Нет, я конечно понимаю как такой код получают (сам такое писал). Но это не нормально.

    Блин, да напиши проект с таким генератором. А лучше парочку.

    И все сам увидишь. Очинка выделки не стоит.
     
  23. TheShock

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

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    Как раааз реализую эту функциональность.

    В принципе, могу. Просто он еще сыроват да только для мускула драйвер есть

    Идёт из-за Зендовских стандартов именования и автолоада. плюс, чтобы названия классов разных подключенных библиотек случайно не скофликтовали.

    всмысле? ты про Джоины? ->get('User.*') ? о да. странно. смотрел код зенда — охуенный класс на 1000+ строк, фиг проссыш, что там написано. А с джоинами, сука, не работает. Такое впечатление, что создатели фреймворков не знают, что такое "Джоин".

    И? Оказалось безумно удобно. Допустим, у нас форум. Простой запрос типа:
    [sql]SELECT *
    FROM `prefix_topics` as `Topic`
    LEFT JOIN `prefix_posts` as `FirstPost`
    ON `FirstPost`.`ID` = `Topic`.`FirstPostID`
    LEFT JOIN `prefix_users` as `FirstUser`
    ON `FirstUser`.`ID` = `FirstPost`.`Author`.`ID`
    LEFT JOIN `prefix_posts` as `LastPost`
    ON `LastPost`.`ID` = `Topic`.`LastPostID`
    LEFT JOIN `prefix_users` as `LastUser`
    ON `LastUser`.`ID` = `LastPost`.`Author`.`ID`[/sql]

    PHP:
    1. <?php $query
    2.   ->select('*')
    3.   ->from('topics', 'Topic') // тут можно записать просто ->from('topics') и будет равно ->from('topics', 'topics')
    4.   ->leftJoin('posts', 'FirstPost', 'FirstPost.ID = Topic.FirstPostID')
    5.   ->leftJoin('users', 'FirstUser', 'FirstUser.ID = FirstPost.AuthorID')
    6.   ->leftJoin('posts', 'LastPost' , ' LastPost.ID = Topic.LastPostID')
    7.   ->leftJoin('users', 'LastUser' , ' LastUser.ID = LastPost.AuthorID')
    во-первых — префиксы расставляются автоматически. нету этих ужасных
    PHP:
    1. <?php $sql = "SELECT * FROM `" . $this->prefix . "topics`"
    во-вторых заметь — получилось не хуже, а, возможно. даже более понятно. чем native-sql

    в-третьих — у тебя есть этот запрос, который есть частью класса возвращающего коллекцию топиков. НО
    теперь представим, что мы захотели получить коллекцию топиков:
    1. Несмотря на раздел и тип — список последних обновленных, для трекера
    2. Для определенного раздела — упорядоченные сначала по типу, а потом - по дате
    3. Список топиков, которые создал юзер з айди $id
    4. Список всех топиков, имеющих тип "объявление"
    5. Определённый изменяемый лимит для опостраничнивания
    6. Количество найденных по топиков по одному из вышеназванных условий

    Ты что сделаешь? Будет на каждое из требований копипастить запрос, изменяя только часть? Или оставишь запрос в каком-то месте такого вида:
    PHP:
    1. <?php function getTopicsQuery($where, $order, $limit) {
    2. return "SELECT *
    3. ...
    4. $where $order $limit
    5. ";
    6. }
    тут тоже свои подводные камни. ты будешь писать запрос дважды, чтобы один раз поставить COUNT?
    а с квери билдером:
    Код (Text):
    1. 1. $q = $this->getTopics()->order('LastPost.ID')->page($page, 10); // подставится LIMIT зависимо от страницы
    2. 2. $q = $this->getTopics()->where('Topic.CatID = %d', $cat)->order('Topic.Type')->order('LastPost.ID')
    3. ...
    4. 6. $count = $q->getCount(); $result = $q->run();
    Суть понятна, я думаю
     
  24. Koc

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

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    я имел в виду, что у тебя указывается тип в where: ->where('id=%d', $_GET['id']) - это мне по нраву. В Kohana такого нет.

    а ничего кроме него и не требуется. Было б неплохо еще 2-3 примера: что задаем и что получим. И важна ли там очередность? Например я задал поля select, задал условия, но после взял и поменял поля (или добавил несколько).

    Префиксы у меня тоже автоматом расставляются:
    $db->fetchAll('SELECT id, title FROM ?t WHERE pid=?i', 'content', 3);
    mysqli_query('SELECT id, title FROM ad_content WHERE pid=3');
    fetch_assoc ...
     
  25. kostyl

    kostyl Guest

    Блин точно как нибудь выложу, пофиг, что не заточенную версию. На данный момент такие фишки имеются:
    1. Поддержка драйверов PDO и MYSQLi
    2. Поддержка плейсхолдеров как на параметры, так и на данные.
    3. Чистый функционал prepare-> execute
    4. Почти полный объектный SQL билдер.
    5. Поддержка синтаксиса MySQL PostgreSQL(пока только кавычки ;) )
    6. Слабосвязанность функционал БД с SQLбилдером.
    7. Не зависимость от порядка изменение частей запроса.
    8. Поддержка функций, подзапросов, джоинов, алиасов и вроде схем...
    9. Отдельный объект результатов Select
    Сейчас так не вспомню что еще.
    Скажите Simpliest, раз уж вы против, что лично вас не устраивает в таком наборе?
    (я просто спрашиваю, без претензий и т.п.)