Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Как удалить не используемые фото?
 
 автор: sega_z   (22.05.2011 в 16:10)   письмо автору
 
 

Есть база данных объявлений с фотографиями (около 40000 шт.). Сами фото хранятся в папке "http://www.xxx.ru/podaty_obyavlenie/foto/" на сервере, а имя фото хранится в базе данных.

Со временем объявления удаляются, удаляется и путь к фото.

Я только не давно сделал PHP код удаления всех фото принадлежащих объявлению, которое удаляется. Поэтому в папке "foto" осталось очень много фото принадлежащих объявлениям, которых уже нет.

В ручную удалять - очень сложно, т.к. их очень много!!!

Помогите составить код для очистки всех файлов (фото) имя которых отсутствует в базе данных.

Попробовал сам, но что то не получилось?

Имена всех фото, хранимые в базе имеют вид: foto/0.02461300 1300270505.jpg и отличаются только цифрами.
У каждого объявления может быть несколько фото, а может быть вообще ни одного.



<?php 
include("...");//Подключаемся к базе данных
$result1212 mysql_query ("SELECT foto_mini1,foto_mini2,
foto_mini3,foto_mini4,foto_mini5,foto_mini6,foto_big1,
foto_big2,foto_big3,foto_big4,foto_big5,foto_big6 FROM doska"
,
$db); // Удаляем все фото из папки foto удаляемого объявления
$myrow1212 mysql_fetch_array ($result1212);
do
{
if (!empty(
$myrow1212['foto_mini1']))
{
$foto_mini1="podaty_obyavlenie/".$myrow1212['foto_mini1']; 
if (
file_exists($foto_mini1)) {
    echo 
"Фото используется!<br><br>";
} else {
unlink($foto_mini1);
    echo 
"Фото не используется и было удалено!<br><br>";
}
}

if (!empty(
$myrow1212['foto_mini2']))
{
$foto_mini2="podaty_obyavlenie/".$myrow1212['foto_mini2']; 
if (
file_exists($foto_mini2)) {
    echo 
"Фото используется!<br><br>";
} else {
unlink($foto_mini2);
    echo 
"Фото не используется и было удалено!<br><br>";
}
}

//и т.д. все 12 столбцов таблицы

}
while (
$myrow1212 mysql_fetch_array ($result1212));
?>


Выдаёт: "Warning: unlink(podaty_obyavlenie/foto/0.02461300 1300270505.jpg) [function.unlink]: No such file or directory in Z:\home\localhost\www\doska_obyavl\3.php on line 12
Фото не существует и было удалено!"

  Ответить  
 
 автор: Valick   (22.05.2011 в 16:37)   письмо автору
 
   для: sega_z   (22.05.2011 в 16:10)
 

ну я бы наверно начал "из-за угла"...
занес бы в базу все имена фото из папки в отдельную таблицу
потом я думаю не составит труда составить запрос для формирования таблицы с "мусором",
и в последствии почистить папку с фотками опираясь на данные "мусорной" таблицы

  Ответить  
 
 автор: sega_z   (22.05.2011 в 16:52)   письмо автору
 
   для: Valick   (22.05.2011 в 16:37)
 

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

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

  Ответить  
 
 автор: cheops   (22.05.2011 в 17:04)   письмо автору
 
   для: sega_z   (22.05.2011 в 16:10)
 

Скрипт удаления относительно папки podaty_obyavlenie где лежит? Такое ощущение, что PHP не может обнаружить этот относительный путь, может имеет смысл задать абсолютный путь от буквы диска?

  Ответить  
 
 автор: cheops   (22.05.2011 в 17:08)   письмо автору
 
   для: sega_z   (22.05.2011 в 16:10)
 

>if (file_exists($foto_mini2)) {
> echo "Фото используется!<br><br>";
>} else {unlink($foto_mini2);
> echo "Фото не используется и было удалено!<br><br>";
>}
Еще вот эта логика не понятна, что значит если file_exists() возвращает true, то фото используется? Это лишь означает, что фото существует на жестком диске, а используется оно или нет можно выяснить обратившись к базе данных. У вас же получается, что unlink() применяется толкько к тем файлам, которых нет на жестком диске физически - разумеется выдается предупреждение и ничего не удаляется, так как файла нет.

  Ответить  
 
 автор: sega_z   (22.05.2011 в 17:13)   письмо автору
 
   для: cheops   (22.05.2011 в 17:08)
 

