Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Скриптовые языки программирования > PHP
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 15.11.2010, 07:29   #1
Nikolai_
Пользователь
 
Регистрация: 27.08.2010
Сообщений: 16
По умолчанию Рубрики статей

Столкнулся с такой задачей. Мне необходимо задавать статьям категории (рубрики). У одной статьи может быть задано несколько (до 5) категорий. Всего же типов категорий более 100. Решил создать поле category типа varchar(20) и записывать туда id категории в таком виде (через запятую):
Код:
5
8
6,7
8,3,7,4,5
а выборку по конкретной категории произвожу так
PHP код:
$query mysql_query("SELECT * FROM articles WHERE category='$category' OR category LIKE '$category,%' OR category LIKE '%,$category,%' OR category LIKE '%,$category'"); 
Прошу опытных программистов оценить это решение – может быть можно было сделать проще и запрос составить попроще?
Nikolai_ вне форума Ответить с цитированием
Старый 15.11.2010, 09:12   #2
Виталий Желтяков
Старожил
 
Аватар для Виталий Желтяков
 
Регистрация: 19.04.2010
Сообщений: 2,702
По умолчанию

ENUM - тип поля, который вам нужен. Это самое правильное решение.
Виталий Желтяков вне форума Ответить с цитированием
Старый 15.11.2010, 09:15   #3
Nikolai_
Пользователь
 
Регистрация: 27.08.2010
Сообщений: 16
По умолчанию

Но ведь в поле ENUM можно будет записать только одну рубрику. А мне надо несколько рубрик для одной статьи.
Nikolai_ вне форума Ответить с цитированием
Старый 15.11.2010, 10:45   #4
Andkorol
Старожил
 
Регистрация: 31.05.2010
Сообщений: 3,301
По умолчанию

Я бы создал дополнительно промежуточную таблицу article_categories:
article_id
category_id
с индексом по category_id

