Как сделать, чтобы неподходящие под условие не забивали лимит?
Есть такой код:
$database->setQuery(" SELECT блаблабла LEFT блаблабла WHERE блаблабла ORDER блаблабла limit 0,2"); блаблабла while($row = mysql_fetch_assoc($request)) { if (file_exists('/www/ПУТЬ/'.$row['id'].'_100.jpg')) echo 'BODY'; } |
$database->setQuery(" SELECT блаблабла LEFT блаблабла WHERE блаблабла ORDER блаблабла limit 0,2"); блаблабла while($row = mysql_fetch_assoc($request)) { if (file_exists('/www/ПУТЬ/'.$row['id'].'_100.jpg')) echo 'BODY'; }
То есть, при наличии картинки '.$row['id'].'_100.jpg должны быть две итерации (limit 0,2) с BODY.
Так оно и происходит, если картинки есть у первых двух итераций.
Но проблема в том, что если первая итерация не находит соответствующей картинки, а, например, вторая находит, то показывается только одно BODY. Если наоборот - то же самое. А если у первых двух итераций нет вообще картинок - то вообще ничего не показывается.
Как сделать так, чтобы итерации, в которых нет картинок, просто пропускались? И всегда вывод был с двумя BODY (у которых есть картинки).
Заранее благодарен ответам профи!
Дополнительно:
Ответы:
Вариант А.
Вы не можете гарантировать, что любой файл изображений, сведения о которых храните в базе, будет доступен физически в любой момент.
Придется неопределенное число раз постучаться в базу и протестировать каждую запись о файле, существует ли он физически. При тесте формируем список мертвых и живых файлов. После того, как протестировали нужное кол-во живых файлов, можно делать итоговый запрос с оглядкой на список мертвых файлов.
$need_count = 10; // сколько требуется файлов для выборки $alive_count = 0; // сколько живых файлов $is_need_repeat = true; // требуется повторить попытку получить живые файлы $death_list = []; // сюда накапливаем список id мертвых файлов $alive_list = []; // сюда накапливаем список id живых файлов while($is_need_repeat) // Если можно делать итерационную попытку и пока не набрали нужное количество живых файлов { // Этот запрос, чтобы прощупать целостность файлов, достаточно получить только те атрибуты, которые позволяют проверить его путь и запомнить id. $database->setQuery(" SELECT id from блаблабла WHERE блаблабла ".(count($depth_list) > 0 ? : ' and id not in ('.join(',',$death_list).') ' : '')." -- отсеиваем мертвые файлы из запроса, они нам не нужны ".(count($alive_list) > 0 ? : ' and id not in ('.join(',',$alive_list).') ' : '')." -- отсеиваем живые файлы из запроса, мы их уже проверяли ORDER блаблабла limit 0,".($need_count - $alive_count)); // делаем лимит по оптимистичному сценарию, как будто можем получить список файлов, и все они будут живые, но только то кол-во, которое недостает while($row = mysql_fetch_assoc($request)) { if(file_exists('/www/ПУТЬ/'.$row['id'].'_100.jpg')) { $alive_list[] = $row['id']; // файл живой, заносим его id в список } else { $death_list[] = $row['id']; // файл мертвый, заносим его id в список } $curr_alive_count = count($alive_list); $is_need_repeat = $curr_alive_count > 0 && $curr_alive_count > $alive_count && $curr_alive_count < $need_count; // необходимо продолжить попытки, если на текущей итерации получили хоть один живой файл, живых файлов на этой итерации оказалось больше, чем на предыдущей, и их кол-во не достаточно до необходимого $alive_count = $curr_alive_count; // вписываем кол-во живых файлов на текущей итерации для проверки в будущем цикле (чтобы сравнить результаты двух циклов) } } // теперь можно сделать нормальный запрос, исключив мертвые файлы: $database->setQuery(" SELECT * from блаблабла WHERE блаблабла ".(count($depth_list) > 0 ? : ' and id not in ('.join(',',$death_list).') ' : '')." -- отсеиваем мертвые файлы из запроса ORDER блаблабла limit 0,".$need_count); |
$need_count = 10; // сколько требуется файлов для выборки $alive_count = 0; // сколько живых файлов $is_need_repeat = true; // требуется повторить попытку получить живые файлы $death_list = []; // сюда накапливаем список id мертвых файлов $alive_list = []; // сюда накапливаем список id живых файлов while($is_need_repeat) // Если можно делать итерационную попытку и пока не набрали нужное количество живых файлов { // Этот запрос, чтобы прощупать целостность файлов, достаточно получить только те атрибуты, которые позволяют проверить его путь и запомнить id. $database->setQuery(" SELECT id from блаблабла WHERE блаблабла ".(count($depth_list) > 0 ? : ' and id not in ('.join(',',$death_list).') ' : '')." -- отсеиваем мертвые файлы из запроса, они нам не нужны ".(count($alive_list) > 0 ? : ' and id not in ('.join(',',$alive_list).') ' : '')." -- отсеиваем живые файлы из запроса, мы их уже проверяли ORDER блаблабла limit 0,".($need_count - $alive_count)); // делаем лимит по оптимистичному сценарию, как будто можем получить список файлов, и все они будут живые, но только то кол-во, которое недостает while($row = mysql_fetch_assoc($request)) { if(file_exists('/www/ПУТЬ/'.$row['id'].'_100.jpg')) { $alive_list[] = $row['id']; // файл живой, заносим его id в список } else { $death_list[] = $row['id']; // файл мертвый, заносим его id в список } $curr_alive_count = count($alive_list); $is_need_repeat = $curr_alive_count > 0 && $curr_alive_count > $alive_count && $curr_alive_count < $need_count; // необходимо продолжить попытки, если на текущей итерации получили хоть один живой файл, живых файлов на этой итерации оказалось больше, чем на предыдущей, и их кол-во не достаточно до необходимого $alive_count = $curr_alive_count; // вписываем кол-во живых файлов на текущей итерации для проверки в будущем цикле (чтобы сравнить результаты двух циклов) } } // теперь можно сделать нормальный запрос, исключив мертвые файлы: $database->setQuery(" SELECT * from блаблабла WHERE блаблабла ".(count($depth_list) > 0 ? : ' and id not in ('.join(',',$death_list).') ' : '')." -- отсеиваем мертвые файлы из запроса ORDER блаблабла limit 0,".$need_count);
Вариант Б.
Вы можете гарантировать, что контролируете целостность файлов.
Тогда в таблице изображений делаете колонку is_del. Когда удаляете файл, вы должны пометить запись о файле в базе как удаленную по этому атрибуту.
Если вы все таки частично контролируете целостность, то в определенный период времени (например, запускать скрипт по cron раз в час, сутки) вам нужно пройтись по всему списку файлов в базе и проверить целостность каждого файла, и внести актуальную метку is_del.
Тогда получать живые файлы будет чуть-чуть проще:
$database->setQuery(" SELECT * from блаблабла WHERE блаблабла and is_del is null -- или нулю, в зависимости, что будет по умолчанию ORDER блаблабла limit 0,".$need_count); |
$database->setQuery(" SELECT * from блаблабла WHERE блаблабла and is_del is null -- или нулю, в зависимости, что будет по умолчанию ORDER блаблабла limit 0,".$need_count);
- Благодарю за такой подробный ответ!
Но в представленном мною коде никаких сведений о файлах изображений в базе данных не хранится. В работающем коде тоже. Проверка на существование изображения осуществляется уже в цикле с помощью file_exists. В базу данных вносить сведения о картинках не будем.
$row['id'] - это идентификатор документа.
Но хочется, чтобы всегда показывались результаты, а именно BODY отображалось два раза.
- Если вам всегда нужно выводить два неких маркера (предположу чтобы хотя бы была выборка), то зачем зондировать файлы?
$is_have_rows = false; while($row = mysql_fetch_assoc($request)) { //if (file_exists('/www/ПУТЬ/'.$row['id'].'_100.jpg')) echo 'BODY'; $is_have_rows = true; } if($is_have_rows) echo 'BODYBODY';
$is_have_rows = false; while($row = mysql_fetch_assoc($request)) { //if (file_exists('/www/ПУТЬ/'.$row['id'].'_100.jpg')) echo 'BODY'; $is_have_rows = true; } if($is_have_rows) echo 'BODYBODY';
- alexalexes, непонятно что Вы написали. Выводить BODY надо лишь тогда, когда картинки в указанном месте присутствуют.
- Ну, блин, ответ лежит в той же плоскости.
$have_image = false; while($row = mysql_fetch_assoc($request)) { if (file_exists('/www/ПУТЬ/'.$row['id'].'_100.jpg')) $have_image = true; } if($have_image) echo 'BODYBODY';
$have_image = false; while($row = mysql_fetch_assoc($request)) { if (file_exists('/www/ПУТЬ/'.$row['id'].'_100.jpg')) $have_image = true; } if($have_image) echo 'BODYBODY';
$string = ''; while($row = mysql_fetch_assoc($request)) { if (file_exists('/www/ПУТЬ/'.$row['id'].'_100.jpg')) { $string .= 'BODY'; } else { $string = ''; break; } } echo $string; |
$string = ''; while($row = mysql_fetch_assoc($request)) { if (file_exists('/www/ПУТЬ/'.$row['id'].'_100.jpg')) { $string .= 'BODY'; } else { $string = ''; break; } } echo $string;
А вообще если у вас не контролируется наличие изображений, значит где-то что-то пошло не так...
- Нет, наличие break при условии, что первая итерация без картинки, прерывает всё и вообще пусто.
Вы меня навели на мысль сделать так:
if (file_exists('/www/ПУТЬ/'.$row['id'].'_100.jpg') == false) continue; else echo 'BODY';
if (file_exists('/www/ПУТЬ/'.$row['id'].'_100.jpg') == false) continue; else echo 'BODY';
Но всё равно ничего получается...
- Korneliy,
Как сделать так, чтобы итерации, в которых нет картинок, просто пропускались? И всегда вывод был с двумя BODY (у которых есть картинки).
Короче я понял что основная ваша проблема в неумении построить нормально задачу. По вашему условию мое решение подходит, если есть картинки(2) то выводится 2 раза боди, в противном случае просто ничего не выводится.
наличие break при условии, что первая итерация без картинки, прерывает всё и вообще пусто.
Так у вас описано - если картинок нет (а логично что первой уже нет, значит будет только одна, что условиям не удовлетворяет), зачем проверять вторую? Просто выходим и выводим пустую строку.
- ThunderCat, если я применяю Ваш код, то совсем ничего не выводится, break останавливает вывод и вообще пусто. А нужно, чтобы итерации, в которых нет картинок, просто пропускались и в результате выводили всегда две итерации с картинками.
- Korneliy, Для информации: В вашем коде выбирается 2(!) элемента всего, цикл состоит из 2 проходов. Естественно что если в этих двух элементах нет картинок ничего не выведется.
- ThunderCat, разве php такой бедный язык, что не может пропустить элементы без картинок и вывести только те, что с картинками?
- Korneliy,
разве php такой бедный язык, что не может пропустить элементы без картинок и вывести только те, что с картинками?
Бедность или богатость языка тут вообще не при чем. Ваш код ПРЕДПОЛАГАЕТ ВЫБОР ИЗ 2 ЭЛЕМЕНТОВ (limit 0,2), так что у вас в коде по сути проверяется 2 элемента ВСЕГДА. Если ничего не выводится, значит хотя бы один из них не имеет картинок.
- ThunderCat, в моём идеальном мире программа работала бы так (для примера)
1. Смотрит первую итерацию. Ищет, есть ли картинка с тем же ID в имени. Не находит. Ничего не выводит, идёт дальше.
2. Смотрит вторую итерацию, сопоставляет. Находит картинку, выводит.
3. Смотрит третью. Картинки нет, ничего не выводит.
4. В четвертой картинка есть - выводит, говорит "Ага! Лимит вывода исчерпан!" и останавливается.
Итак, два вывода сделано. Почему глупый PHP на такое не способен - для меня загадка. :(
=============
Вот думаю, в limit может больше записать (например, 10), а ограничение на вывод двух при условии, что они с картинками, сделать в цикле.
- Korneliy,
3. Смотрит третью. Картинки нет, ничего не выводит.
Нету третьей, в вашей выборке 2(!!!) элемента или меньше. Всегда. И это к пхп напрямую не относится, вы сами задали такие условия выборки из бд.
Почему глупый PHP на такое не способен - для меня загадка.
Подозреваю что глупый здесь кто-то другой, ибо нечего на зеркало пхп пенять, если не знаете как что работает ))
- Korneliy, Кроме того,
2. Смотрит вторую итерацию, сопоставляет. Находит картинку, выводит.
и если дальше ни разу картинок не будет, то у вас выведется 1 раз "боди", что вроде как не соответствует условию.
- ThunderCat, да, до меня уже дошло, что из базы надо лимит делать больше, а вот ограничивать уже в цикле.
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
Для того чтобы предотвратить злоупотребление и избежать неподходящих ответов, можно использовать несколько методов. Вот несколько рекомендаций:
1. **Подробное описание задачи**: В своем вопросе необходимо дать максимально подробное описание проблемы или задачи, с которой вы столкнулись. Чем точнее и яснее будет сформулирован вопрос, тем больше вероятность получить качественный и подходящий ответ.
2. **Ограничение области применения**: Укажите в своем вопросе конкретные ограничения или условия, которые должны быть выполнены в ответе. Например, если вам нужно решение на PHP, укажите это в вопросе.
3. **Использование тегов**: При формулировке вопроса используйте соответствующие теги, чтобы указать язык программирования или технологию, с которой связан ваш вопрос. Это поможет привлечь внимание специалистов по данной теме.
4. **Активное участие**: Если у вас возникают дополнительные вопросы или требуется уточнение, активно участвуйте в обсуждении в комментариях под ответами. Это поможет уточнить детали и получить более качественный ответ.
5. **Оценка ответов**: После получения ответов, не забудьте оценить их, выбрав лучший или наиболее полезный ответ. Это поможет другим пользователям выбрать правильное решение и повысит качество ответов на сайте.
Соблюдение этих рекомендаций поможет вам получить качественные и подходящие ответы на ваш вопрос, избежать неподходящих ответов и сделать общение на сайте более продуктивным.