Скрипт удаления и папка podaty_obyavlenie лежат в корне сайта, путь http://www... я не использую, т.к. хочу сначала проверить работу на локальном сервере.

  Ответить  
 
 автор: cheops   (22.05.2011 в 17:17)   письмо автору
 
   для: sega_z   (22.05.2011 в 17:13)
 

А директория podaty_obyavleni тоже в корне сайта лежит?

PS Но вообще нужно разбираться с file_exists().

  Ответить  
 
 автор: sega_z   (22.05.2011 в 17:22)   письмо автору
 
   для: cheops   (22.05.2011 в 17:17)
 

Да, тоже в корне лежит.

Дак можно или нет с помощью функции file_exists() очистить папку от не используемых файлов???

  Ответить  
 
 автор: cheops   (22.05.2011 в 17:26)   письмо автору
 
   для: sega_z   (22.05.2011 в 17:22)
 

При помощи file_exists() вы можете проверить существует ли файл на жестком диске или нет. Больше ничего при помощи её сделать нельзя. Если файл существует, функция не ответит вам на вопрос нужен он вам или нет, есть он в базе данных или отсутствует - эту проверку вы должны реализовать сами. Если вы помещаете unlink() в блок else(), то однозначно никакие файлы удалены не будут, так как их просто физически нет, даже если в базе данных на них имеется ссылка.

  Ответить  
 
 автор: sega_z   (22.05.2011 в 17:33)   письмо автору
 
   для: cheops   (22.05.2011 в 17:26)
 

Ну как тогда, вы можете привести пример?

Если условие if (file_exists($foto_mini1)) выполняется, значит этот файл есть в базе и его удалять не нужно. Зачем тогда ещё проверять есть ли он в базе?

  Ответить  
 
 автор: sega_z   (22.05.2011 в 17:41)   письмо автору
 
   для: cheops   (22.05.2011 в 17:26)
 

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

Но как это сделать в коде???

  Ответить  
 
 автор: Valick   (22.05.2011 в 17:51)   письмо автору
 
   для: sega_z   (22.05.2011 в 17:41)
 

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

так как файлов в папке я так понимаю очень много, то начинаем с opendir
хотя может и лучше начать с glob
в принципе можете конечно и в цикле отправить запрос на существование записи в базе
операция разовая, может база и "потерпит" нагрузку

  Ответить  
 
 автор: sega_z   (22.05.2011 в 18:14)   письмо автору
 
   для: Valick   (22.05.2011 в 17:51)
 

Ладно, спасибо за помощь!
Сам как нибудь разберусь.

  Ответить  
 
 автор: Valick   (22.05.2011 в 18:17)   письмо автору
 
   для: sega_z   (22.05.2011 в 18:14)
 

ну в принципе незачто, я не могу Вас заставить писать код
хотя попытался помочь Вам в этом

  Ответить  
 
 автор: sega_z   (22.05.2011 в 18:18)   письмо автору
 
   для: Valick   (22.05.2011 в 18:17)
 

Вы можете просто написать как можно извлечь ТОЛЬКО имя файла из папки "podaty_obyavlenie/foto/".
А дальше я сам знаю как сделать.

  Ответить  
 
 автор: Valick   (22.05.2011 в 18:19)   письмо автору
 
   для: sega_z   (22.05.2011 в 18:18)
 

я же дал Вам ссылку на функцию glob
в результате Вы получите массив имен
там даже пример есть
<?php
foreach (glob("*.txt") as $filename) {
    echo 
"$filename size " filesize($filename) . "\n";
}
?> 

только укажите соответствующее расширение файла

  Ответить  
 
 автор: sega_z   (22.05.2011 в 18:23)   письмо автору
 
   для: Valick   (22.05.2011 в 18:19)
 

Но там три варианта ответа кода и что означает "as $filename"?