Затем при добавлении новой статьи(и назначении ей нужных категорий) - заносим категории в эту таблицу:
PHP код:
// подразумевается предварительная обработка значений
$query "INSERT INTO `article_categories` (`article_id`, `category_id`)
                     VALUES ('
$article_id', '$category_id_1'),
                                ('
$article_id', '$category_id_2'),
                                ('
$article_id', '$category_id_N')";// нужное кол-во категорий 
Ну а при выводе статей для нужной категории - просто запрашиваем нужную категорию в промежуточной таблице,и по ней выбираем статьи:
PHP код:
// подразумевается предварительная обработка значений
$query "SELECT a.* FROM `articles` a 
                               JOIN `article_categories` ac 
                                        ON ac.`article_id` = a.`id`
                             WHERE ac.`category_id` = '
$category'
                               LIMIT 
$start$limit"
Всё это примерно,конечно - просто чтоб показать принцип.
Andkorol вне форума Ответить с цитированием
Старый 15.11.2010, 11:33   #5
Nikolai_
Пользователь
 
Регистрация: 27.08.2010
Сообщений: 16
По умолчанию

Andkorol, а какие недостатки по Вашему имеются в моем решении?
Nikolai_ вне форума Ответить с цитированием
Старый 15.11.2010, 13:01   #6
Виталий Желтяков
Старожил
 
Аватар для Виталий Желтяков
 
Регистрация: 19.04.2010
Сообщений: 2,702
По умолчанию

Цитата:
Но ведь в поле ENUM можно будет записать только одну рубрику. А мне надо несколько рубрик для одной статьи.
Так создайте несколько полей. Скорость выборки нескольких полей из одной таблицы будет гораздо выше, чем сложные запросы к двум таблицам или использование like.
Данный метод проверен мною.
Виталий Желтяков вне форума Ответить с цитированием
Старый 15.11.2010, 16:59   #7
ssdm
Форумчанин
 
Регистрация: 20.05.2009
Сообщений: 506
По умолчанию

Цитата:
Сообщение от Виталий Желтяков Посмотреть сообщение
Так создайте несколько полей. Скорость выборки нескольких полей из одной таблицы будет гораздо выше, чем сложные запросы к двум таблицам или использование like.
Данный метод проверен мною.
А если рубрик будет 10 ?
ssdm вне форума Ответить с цитированием
Старый 15.11.2010, 23:21   #8
Andkorol
Старожил
 
Регистрация: 31.05.2010
Сообщений: 3,301
По умолчанию

Цитата:
Сообщение от Nikolai_ Посмотреть сообщение
а какие недостатки по Вашему имеются в моем решении?
Ну, во-первых конечно скорость : обработка вашей "LIKE-вереницы", да ещё и при большом количестве статей - дело не быстрое.

Далее - например,вы захотели изменить/удалить одну из категорий статьи.
Вам нужно для этого:
1.Получить значение категорий для данной статьи (1-й запрос).
2.Разбить полученную строку на элементы при помощи explode().
3.Найти в полученном массиве нужный ID.
4.Заменить его на новый(или удалить).
5.Собрать обратно новую строку при помощи implode().
6.Внести новое значение в Базу(2-й запрос).

В моём варианте:
PHP код:
// подразумевается предварительная обработка значений
$query "UPDATE `article_categories` 
                     SET `category_id` = '
$new_value'
                     WHERE `article_id` = '
$article_id'
                     AND `category_id` = '
$old_value' ";
// или для удаления
$query "DELETE FROM `article_categories` 
              WHERE `article_id` = '
$article_id'
              AND `category_id` = '
$old_value' "
Или,допустим, у вас возникла необходимость вывести статьи по нескольким категориям сразу.
В моём случае в запрос просто добавляется такое условие :
Цитата:
WHERE `category_id` IN('$category_1', '$category_2', ..., '$category_N')
В вашем - так сходу даже и не придумаю,как это реализовать....

Всё дело в гибкости и масштабируемости.
Нужно сразу,на этапе разработки, планировать ВСЕ возможные варианты развития событий в приложении.
То,что вам сейчас кажется "ненужным и врядли когда-то необходимым" - завтра может стать ключевым моментом в вашем приложении.
И будет весьма уныло переписывать горы функционала ради какой-нибудь мелкой опции,невозможной при существующем коде.
Andkorol вне форума Ответить с цитированием
Старый 16.11.2010, 08:09   #9
Nikolai_
Пользователь
 
Регистрация: 27.08.2010
Сообщений: 16
По умолчанию

Спасибо, Andkorol, за внятные разъяснения. Особенно вот эта часть была для меня очень полезна:

Цитата:
Сообщение от Andkorol Посмотреть сообщение
Всё дело в гибкости и масштабируемости.
Нужно сразу,на этапе разработки, планировать ВСЕ возможные варианты развития событий в приложении.
То,что вам сейчас кажется "ненужным и врядли когда-то необходимым" - завтра может стать ключевым моментом в вашем приложении.
И будет весьма уныло переписывать горы функционала ради какой-нибудь мелкой опции,невозможной при существующем коде.
Попробовал применить Ваш пример к моему проекту и вот что получилось. Пойдет ли так или что-то нужно изменить?

И еще пару вопросов.
1. Так ли необходимы наклонные кавычки в названиях таблиц и полей?
2. Как лучше назвать поле: id_article или наоборот article_id ? Заметил, что почти все пишут article_id, но у меня уже во всем приложении прописано как id_article. Или это без разницы?

PHP код:
CREATE TABLE articles_categories (
  
id_article int(8UNSIGNED NOT NULL,
  
id_category int(3UNSIGNED NOT NULL,
TYPE=MyISAM

PHP код:
$categories "1,5,165,2,4" // или...
$categories "5"// или...
$categories "";

$category explode(","$categories);

if(
$category[0] > 0)
    
$query_2 "INSERT INTO `articles_categories` (`article_id`, `category_id`) VALUES ('$id_article', '$category[0]')";
if(
$category[1] > 0)
    
$query_2 .= ", ('$id_article', '$category[1]')";
if(
$category[2] > 0)
    
$query_2 .= ", ('$id_article', '$category[2]')";
if(
$category[3] > 0)
    
$query_2 .= ", ('$id_article', '$category[3]')";
if(
$category[4] > 0)
    
$query_2 .= ", ('$id_article', '$category[4]')";
if(
$category[5] > 0)
    
$query_2 .= ", ('$id_article', '$category[5]')";

$query sprintf("INSERT INTO articles VALUES ('', '$name', %s, '$author', '$datetime', '$ip')"quote_smart($text));

mysql_query($query); // вставка статьи
mysql_query($query_2); // вставка категорий 

Последний раз редактировалось Nikolai_; 16.11.2010 в 08:14.
Nikolai_ вне форума Ответить с цитированием
Старый 16.11.2010, 10:07   #10
Andkorol
Старожил
 
Регистрация: 31.05.2010
Сообщений: 3,301
По умолчанию

Цитата:
1. Так ли необходимы наклонные кавычки в названиях таблиц и полей?
Для выделения названий полей и таблиц при помощи апострофов есть только одна серьёзная причина - иногда названия полей или таблиц являются т.н. "ключевыми (зарезервированными) словами".
Например,многие любят называть поле,содержащее значение даты `date` - что,вобщем-то, логично.Но date - ключевое слово в SQL(тип поля), потому встретив его в запросе - Mysql может выдать ошибку,и не выполнить запрос.
Если же экранировать такое ключевое слово апострофами - это укажет,что обращение идёт к полю,а не имеется ввиду тип поля.
Таким образом - экранирование апострофами не является обязательным - но может иногда избавить от длительного поиска причин "почему же коррекный запрос не проходит?".
Кроме того - выделение названий полей и таблиц повышает читабельность запросов.
Цитата:
2. Как лучше назвать поле: id_article или наоборот article_id ? Заметил, что почти все пишут article_id, но у меня уже во всем приложении прописано как id_article. Или это без разницы?
Это абсолютно без разницы,и связанно с разницей в построении фраз между русским и английским языками:
Русский - "идентификатор статьи" - "id_article"
Английский - "article identifier" - "article_id"
Главное при этом - придерживаться ОДНОЙ логики во всём приложении - либо русской,либо английской.
Потому что в процессе написания кода запросы чаще всего пишутся автоматически,по памяти - соответственно,гораздо легче их писать,когда точно знаеш,что все поля именованны в одном стиле,по одному принципу(`article_id`, `category_id`, `section_id`, `group_id`, `user_id`, etc...) - чем постоянно сверяться с "картой БД".

Всё это мелочи на первый взгляд - но применение этих "мелочей" делает код понятным,последовательным и читабельным,а сам процесс разработки и отладки - более упорядоченным.
Чтоб понять важность и необходимость таких мелочей - достаточно попробовать взять в доработку/поддержку чей-то чужой объёмный код,в котором всё будет отличаться от привычных вам стиля и логики(название переменных,стиль оформления кода и запросов,блоки кода и функции, прочее...) - получите бесценный опыт,поверьте.
Andkorol вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
переход статей timon777777 PHP 9 27.06.2010 23:16