Bug Tracker: изменения в проекте (часть третья)

Владимир | | Ajax, CodeIgniter, HTML, MySQL, PHP, Web разработка.

bug_tracker_logo_part3

Приветствую всех!

В этой статье продолжения рассказа о разработке собственной системы отслеживания ошибок. Предыдущие части вы найдете здесь и здесь.

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

База данных.

Первоначально я хотел максимально упростить структуру БД и перестарался. А именно: я решил хранить описания багов и комментарии к ним в одной таблице. В принципе, это возможно. Баги и комментарии имеют много одинаковых полей, и работать с такой таблицей было бы вполне реально.

Но я не учел, что при этом значительно усложняется код формирования страницы. Например, для создания списка багов с комментариями нужна рекурсивная функция с множеством проверок.

В общем, я решил, что лучше изменить базу данных сейчас, чем морочить себе голову потом 🙂

Новая структура базы данных выглядит следующим образом.

database_structure

Как видите, баги и комментарии к ним находятся в разных таблицах, которые связаны с помощью поля bug_id в таблице comments.

Это поле (bug_id) является внешним ключом и для него установлена опция ON DELETE CASCADE. Это гарантирует, что удаление записи в таблице bugs повлечет за собой автоматическое удаление (движком MySQL) всех записей из таблицы comments, у которых значение поля bug_id совпадает со значением поля id удаляемой записи.

Кроме того, таблица comments имеет ещё один внешний ключ – поле parent_id.

С его помощью можно создавать связанные списки комментариев. Т.е. значение этого поля должно совпадать со значением поля id родительского комментария. Если комментарий является первым в цепочке, то parent_id должно быть равно NULL.

Для этого поля также установлена опция ON DELETE CASCADE. Таким образом, удалив родительский комментарий, мы удалим всю цепочку. И, точно также, удаляя запись о баге, мы будем удалять все связанные комментарии, не зависимо от глубины их вложенности.

О таблице categories я рассказывал в прошлый раз. В ней ничего не изменилось.

Четвертая таблица (users) предназначена для хранения данных об администраторах баг трекера. Они могут удалять чужие записи. Добавить сообщение о баге или комментарий к нему может кто угодно без авторизации.

Структура приложения.

Тут я тоже решил внести некоторые изменения. Первоначально я планировал сделать одностраничное приложение, а весь функционал реализовать с помощью AJAX запросов.

Дело в том, что мне очень нравятся такие приложения. Они удобные, быстро работают и вообще это Web 2.0 🙂

Но есть одна проблемка – поисковики.

Если доступ к вашему приложению возможен только после авторизации, то и говорить не о чем. Поисковик всё равно до него не доберется. Но баг трекеры практически всегда открыты, и было бы очень не плохо добавить возможность поиска с помощью того же Google.

Я начал искать возможные пути решения проблемы и практически сразу наткнулся на пост в официальном блоге Google.

Подробно пересказывать его нет смысла. Если отбросить фразы в духе «мы понимаем роль AJAX и Flash в развитии интернета…», то суть сводится к следующему:

1) индексируется только текст;