А мне нужно чтобы выводилось только имя (я не знаю как использовать дополнительные флаги!)
Когда всё знаешь - всегда кажется все пустяком!

  Ответить  
 
 автор: Valick   (22.05.2011 в 18:27)   письмо автору
 
   для: sega_z   (22.05.2011 в 18:23)
 

<?php 
foreach (glob("*.jpg") as $filename) { 
    echo 
$file basename($filename'.php'); 

?>

  Ответить  
 
 автор: sega_z   (22.05.2011 в 18:29)   письмо автору
 
   для: Valick   (22.05.2011 в 18:27)
 

И где в этой функции задаётся папка для извлечения???
Где задается переменная $filename???

И зачем мне размер файла, мне нужно только имя файла: 0.2598745554 5544.jpg
Файлы могут быть не только .jpg

  Ответить  
 
 автор: Valick   (22.05.2011 в 18:31)   письмо автору
 
   для: sega_z   (22.05.2011 в 18:29)
 

размер Вам не нужен, я просто скопипастил пример с мануала
чтобы понять что такое as $filename, нужно прочитать описание функции foreach
поверьте лучше чем описано в мануале я не смогу написать :)

  Ответить  
 
 автор: sega_z   (22.05.2011 в 18:32)   письмо автору
 
   для: Valick   (22.05.2011 в 18:31)
 

Файлы в моей папке могут быть не только .jpg, но и .gif и т.д.

  Ответить  
 
 автор: Valick   (22.05.2011 в 18:34)   письмо автору
 
   для: sega_z   (22.05.2011 в 18:32)
 

тогда glob("путь если есть/папка/*.*")

  Ответить  
 
 автор: sega_z   (22.05.2011 в 18:37)   письмо автору
 
   для: Valick   (22.05.2011 в 18:34)
 

glob("путь если есть/папка/*.*") - какой задать путь при использовании локального сервера?

У меня данный скрипт очистки и папка с фото "podaty_obyavlenie/foto/" лежат в корне.

  Ответить  
 
 автор: Valick   (22.05.2011 в 18:41)   письмо автору
 
   для: sega_z   (22.05.2011 в 18:37)
 

его и пишите, если скрипт тоже в корне
а можно и "http://site.ru/podaty_obyavlenie/foto/*.*"
хотя у меня щас нет Денвера под рукой, не могу проверить, да и пол года без практики, так что проверяйте

  Ответить  
 
 автор: sega_z   (22.05.2011 в 18:44)   письмо автору
 
   для: Valick   (22.05.2011 в 18:41)
 

Я сделал так:


