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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 18.11.2010, 15:19   #31
ssdm
Форумчанин
 
Регистрация: 20.05.2009
Сообщений: 506
По умолчанию

Цитата:
Этот вопрос решается заменой OR на AND и добавлением жесткой упорядочености категорий при добавлении статьи.
Пример в студию. Уж очень хочется посмотреть что вы опять придумаете.
Цитата:
По чему? Выбор статьи по её названию и вывод её из файла. Или Вы делаете как-то по другому?
Вы же написали что это запрос на выбор одной категории, то есть статей одной категории.
Код:
if (mysql_num_rows($sql) == 1) {
$row = mysql_fetch_assoc($sql);
Здесь if (mysql_num_rows($sql) == 1) можно убрать и просто оставить while($row = mysql_fetch_assoc($sql)) (зачем лищнии операции делать ?)
Цитата:
Посмотрите снова приведённую мной таблицу.
Прочитайте первый пост 3-ей страницы.
Код:
А откуда id категорий возьмём? Или это "уличная магия"...
select * from articles where id in (select aticle_id from cat_at where cat_id in ( select id from categories where name in (<name_1>,...,<name_n>) ) ) , где name_i - название категории
Цитата:
Сначала получаем id, потом саму статью - два запроса.
Не два запроса, а один запрос с подзапросом.

Судя по вашему последнему посту вы до этого вообще не знали как решается проблема many-to-many связей. Приведенный Androkol'ом пример - классический. У вашего же подхода очень много слабых мест. Почитайте что ли про проектирование БД.

Последний раз редактировалось ssdm; 18.11.2010 в 15:24.
ssdm вне форума Ответить с цитированием
Старый 18.11.2010, 15:30   #32
Nikolai_
Пользователь
 
Регистрация: 27.08.2010
Сообщений: 16
По умолчанию

Коллеги, оцените, пожалуйста, что я написал. Пойдет ли или можно было проще сделать?

Категории передается обработчику в виде переменных:
$category[1], $category[2], $category[3], $category[4], $category[5]

Вот так будут вставляться в таблицу категории при создании статьи:
PHP код:
    $category $_POST['category'];

   
// вставка текста, автора и названия в табл. articles
    
mysql_query($query);

    
// получение id записанной статьи
    
$id_article mysql_insert_id();


    if(isset(
$category)){ // если категории заданы
        
$category array_unique($category); // удаление повторов
        // удаление пустых элементов, если была оставлена опция "Не выбрана"
        
function empty_value($category){return ($category !== "");}
        
$category array_filter($category"empty_value");
    }

  
// вставку категорий в таблицу articles_categories
    
$count_category count($category); // кол-во элементов в массиве
    
if($count_category 0){ // если задана хоть 1 категория, то...
        // формирование запроса
        
$query_2 "INSERT INTO `articles_categories` VALUES ";
        foreach(
$category as $key => $value){
            
$query_2 .= "('$id_article', '$value')";
            if(
$key < ($count_category)){
                
$query_2 .= ', ';  // если это не последний элемент массива
            
}
        }
        
mysql_query($query_2); // вставка в табл. категорий
    

А вот так будут изменяться категории при редактировании статьи администратором:

PHP код:
$category $_POST['category'];

// обновление названия, текста и автора статьи
mysql_query("UPDATE articles SET name='$name', text='$text', author='$author' WHERE id_article='$id_article';");

// удаление старых категорий статьи
mysql_query("DELETE FROM articles_categories WHERE id_article='$id_article';");

// запись новых категорий - НИЖЕ ПОВТОР КОДА ИЗ ЛИСТИНГА ВЫШЕ
    
if(isset($category)){ // если категории заданы
        
$category array_unique($category); // удаление повторов
        // удаление пустых элементов, если была оставлена опция "Не выбрана"
        
function empty_value($category){return ($category !== "");}
        
$category array_filter($category"empty_value");
    }

  
// вставку категорий в таблицу articles_categories
    
$count_category count($category); // кол-во элементов в массиве
    
if($count_category 0){ // если задана хоть 1 категория, то...
        // формирование запроса
        
$query_2 "INSERT INTO `articles_categories` VALUES ";
        foreach(
$category as $key => $value){
            
$query_2 .= "('$id_article', '$value')";
            if(
$key < ($count_category)){
                
$query_2 .= ', ';  // если это не последний элемент массива
            
}
        }
        
mysql_query($query_2); // вставка в табл. категорий
    

Nikolai_ вне форума Ответить с цитированием
Старый 18.11.2010, 15:50   #33
ssdm
Форумчанин
 
Регистрация: 20.05.2009
Сообщений: 506
По умолчанию

Выглядет неплохо.
ЗЫ. Рекомендую при работе с БД пользоваться функцией для защиты от иньекций.
Нпример
Код:
function ToSql($value){
    $value = trim(ltrim($value));
    if( (trim($value)!='') && (trim($value)!='null') ){
            $SqlValue = "'".str_replace("'","''",$value)."'";}
    else{
            $SqlValue = "null";}
    return $SqlValue;
}
Пример использования :
mysql_query("DELETE FROM articles_categories WHERE id_article=".ToSql($id_article));
ssdm вне форума Ответить с цитированием
Старый 18.11.2010, 15:53   #34
Andkorol
Старожил
 
Регистрация: 31.05.2010
Сообщений: 3,301
По умолчанию

to Виталий Желтяков:
Цитата:
Надоели вы мене все...
Ну так а кто вас заставляет ввязываться...???
Я ведь про ЧСВ не зря вам заметил - вы вот сами может и не замечаете,но ВО ВСЕХ своих постах вы слово "я" пишете с большой буквы(см. цитату ниже).Для людей,понимающих психологию - это важный момент.

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

Цитата:
А давайте поговорим о цифрах?Мой код с ростом числа статей и количества категорий будет выдавать примерно одно и тоже время. Ваш же код с ростом количества категорий будет увеличиваться на время поиска этой категории.
А давайте!!!
Это с чего бы на ваш вариант не будет влиять изменения количества статей и категорий???
Увеличивается количество объектов, в которых производится поиск - соответственно,увеличивается время поиска - это логика.
К тому же,как я и говорил ранее - я сильно сомневаюсь,что при "более 100 категорий"(условия ТС) ваш поисковый запрос,содержащий более 100 элементов OR `category_<1 - 100>` = '$category' будет быстрее моего единственного условия WHERE `category_id` = '$category'.
Никогда не поверю - ибо бред.

Цитата:
Мой вариант даже на порядок легче редактировать через phpmyadmin, т.к. категории обозначаются не в виде цифр, значения которых надо смотреть в другой таблице, а в виде списка.
Когда вы уже поймёте,что в 100% случаев конечному пользователю вашего программного продукта абсолютно наплевать на то,что удобно лично вам,как разработчику.
Конечным пользователям, из которых 99% даже не знает,что такое phpMyAdmin, важно только одно - удобство использование вашего продукта лично для них.
Это подразумевает простой и интуитивно-понятный веб-интерфейс,позволяющий максимально гибко управлять продуктом.
При чём тут удобство редактирования в phpMyAdmin ????

Кстати - по поводу редактирования.
Что-то я не заметил вашего решения по редактированию самих категорий,их количества....
Это важный момент в вашем случае.
Вы тут мне пеняли на избыточность и громоздкость моего кода, вместо простого использования ENUM - ну так покажите,насколько это "простое использование"!!!
Типичные задачи - изменение названия категории,добавление новой категории,удаление ненужной категории,изменение допустимого количества категорий для одной статьи(напр. не 5,а 10).
Будьте любезны,примерчик - ну просто чтоб мы все по достоинству оценили "простоту и могущество" использования ENUM в данном случае.


Цитата:
Запрос на выбор одной категории:
Код:
$query = "SELECT * FROM `articles` WHERE `name`='{$id}' LIMIT 1";
Согласен с ssdm - нечто непонятное.
При чём тут категория - вы же просто выбираете 1 статью,при этом пытаясь её получить по `name`, используя для этого почему-то $id???

Цитата:
Тут самое противное, что Вы даже не хотите менять точку зрения, если вам указали ваши ошибки.
Что-то я "указаний на ошибки" в моём коде не заметил.
Мой подход отличен от вашего - но врядли ошибочен,ибо работает корректно.
Andkorol вне форума Ответить с цитированием
Старый 18.11.2010, 16:10   #35
Nikolai_
Пользователь
 
Регистрация: 27.08.2010
Сообщений: 16
По умолчанию

А нужно ли в таблице articles_categories кроме полей id_article и id_categories еще и 3-поле id(auto_increment) с первичным ключом? Или в данном случае оно излишне? Или для чего-нибудь может пригодиться?

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

Цитата:
Сообщение от Nikolai_ Посмотреть сообщение
Коллеги, оцените, пожалуйста, что я написал. Пойдет ли или можно было проще сделать?
Ну не то,чтобы проще, но из-за того,что я не люблю copy-paste при написании кода - я бы всю работу с категориями вынес бы либо в функцию,либо в отдельный подключаемый файл.
Потому как код абсолютно идентичен в двух местах,а редактировать(если вдруг что) удобнее-таки в одном месте.
Меньше повторов - чище и понятнее код.

PS : поле `id` AUTO_INCREMENT тут скорее всего не пригодится,потому что критичны либо сочетания article_id - category_id, либо только category_id - значит этих значений достаточно.
Не забудьте про индексы.

Последний раз редактировалось Andkorol; 18.11.2010 в 16:17.
Andkorol вне форума Ответить с цитированием
Старый 18.11.2010, 16:18   #37
Виталий Желтяков
Старожил
 
Аватар для Виталий Желтяков
 
Регистрация: 19.04.2010
Сообщений: 2,702
По умолчанию

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

if (mysql_num_rows($sql) == 1) {
$row = mysql_fetch_assoc($sql);
Здесь if (mysql_num_rows($sql) == 1) можно убрать и просто оставить while($row = mysql_fetch_assoc($sql)) (зачем лищнии операции делать ?)
Мы тут о двух разных вещах говорим. Я имел в виду получение статьи по её названию, т.е. вывод. Этот пример Я привел в качестве общего случая.
И то что, Вы хотите получить легко организовать:
Код:
$query = "SELECT `name` FROM `articles` 
WHERE (`category1` IN ('{$id1}','{$id2}','{$id3}')) 
OR (`category2` IN ('{$id1}','{$id2}','{$id3}')) 
OR (`category3` IN ('{$id1}','{$id2}','{$id3}')) 
OR (`category4` IN ('{$id1}','{$id2}','{$id3}')) 
OR (`category5` IN ('{$id1}','{$id2}','{$id3}'))";
$sql = mysql_query($query);
mysql_num_rows($sql);
if (mysql_num_rows($sql) > 0) {
$row = mysql_fetch_assoc($sql);
do {
// Вывод названия статьи
echo $row['name'];
// Вывод категорий
$cat = '';
for ($i=1; $i<=5; ++$i) {
if ($row['category'+i] != '') {
$cat .= $row['category'+i] + ' ';
}
}
echo $cat;
}
}
while ($row = mysql_fetch_assoc($sql));
}
Цитата:
Прочитайте первый пост 3-ей страницы.
Не понял на что Вы ссылаетесь.
Цитата:
select * from articles where id in (select aticle_id from cat_at where cat_id in ( select id from categories where name in (<name_1>,...,<name_n>) ) ) , где name_i - название категории
Цитата:Сначала получаем id, потом саму статью - два запроса.

Не два запроса, а один запрос с подзапросом.
И эту конструкцию Вы называете простой? Проще моего кода? Смешно...
Цитата:
Судя по вашему последнему посту вы до этого вообще не знали как решается проблема many-to-many связей. Приведенный Androkol'ом пример - классический. У вашего же подхода очень много слабых мест. Почитайте что ли про проектирование БД.
Я про это уже писал. Моё решение далеко от теории БД и построено на хитростях работы MySQL, но оно значительно эффективней вашего.
Цитата:
Я ведь про ЧСВ не зря вам заметил - вы вот сами может и не замечаете,но ВО ВСЕХ своих постах вы слово "я" пишете с большой буквы(см. цитату ниже).Для людей,понимающих психологию - это важный момент.
Я пишу местоимение "Я" наравне с "Вы", "Ты" и "Они". Я выделяю людей среди текста.
Цитата:
Так непонятно - мой код "плохой" или же он "логичен и достаточно прост для понимания"???
Цитата:
Это с чего бы на ваш вариант не будет влиять изменения количества статей и категорий???
Увеличивается количество объектов, в которых производится поиск - соответственно,увеличивается время поиска - это логика.
К тому же,как я и говорил ранее - я сильно сомневаюсь,что при "более 100 категорий"(условия ТС) ваш поисковый запрос,содержащий более 100 элементов OR `category_<1 - 100>` = '$category' будет быстрее моего единственного условия WHERE `category_id` = '$category'.
Никогда не поверю - ибо бред.
Тут вся фишка, что у Вас ДВЕ таблицы (!). Была бы одна Я бы не спорил. Для того, что бы получить название статьи из одной таблицы, Вам надо получить id из другой таблицы. Что ж Вы все это никак не признаете...
Вот поэтому мой вариант будет быстрее при наращивании числа категорий. Можете протестировать на xdebug.
Цитата:
Это подразумевает простой и интуитивно-понятный веб-интерфейс,позволяющий максимально гибко управлять продуктом.
Вы скорее не поверите, но для моего и вашего подхода можно написать одинаковый интерфейс.
Вопрос не в этом...
Каждый раз как Вы будете изменять категории, у Вас будут также задействованы ДВЕ таблицы, а у меня ОДНА.
У меня с модификацией таблицы просто:
Собираем все категории в переменную через запятую ($condition) и
Код:
ALTER TABLE 'articles' MODIFY `category01` ENUM('.$condition.');
Цитата:
При чём тут категория - вы же просто выбираете 1 статью,при этом пытаясь её получить по `name`, используя для этого почему-то $id???
Я привел общий пример взятый из моего проекта. $id - поступившая переменная.
Виталий Желтяков вне форума Ответить с цитированием
Старый 18.11.2010, 16:39   #38
ssdm
Форумчанин
 
Регистрация: 20.05.2009
Сообщений: 506
По умолчанию

Цитата:
В цикле перебираете все поступившие данные select-ов и не пустые по порядку приписываете к запросу.
Виталий, Вы не можете привести код вашего запроса? Для конктретного случая(что за случай описал уже выше).
Цитата:
И то что, Вы хотите получить легко организовать:
Код:


$query = "SELECT `name` FROM `articles`
WHERE (`category1` IN ('{$id1}','{$id2}','{$id3}'))
OR (`category2` IN ('{$id1}','{$id2}','{$id3}'))
OR (`category3` IN ('{$id1}','{$id2}','{$id3}'))
OR (`category4` IN ('{$id1}','{$id2}','{$id3}'))
OR (`category5` IN ('{$id1}','{$id2}','{$id3}'))";
$sql = mysql_query($query);
mysql_num_rows($sql);
if (mysql_num_rows($sql) > 0) {
$row = mysql_fetch_assoc($sql);
do {
// Вывод названия статьи
echo $row['name'];
// Вывод категорий
$cat = '';
for ($i=1; $i<=5; ++$i) {
if ($row['category'+i] != '') {
$cat .= $row['category'+i] + ' ';
}
}
echo $cat;
}
}
while ($row = mysql_fetch_assoc($sql));
}
Это то что я просил получить ? Я не это просил, либо вы очень сильно ошибаетесь.

Код:
Не понял на что Вы ссылаетесь.
http://www.mysql.ru/docs/man/Static_format.html
http://www.adminworld.ru/tag/mysql
пункт 15
ssdm вне форума Ответить с цитированием
Старый 18.11.2010, 16:45   #39
Andkorol
Старожил
 
Регистрация: 31.05.2010
Сообщений: 3,301
По умолчанию

Цитата:
Сообщение от Виталий Желтяков Посмотреть сообщение
У меня с модификацией таблицы просто:
Собираем все категории в переменную через запятую ($condition) и
Код:
ALTER TABLE 'articles' MODIFY `category01` ENUM('.$condition.');
Да уж,проще некуда.

Ну-ка попробуем ваш "простой" вариант модификации в деле:

Выполните последовательно эти шаги:
1.Создаём тестовую таблицу:
Цитата:
CREATE TABLE `test_enum` (
`id` INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`category_1` ENUM( 'one', 'two', 'three', 'four' ) NULL
) ENGINE = MYISAM ;
2.Добавляем пару тестовых значений:
Цитата:
INSERT INTO `test_enum` (`category_1`) VALUES ('one'), ('two');
3.Применяем ваше "простое" модифицирование:
Задача - изменить названия и кол-во категорий.
Цитата:
ALTER TABLE `test_enum` MODIFY `category_1` ENUM('five','six','seven');
Пожалуйста - сообщите нам полученный результат.
Andkorol вне форума Ответить с цитированием
Старый 18.11.2010, 16:55   #40
Виталий Желтяков
Старожил
 
Аватар для Виталий Желтяков
 
Регистрация: 19.04.2010
Сообщений: 2,702
По умолчанию

Цитата:
Виталий, Вы не можете привести код вашего запроса? Для конктретного случая(что за случай описал уже выше).
Упорядоченность при добавлении:
Код:
$str = ''
parse_str($id, $data);
if (!is_array ($data)) {
// если что-то прошло не так, инициализировать пустой массив
$data = array();
}
$count_category = 5; // Количество категорий
j=1;
for ($i=1; $i<=$count_category; ++$i) {
// обрабатывае пришедшие данные функцией mysql_real_escape_string перед вставкой в таблицу БД
if (isset($data['category'+i])) {
str .= 'category'.j.' = '.mysql_real_escape_string($data['category'+i]);
++j;
}
Запрос на выборку:
Код:
$query = "SELECT `name` FROM `articles` 
WHERE (`category1` IN ('{$id1}','{$id2}','{$id3}', '')) 
AND (`category2` IN ('{$id1}','{$id2}','{$id3}', '')) 
AND (`category3` IN ('{$id1}','{$id2}','{$id3}', '')) 
AND (`category4` IN ('{$id1}','{$id2}','{$id3}', '')) 
AND (`category5` IN ('{$id1}','{$id2}','{$id3}', ''))";
$sql = mysql_query($query);
mysql_num_rows($sql);
if (mysql_num_rows($sql) > 0) {
$row = mysql_fetch_assoc($sql);
do {
// Вывод названия статьи
echo $row['name'];
// Вывод категорий
$cat = '';
for ($i=1; $i<=5; ++$i) {
if ($row['category'+i] != '') {
$cat .= $row['category'+i] + ' ';
}
}
echo $cat;
}
}
while ($row = mysql_fetch_assoc($sql));
}
Цитата:
Это то что я просил получить ? Я не это просил, либо вы очень сильно ошибаетесь.
Я телепатией не обладаю - уточните, что Вам не понятно.

Ещё раз обратите внимание на приведённую мной таблицу - она статична, т.к. использует поля int, enum и var.
Виталий Желтяков вне форума Ответить с цитированием
Ответ


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



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