2) для перемещения по сайту поисковому боту нужны обычные ссылки (ajax-ссылки, т.е. sitename.domen#... игнорируются).

Т.е. делать сайт можно как угодно, но Google проиндексирует только то, что найдет. И, насколько я знаю, с Яндексом ситуация такая же.

Попасть в индекс и при этом использовать AJAX можно с помощью методики Progressive Enhancement (постепенного улучшения).

Это означает, что разрабатывать сайт нужно так, чтобы с ним можно было нормально работать при отключенном JavaScript и CSS стилях (т.е. посетитель должен видеть весь необходимый ему контент, иметь возможность перемещаться по страницам и отправлять данные с помощью форм). Включение JavaScript должно увеличивать удобство работы с сайтом, например, добавлять поддержку асинхронной загрузки данных (AJAX), создавать различные визуальные эффекты вроде слайдеров, выпадающих меню и т.п.

Кстати, есть хорошее слайд-шоу о Progressive Enhancement.

У этой методики есть ещё одно преимущество (кроме индексации поисковиками), с сайтом можно будет работать, используя устройства чтения с экрана.

Поэтому на первом этапе мы напишем баг трекер без использования ajax. Т.е. все ссылки будут обычными, например,

bugtracker.local/bugtracker/addbug

После этого, мы с помощью JavaScript будем изменять эти ссылки для использования в AJAX запросах. Например, предыдущая ссылка будет выглядеть так:

bugtracker.local/bugtracker#addbug

Поисковый бот JavaScript не выполняет, поэтому он будет работать с первым вариантом ссылки, а посетители – со вторым.

Теперь рассмотрим перечень страниц баг трекера.

index — главная, отображается форма добавления сообщения о баге, список багов с комментариями и навигация;

page/id – показываем выбранную страницу (id – номер страницы), тоже самое, что и index, т.е. index соответствует page/1;

category/id — тоже самое, что и page/id, только показываем баги, относящиеся к указанной категории;

bug/id — страница с выбранным багом, внизу будет форма для добавления комментария;

bug/add — добавляет новое сообщение о баге (передача данных методом POST);

bug/addcomment — добавляет комментарий к выбранному багу (данные передаём методом POST);

bug/remove — удаляет выбранный баг (id бага передается методом POST).

comment/remove — удаляет выбранный комментарий.

Это ориентировочный список. При необходимости можно будет добавить ту или иную функцию.

В следующих выпусках мы подробно рассмотрим добавление нового сообщения о баге и формирование страниц приложения.

До встречи!

P.S. Если есть вопросы или предложения, пишите в комментариях, обсудим 😉

  • Big_Shark

    То есть допустим в определенной категории 2 страница будет выгладить так ?
    category/id/page/id ?

    bug/addcomment Думаю что лучше форму добавления комментария сделать на страницы bug/id

    Хорошо что вы все таки решили переделать структуру БД.

    • Нет, немного по-другому (я пропустил этот момент).

      category/id/page_id

      category — имя метода в контроллере, после него идут параметры, первый — id категории, второй page_id — номер страницы. Точнее, это не номер страницы. Это номер записи с которого начинается вывод на данной странице. Подробнее этот момент я опишу вместе с использованием библиотеки пагинации.

    • Думаю что лучше форму добавления комментария сделать на страницы bug/id

      Она там и будет находится. bug/addcomment страницу не создает, просто данные добавятся в базу и после этого будет выполнен редирект на страницу с которой вы отправили форму (например, bug/5).

  • Big_Shark

    То есть допустим в определенной категории 2 страница будет выгладить так ?
    category/id/page/id ?

    bug/addcomment Думаю что лучше форму добавления комментария сделать на страницы bug/id

    Хорошо что вы все таки решили переделать структуру БД.

    • Нет, немного по-другому (я пропустил этот момент).

      category/id/page_id

      category — имя метода в контроллере, после него идут параметры, первый — id категории, второй page_id — номер страницы. Точнее, это не номер страницы. Это номер записи с которого начинается вывод на данной странице. Подробнее этот момент я опишу вместе с использованием библиотеки пагинации.

    • Думаю что лучше форму добавления комментария сделать на страницы bug/id

      Она там и будет находится. bug/addcomment страницу не создает, просто данные добавятся в базу и после этого будет выполнен редирект на страницу с которой вы отправили форму (например, bug/5).

  • в таблицу users добавить бы мыло, чтобы узнавать о изменениях и закрытиях бага например, ну еще бы связать с таблицей bugs, чтобы знать кто указал на баг это например uid_report, и кто пофиксил баг uid_fixed, ну и добавить бы дату фиксации бага fix_date

    в комментариях, я как понимаю раз есть parent_id то это древовидные собираются быть, может поглядеть в сторону Nested Sets добавить еще пару полей и обсчитывать при добавлении?

    • Big_Shark

      Так как это статья для обучения то не думаю что стоит с самого начала переходить на Nested Sets так как он сложнее и его оправданность в данном случае стремиться к 0.
      Из за того что комментарии будут добавляться достаточно часто и пересчитывать каждый раз дерево будет затруднительно.

    • Big_Shark прав. Слишком сложно. Нужно писать отдельную статью.

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

  • в таблицу users добавить бы мыло, чтобы узнавать о изменениях и закрытиях бага например, ну еще бы связать с таблицей bugs, чтобы знать кто указал на баг это например uid_report, и кто пофиксил баг uid_fixed, ну и добавить бы дату фиксации бага fix_date

    в комментариях, я как понимаю раз есть parent_id то это древовидные собираются быть, может поглядеть в сторону Nested Sets добавить еще пару полей и обсчитывать при добавлении?

    • Big_Shark

      Так как это статья для обучения то не думаю что стоит с самого начала переходить на Nested Sets так как он сложнее и его оправданность в данном случае стремиться к 0.
      Из за того что комментарии будут добавляться достаточно часто и пересчитывать каждый раз дерево будет затруднительно.

    • Big_Shark прав. Слишком сложно. Нужно писать отдельную статью.

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

  • хм… ну так то да… если уж обучающая тогда комменты можно и без дерева, чтобы зря их потом не дёргать кучей запросов в рекурсии 🙂

    • Big_Shark

      А мы их и не будем дергать кучей запросов.
      Мы выбираем все комменты по bug_id и загоняем их в массив из которого с помощью рекурсии делаем многомерный массив в виде дерева.
      Есть куча примеров типа как написать блог за 20 минут и там описано как создавать комментарии но я что то давно не видел как создавать древовидные комментарии по этому будет очень интересно посмотреть.

      • Big_Shark абсолютно прав.
        Никаких запросов в рекурсивных функциях не будет. Результаты запроса будут преобразованы в многомерный массив с помощью PHP.

        Такой массив удобно сформировать в любом случае не зависимо от того, получаем мы данные одним запросом или несколькими. Его удобно выводить в цикле и, например, встроенный в CI шаблонизатор требует чтобы ему данные передавались именно в таком формате.

        • ну тогда странно получается, написать функцию обсчета дерева, строк 50 это «слишком сложно», а дёргать запросом весь массив данных и перестраивать рекурсией во вложенные массивы это не сложно… хыхы, не академично… стоит тогда вообще отказаться от древовидных комментов, обычные подряд комменты, раз уж академический проект 🙂

        • Я имел в виду, что сам принцип работы с Nested Sets довольно сложный. Посмотрите, например, эту статью и сравните сколько от её объема занимает Adjacency List Model, и сколько Nested Set Model.

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

          Обычные комментарии, конечно, проще, но рекурсивная функция не будет сложной (меньше 50 строк 😉 ).

  • хм… ну так то да… если уж обучающая тогда комменты можно и без дерева, чтобы зря их потом не дёргать кучей запросов в рекурсии 🙂

    • Big_Shark

      А мы их и не будем дергать кучей запросов.
      Мы выбираем все комменты по bug_id и загоняем их в массив из которого с помощью рекурсии делаем многомерный массив в виде дерева.
      Есть куча примеров типа как написать блог за 20 минут и там описано как создавать комментарии но я что то давно не видел как создавать древовидные комментарии по этому будет очень интересно посмотреть.

      • Big_Shark абсолютно прав.
        Никаких запросов в рекурсивных функциях не будет. Результаты запроса будут преобразованы в многомерный массив с помощью PHP.

        Такой массив удобно сформировать в любом случае не зависимо от того, получаем мы данные одним запросом или несколькими. Его удобно выводить в цикле и, например, встроенный в CI шаблонизатор требует чтобы ему данные передавались именно в таком формате.

        • ну тогда странно получается, написать функцию обсчета дерева, строк 50 это «слишком сложно», а дёргать запросом весь массив данных и перестраивать рекурсией во вложенные массивы это не сложно… хыхы, не академично… стоит тогда вообще отказаться от древовидных комментов, обычные подряд комменты, раз уж академический проект 🙂

        • Я имел в виду, что сам принцип работы с Nested Sets довольно сложный. Посмотрите, например, эту статью и сравните сколько от её объема занимает Adjacency List Model, и сколько Nested Set Model.

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

          Обычные комментарии, конечно, проще, но рекурсивная функция не будет сложной (меньше 50 строк 😉 ).

  • Terry

    Скажите пожалуйста, какой тулзой создаються такие графические представления таблиц БД?

    • MySQL Workbench
      В бесплатной версии сохранить диаграмму в виде картинки нельзя, но делать скриншоты никто не мешает 😉

  • Terry

    Скажите пожалуйста, какой тулзой создаються такие графические представления таблиц БД?

    • MySQL Workbench
      В бесплатной версии сохранить диаграмму в виде картинки нельзя, но делать скриншоты никто не мешает 😉

  • В принципе нормально, я себе так и представлял, но пользуюсь mantis'ом — там всётаки и разбиение по проектам есть и управление пользователями. Не хотелось заново всё писать.

  • В принципе нормально, я себе так и представлял, но пользуюсь mantis'ом — там всётаки и разбиение по проектам есть и управление пользователями. Не хотелось заново всё писать.

  • Злодей

    Если вы урок пишете — то будте добры код выкладывать. С картинок непонятно какие ключи и какие настройки полей в таблицах базы.
    Вобщем SQL запросик для создания бд выложите плиз.

  • Злодей

    Если вы урок пишете — то будте добры код выкладывать. С картинок непонятно какие ключи и какие настройки полей в таблицах базы.
    Вобщем SQL запросик для создания бд выложите плиз.

  • Очень хорошая онлайн аптека торгующая индийскими таблетками, медикаментами и препаратами.