<?php 
foreach (glob("podaty_obyavlenie/foto/*.*") as $filename) { 
    echo 
$file basename($filename'.php'); 

?> 


Он мне вывел все имена файлов, находящихся в папке foto - то что нужно!

Теперь как мне по одному имени файла извлекать из переменной $file?

  Ответить  
 
 автор: Valick   (22.05.2011 в 18:45)   письмо автору
 
   для: sega_z   (22.05.2011 в 18:44)
 

этого делат не нужно
сразу делаете запрос в цикле foreach и подставляете $file в тело запроса
___
ах да забыл, у Вас там с полями наворочано

  Ответить  
 
 автор: Valick   (22.05.2011 в 18:47)   письмо автору
 
   для: Valick   (22.05.2011 в 18:45)
 

для начала составте запрос SELECT для выбора имени файла

  Ответить  
 
 автор: sega_z   (22.05.2011 в 18:55)   письмо автору
 
   для: Valick   (22.05.2011 в 18:47)
 

Ничего не понял...

А разве нельзя эти результаты просто сравнивать условием if () с массивом $myrow1212['foto_mini1'] полученным так:


include("...");//Подключаемся к базе данных
$result1212 = mysql_query ("SELECT foto_mini1,foto_mini2,foto_mini3,foto_mini4,foto_mini5,
foto_mini6,foto_big1,foto_big2,foto_big3,foto_big4,
foto_big5,foto_big6 FROM doska",$db);
$myrow1212 = mysql_fetch_array ($result1212);

  Ответить  
 
 автор: Valick   (22.05.2011 в 18:59)   письмо автору
 
   для: sega_z   (22.05.2011 в 18:55)
 

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

  Ответить  
 
 автор: sega_z   (22.05.2011 в 19:01)   письмо автору
 
   для: Valick   (22.05.2011 в 18:59)
 

Я просто не представляю как все это "foreach (glob("podaty_obyavlenie/foto/*.*") as $filename)" подставить в запрос $result1212 = mysql_query ("SELECT foto_mini1,foto_mini2,foto_mini3,foto_mini4,foto_mini5,foto_mini6,foto_big1,foto_big2,foto_big3,foto_big4,foto_big5,foto_big6 FROM doska WHERE ........",$db);

  Ответить  
 
 автор: Valick   (22.05.2011 в 19:04)   письмо автору
 
   для: sega_z   (22.05.2011 в 19:01)
 

это не нужно подставлять... это цикл
подставлять нужно именно $file
условие запроса у Вас получиться с кучей OR
WHERE foto_mini1=$file OR foto_mini2=$file и т.д.

  Ответить  
 
 автор: sega_z   (22.05.2011 в 19:06)   письмо автору
 
   для: Valick   (22.05.2011 в 19:04)
 

Но переменная $file содержит сразу все имена файлов, или нет?

  Ответить  
 
 автор: Valick   (22.05.2011 в 19:08)   письмо автору
 
   для: sega_z   (22.05.2011 в 19:06)
 

или нет :)
http://www.softtime.ru/bookphp/gl4_2.php

  Ответить  
 
 автор: sega_z   (22.05.2011 в 19:12)   письмо автору
 
   для: Valick   (22.05.2011 в 19:08)
 

Хорошо вот так делаем:


<?php 
foreach (glob("podaty_obyavlenie/foto/*.*") as $filename

$file basename($filename'.php');
$result1212 mysql_query ("SELECT id FROM doska WHERE foto_mini1=$file OR foto_mini2=$file OR foto_mini3=$file OR foto_mini4=$file OR foto_mini5=$file OR foto_mini6=$file OR foto_big1=$file OR foto_big2=$file OR foto_big3=$file OR foto_big4=$file OR foto_big5=$file OR foto_big6=$file",$db); 
$myrow1212 mysql_fetch_array ($result1212);

if (empty(
$myrow1212['id']))
{
unlink();
}

?> 


А что именно удалять, что написать здесь: unlink();

  Ответить  
 
 автор: Valick   (22.05.2011 в 19:16)   письмо автору
 
   для: sega_z   (22.05.2011 в 19:12)
 

рано, нужно сначала вот с этим роазобраться
$file = basename($filename, '.php');
у Вас расширения совсем другие

  Ответить  
 
 автор: sega_z   (22.05.2011 в 19:20)   письмо автору
 
   для: Valick   (22.05.2011 в 19:16)
 

И как это сделать?

  Ответить  
 
 автор: sega_z   (22.05.2011 в 19:32)   письмо автору
 
   для: sega_z   (22.05.2011 в 19:20)
 

Я так и думал, что это "foto_big1=$file" не получится!!!

  Ответить  
 
 автор: sega_z   (22.05.2011 в 19:24)   письмо автору
 
   для: Valick   (22.05.2011 в 19:16)
 

Я проверил работу скрипта:


<?php 
foreach (glob("podaty_obyavlenie/foto/*.*") as $filename

$file basename($filename'.php');
$result1212 mysql_query ("SELECT id FROM doska WHERE
foto_mini1='
$file' OR foto_mini2='$file' OR 
foto_mini3='
$file' OR foto_mini4='$file' OR 
foto_mini5='
$file' OR foto_mini6='$file' OR 
foto_big1='
$file' OR foto_big2='$file' OR 
foto_big3='
$file' OR foto_big4='$file' OR 
foto_big5='
$file' OR foto_big6='$file'",$db);
$myrow1212 mysql_fetch_array ($result1212);

if (!empty(
$myrow1212['id']))
{
echo 
$myrow1212['id']."<br>";
}

?> 


И он выдал кучу строк:

Warning: mysql_query(): supplied argument is not a valid MySQL-Link resource in Z:\home\localhost\www\doska_obyavl\4.php on line 5

Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in Z:\home\localhost\www\doska_obyavl\4.php on line 6

  Ответить  
 
 автор: cheops   (22.05.2011 в 19:44)   письмо автору
 
   для: sega_z   (22.05.2011 в 19:24)
 

После выполнения mysql_query(), тем более, когда запрос динамический всегда осуществляйте проверку правильности выполнения запроса (это не тяжело, но очень полезно для отладки, экономии времени и для понимания того, что на самом деле происходит)
<?php
  
...
  
$query "...";
  
$res mysql_query($query);
  if(!
$res) exit("Ошибка - ".$query."<br>".mysql_query());
  ...
?>

  Ответить  
 
 автор: sega_z   (22.05.2011 в 19:59)   письмо автору
 
   для: cheops   (22.05.2011 в 19:44)
 

Может вы подскажете, в чем ошибка:


<?php 
foreach (glob("podaty_obyavlenie/foto/*.*") as $filename

$filename basename($filename'.php');
$file "foto/"$filename;
$result1212 mysql_query ("SELECT id FROM doska WHERE 
foto_mini1='
$file' OR foto_mini2='$file' OR 
foto_mini3='
$file' OR foto_mini4='$file' OR 
foto_mini5='
$file' OR foto_mini6='$file' OR 
foto_big1='
$file' OR foto_big2='$file' OR 
foto_big3='
$file' OR foto_big4='$file' OR 
foto_big5='
$file' OR foto_big6='$file'",$db);
$myrow1212 mysql_fetch_array ($result1212);
$res mysql_query($result1212);
  if(!
$res) exit("Ошибка - ".$result1212."<br>".mysql_query());
if (!empty(
$myrow1212['id']))
{
echo 
$myrow1212['id']."<br>";
}
}
?> 


выдаёт:

Warning: mysql_query(): supplied argument is not a valid MySQL-Link resource in Z:\home\localhost\www\doska_obyavl\4.php on line 6

Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in Z:\home\localhost\www\doska_obyavl\4.php on line 7

Warning: mysql_query() [function.mysql-query]: Access denied for user 'ODBC'@'localhost' (using password: NO) in Z:\home\localhost\www\doska_obyavl\4.php on line 8

Warning: mysql_query() [function.mysql-query]: A link to the server could not be established in Z:\home\localhost\www\doska_obyavl\4.php on line 8

Warning: Wrong parameter count for mysql_query() in Z:\home\localhost\www\doska_obyavl\4.php on line 9
Ошибка -

  Ответить  
 
 автор: cheops   (22.05.2011 в 20:04)   письмо автору
 
   для: sega_z   (22.05.2011 в 19:59)
 

Не нужно передавать дескриптор функции mysql_query(), она принимает только SQL-запросы. Вам нужно проверять не $res (это было приведено для примера), а $result1212, который выдает функция mysql_query().

  Ответить  
 
 автор: sega_z   (22.05.2011 в 20:09)   письмо автору
 
   для: cheops   (22.05.2011 в 20:04)
 

Я нашел ошибку - забыл подключить базу данных!!!

Скрипт вывел все id, но в самом конце выдал: Fatal error: Maximum execution time of 30 seconds exceeded in Z:\home\localhost\www\doska_obyavl\4.php on line 7

Что это значит?

  Ответить  
 
 автор: cheops   (22.05.2011 в 20:44)   письмо автору
 
   для: sega_z   (22.05.2011 в 20:09)
 

Не успевает в 30 секунд уложиться, попробуйте выставить бесконечное время выполнения скрипта
<?php
  set_time_limit
(0);
  ...
?>

  Ответить  
 
 автор: sega_z   (22.05.2011 в 20:55)   письмо автору
 
   для: cheops   (22.05.2011 в 20:44)
 

Все нормально, я изменил настройки максимального времени выполнения скрипта на 60 сек.
Все ненужные файлы были успешно удалены!

Всем участникам данного процесса огромное спасибо!!!

  Ответить  
 
 автор: sega_z   (22.05.2011 в 19:32)   письмо автору
 
   для: Valick   (22.05.2011 в 19:16)
 

Я так и думал, что это "foto_big1=$file" не получится!!!

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования