Откуда берутся папки

ЕСТЬ РЕШЕНИЕ ЗАКРЫТО
#1 4 февраля 2018 в 17:19
Сразу скажу, что я не собираюсь ругать папку upload и сетовать, как там всё плохо.
Вместо этого предлагаю посмотреть на метод getUploadDestinationDirectory(). Именно он генерирует многочисленные
папки.
Простой пример далее демонстрирует работу отдельных функций, использованных в методе.
  1. <?php
  2. // работа intval()
  3. for ($i=95; $i < 106; $i++) {
  4. echo sprintf('%03d', $i).' '.intval($i/100).'<br>';
  5. }
  6. echo '---<br>';
  7. // работа uniqid() и microtime()
  8. for ($i=0; $i <5 ; $i++) {
  9. echo sprintf('%03d', $i).' '.uniqid().' '.microtime(true).'<br>';
  10. sleep(1);
  11. }
Посмотрим в метод, в переменных $first_dir и $second_dir получаются строчки из 2-х случайных шестнадцатеричных символов.

Таким образом, $dest_dir содержит путь к результирующей папке и состоит из сегментов:
1.upload
2.к какой сотне принадлежит id пользователя, начиная с нулевой
3.к символу u конкатенируется id пользователя
4.$first_dir — это сгенерированная случайная величина
5.$second_dir — это сгенерированная случайная величина

Дальше в методе — создание при необходимости и назачение прав папкам из пути $dest_dir.

Что это даёт?
Не нужно париться и проверять не перегружена ли какая-то фиксированная папка файлами. Таких папок не будет.
Файлы будут размазаны ровным слоем по многочисленным папкам, их может быть, если не ошибся, около 65000 на одного пользователя.
Есть структура, позволяющая сгруппировать файлы по пользователям.

Некоторые авторы писали здесь на форуме, что нужно

избавиться от случайного выбора имени папки

. Ничто не мешает вам это сделать переписав лишь одну функцию под свои нужды. Но каждое решение имеет "побочные эффекты" и это серьёзное испытание для таких "побегов из курятника".
#2 6 февраля 2018 в 01:44

их может быть, если не ошибся, около 65000 на одного пользователя

@IamB
Вы не ошиблись. Если считать точно, то конечных папок может быть 256*256=65536. Плюс сюда ещё 256 папок первого уровня (из $first_dir). Итого: при операциях сканирования или бекапа нужно проходить максимум 65792 папок у каждого пользователя.

Тут сразу есть два неприятных момента:
1. "Файлы будут размазаны ровным слоем" хоть и звучит красиво, но на самом деле такой подход выливается в то, что пока пользователь создаёт первые 65 тысяч файлов, по теории вероятности практически каждый его файл будет лежать в своей отдельной папке, единственный в ней. Что и подтверждается практикой.
2. Эта цифра именно для каждого пользователя. Для 100 активных пользователей умножайте эту цифру на 100. А это уже значительная нагрузка на сервер каждую ночь во время служебных операций. А если пользователей тысяча? На больших реальных проектах получаются десятки тысяч файлов, каждый из которых лежит в отдельной папке — то есть, десятки тысяч папок с одним единственным файлом. Жесть… Или, как минимум, очень странно...

Ничто не мешает вам это сделать переписав лишь одну функцию под свои нужды

@IamB
Абсолютно логично. Также ничто не мешает переписать под себя любую другую функцию или вообще любую часть движка. Но ведь мы же не к этому стремимся, чтобы сделать систему, ядро которой нужно переписывать под себя. Мы же хотим максимально универсальную систему, верно? Пара новых строчек кода — небольшая цена за возможность любому пользователю получить свой функционал без патчей системных файлов. Тем более, когда дефолтный вариант создаёт проблемы или хотя бы просто необоснованно увеличивает нагрузку на сервер.

Да и дело не в том, чтобы я что-то "переписал под себя". Это не проблема, я себе много так подправил и добавил. Начиная от вывода виджетов в любом месте шаблона или под/над контентом, заканчивая логинами и красивыми адресами у пользователей.

Вопрос в том, что во-первых, далеко не все вебмастера, пользующиеся InstantCMS могут это сделать.
Во-вторых, потом эту патченную систему нужно корректно обновлять несколько раз в год, учитывая все свои правки. Многие ли пользователи этой замечательной CMS так смогут и вообще на это согласятся?
В-третьих, достаточно сделать одну или несколько правок в коде, чтобы дать возможность людям без всяких патчей использовать свою систему имён папок вместо дефолтной, например, через хук или через вызов пользовательского варианта функции при её наличии. И лично мне пока не понятны причины столь категорического отказа от этого, тем более когда на форуме уже не первый раз поднимается этот проблемный момент. Такой хук или проверка наличия пользовательской функции не будут нагружать систему, так как функция вызывается редко, только при создании новых файлов.

Так что, @IamB, Вы правильно описали работу функции. Но хочется понять, с какой целью Вы написали этот пост?
#3 6 февраля 2018 в 12:23
Оу! Благодарю за развёрнутый ответ!
1. Я сам разобрался с функцией, поделился своими идеями с другими. Это плохо?
2. Есть логика разработчика icms и есть ваша. И это разные вещи. Я попытался понять логику разработчика и увидел, что он нашел универсальное решение и в списке его приоритетов нет пункта его менять.
3. Хотел бы увидеть эти пару строчек кода в вашем исполнении. А уж там и до pull request рукой подать.
#4 6 февраля 2018 в 15:39
1. Это хорошо. 😊

2. У каждого есть своя логика и каждый имеет на неё право.
Текущий вариант отлично подходит для очень больших проектов на Двойке, в которых пользователи оооочень плодовиты, каждый из них создаёт в сутки сотни или тысячи файлов. Тогда такая "размазанность по папкам" становится оправданной. Через годик-другой заполнение папок начинается по второму кругу
Но подобных проектов очень мало. На подавляющем большинстве сайтов если пользователь создаёт одну публикацию в день — это уже радость. При такой обычной активности в ближайшие 20-30 лет пользователь не сможет добраться до цифры 65 тысяч файлов даже при четырёх сохраняемых пресетах для каждой картинки. Всё это время практически каждая картинка будет лежать в своей отдельной папке. Спрашивается, зачем так усложнять структуру и забивать файловую систему?
Да и по здравой логике, именно единицы владельцев высокопосещаемых и прибыльных проектов могут заплатить программистам за нестандартную систему сохранения файлов, а не 99% начинающих и средних, которым эта "размазанность" не нужна.

Также текущий вариант подходит при автоматическом наполнении сайта десятками тысяч материалов с картинками, которое обычно делается под одним пользователем. Но 1) таких проектов меньше; 2) даже на этих сайтах такой активный пользователь всего один — админ, а для остальных юзеров всё равно сохраняется проблема: сколько картинок — столько и новых папок.

Логика авторов движка вполне понятна: избавиться от лишних забот и строк кода при сохранении файлов. Но ведь упрощение кода — это не единственное, что нужно учитывать при написании CMS, которой пользуется много разных людей для очень разных целей. Поэтому вторая часть логики авторов: "категорический отказ от большей универсальности" становится не понятна.

3. Вызов хука ничем не отличается от других мест, например:
  1. // Вызов хука
  2. $dest_dir = cmsEventsManager::hook('get_upload_directory');
  3. // Проверка, вернулась ли папка
  4. if ($dest_dir) {
  5. $dest_dir = $this->site_cfg->upload_path . "{$dir_num_user}/u{$this->user_id}/{$first_dir}/{$second_dir}/";
  6. }
Добавилась 1 строка вызова хука и 1 условие.

Можно сделать проверку наличия пользовательской функции, возвращающей путь к папке, и её вызов. Это тоже займёт 1 строку + 1 строку проверки возвращаемого ей результата.

Можно вообще сделать механизм загрузки альтернативного пользовательского файла с кодом для любого класса ядра, если такой файл есть в системе. Или, что ещё интереснее, переименовать классы ядра в cms_имя_класса_default и сделать пустые классы cms_имя_класса, наследующие дефолтные классы. Все правки при обновлении движка разработчики Двойки будут вносить в дефолтные классы. А владельцы сайтов получат возможность заменять методы классов ядра на свои или добавлять новые без правки самого ядра. При обновлении системы ничего патчить повторно не придётся. Достаточно будет проверить несколько своих функций, заменяющих дефолтные.

Вариантов много: от локальных только для этой функции до глобавльных, позволяющих подменять нужное в ядре. Главное сделать так, чтобы если авторы Двойки не хотят что-то сами менять в системных файлах, чтобы у вебмастеров была возможность без патчей использовать свои варианты кода.
#5 6 февраля 2018 в 16:04
Вот ещё один простой вариант, решающий проблему создания отдельной папки для каждого файла.
Достаточно добавить в настройки сайта одну опцию-галочку "Использовать расширенную структуру папок для сохранения файлов".
Если она включена, то делать в папках пользователя папку и подпапку, как сейчас.
Если выключена — делать только одну папку первого уровня и сохранять файлы в ней, без использования и создания подпапок. Получим 256 папок на первом уровне. При сохранении пользователем четырёх пресетов для одной картинки в день, за год получим в среднем 365 дней * 4 пресета / 256 папок = 5,7 файлов в папке. Отличное наполнение папок и мало лишних подпапок.

Так разработчикам не придётся думать над другой системой хранения файлов, зато каждый сможет выбрать под свой проект подходящую ему систему папок. При этом никаких конфликтов с существующей структурой не будет.

Кроме того, можно будет для нового сайта выключить галку, а потом, если проект "попрёт" и в конечных папках будет очень много файлов, можно будет в любой момент включить галку и тогда добавится ещё один подуровень в структуру.

Скорее всего, я себе сделаю именно так, если разработчики не предложат иного варианта.
На мой взгляд это хорошее решение, удовлетворяющее всех. А как вы думаете, форумчане?
#6 6 февраля 2018 в 18:33
С хуками ещё не знакомился, поэтому сказать нечего.
Если хочется меньше папок, то всё же предложил бы не ломать 2-х уровневую структуру.
Можно ввести переменную $qf — количество папок на 1 уровне, в каждой из которых будет $qf папок 2 уровня.
Сейчас $qf = 256.
Таким образом, получим: при $qf = 5 — 25 папок для хранения файлов, при 10 — 100 и т.д… Достигнуть этого
можно небольшой модернизацией существующего алгоритма. Тут ещё потребуется повозиться с переводом из шестнадцатеричной системы
в десятичную и наоборот.
#7 6 февраля 2018 в 20:53

Или, что ещё интереснее, переименовать классы ядра в cms_имя_класса_default и сделать пустые классы cms_имя_класса, наследующие дефолтные классы. Все правки при обновлении движка разработчики Двойки будут вносить в дефолтные классы. А владельцы сайтов получат возможность заменять методы классов ядра на свои или добавлять новые без правки самого ядра.

Отличная идея!
#8 6 февраля 2018 в 21:50
Кто мне объяснит, в чем надобность отдельной папки для каждого файла?
Что страшного, если в одной папке будет лежать много файлов?
#9 6 февраля 2018 в 21:51
обычно папков находят мамки — или папки находят себе мамок и тогда они становятся папками и у них появляются файлики…
#10 6 февраля 2018 в 22:20

Кто мне объяснит, в чем надобность отдельной папки для каждого файла?
Что страшного, если в одной папке будет лежать много файлов?

Ris
Двухуровневая система папок для каждого пользователя это уже как некий стандарт де-факто. Можно нагуглить множество статей где предлагаются всевозможные варианты реализации такой системы папок.
Это требуется в первую очередь для скорости чтения файлов на сервере. Обычно принимают пороговое значение 1000 шт в одной папке. Также в зависимости от файловой системы сервера могут быть ограничения на количество.

Пробема с большим количеством папок явно надуманная. Кому не нравится волен переделывать под себя как бует угодно. Но раздувать из мухи слона… лепить набор костылей непонятно зачем ...
В общем не стоит искать черную кошку где ее нет))
#11 6 февраля 2018 в 22:37

Это требуется в первую очередь для скорости чтения файлов на сервере.

Val
Какой смысл экономить на чтении файлов, если Инстант2 все равно гарантированно уткнется в запросы mysql ?
Сайт со 127000 единиц главного типа контента. В нем ни картинок, ни ссылок, голый текст. Главный тип контента выводится на главную страницу.
И всё. Главная страница сайта открывается 5 секунд.
Я задавал вопрос на форуме:
instantcms.ru/forum/thread28414-1.html
Последовал ответ, что мол мускул несвежий и я его готовить не умею. Несколько месяцев бьюсь с настройками мускула, но проблема так и не решена.
На опенсервере тормозит почти также (4 секунды главная страница).
А на первой ветке, где тысячи файлов в одной папке, этот же сайт летал.
Так что не в количестве файлов в папке проблема, а в модели контента…
#12 6 февраля 2018 в 23:52

Какой смысл экономить на чтении файлов

Ris
Вроде никто и не экономит))

Инстант2 все равно гарантированно уткнется в запросы mysql ?
Сайт со 127000 единиц главного типа контента. В нем ни картинок, ни ссылок, голый текст. Главный тип контента выводится на главную страницу.
...

Ris
По моему мы теплое с мягким начинаем путать?! Причем тут запросы в БД и запросы сервера к файлам на диске?

Очевидно — 5 сек это долго. Трассируйте запросы, ищите узкое место и оптимизируйте. Если узкое место в одном из запросов движка — укажите на него на github'е — по возможности все починится))
#13 7 февраля 2018 в 01:50

Можно ввести переменную $qf — количество папок на 1 уровне, в каждой из которых будет $qf папок 2 уровня.

@IamB
Интересно, но не очень совместимо с текущим вариантом. Предположим, мы забили эти 25 папок по 100 файлов в каждой. Что дальше? Расширять диапазон? Тогда к этим забитым добавятся новые пустые и уже по всем ним будут "размазываться" загруженные файлы. В старых папках будет больше файлов, чем в новых. Не годится.
Второй момент — у одного пользователя эти первые 25 папок забиты, а у остальных — пустые. Как быть?
Третий минус — в том, что нужно следить вручную.
Вывод: вариант не подходит.
#14 7 февраля 2018 в 02:05

Обычно принимают пороговое значение 1000 шт в одной папке.

Val
В данной реализации это значение в принципе недостижимо. Пока мы имеем совсем противоположный результат — каждый файл в своей папке.

Это требуется в первую очередь для скорости чтения файлов на сервере.

Val
Не вижу увеличения скорости чтения, если приходится искать в двух уровнях папок вместо одного. Как раз наоборот. Тем более в предложенном мной варианте с выключенной галкой "Расширенная структура" останется один уровень с теми же 256-ю папками максимум.

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

Val
Чтобы достичь ограничения в 1000 файлов в папке при одноуровневой структуре нужно одному пользователю сохранить 256 тысяч файлов. В обычных проектах это никогда не достигается, даже в соцсетях. А кому такая возможность понадобится — просто включит одну галку в Админке — и всех делов.
А вот проблема с неадекватным количеством папок никак не надуманная. С таким подходом быстрее нарвёшься на тормоза файловой системы при еженочных операциях обслуживания, чем с 1000 файлов в папке. И МегаРостов уже попал на такое ограничение. Так что проблема реальна, просто мало людей пока с ней столкнулись в том или ином виде.

Но раздувать из мухи слона ..

Val
При всём уважении, Val, к Вам и разработчикам Двойки, не стоит убегать от решения задачи, когда она возникла. А она уже есть.
И в данной ситуации, "слона" раздувают разработчики свои категорическим отказом учитывать разные ситуации и разные нужды пользователей их системы. Сказали бы: "Посмотрим, что можно сделать, предлагайте варианты" — уже давно бы тема была решена и закрыта. А так она всё время вылазит разными боками.
#15 7 февраля 2018 в 03:04
WebMan, я выше написал структура с двойной вложенностью — это не прихоть разработчиков, а проверенная временем практика. Не поленитесь и погуглите различные статьи по организации ихранению файлов на сервере. Все практически в одиин голос сходятся на текущей структуре как самой оптимальной!

Не вижу увеличения скорости чтения, если приходится искать в двух уровнях папок вместо одного.

WebMan
какой массив быстрее перерать в сто или тысячу значений? Правильно — первый! Принцип тот же — если все в одной папке то требуемый файл ищется гораздо дольше. Плюс не забывайте что в зависимости от файловой системы конкретного хостера тоже могут быть проблемы с чрезмерно большим количеством файлов в одной папке. А CMS это же универсальная система?!

разработчикам Двойки, не стоит убегать от решения задачи, когда она возникла. А она уже есть.

WebMan
Вот скажите, у вас что за проблема возникла? Сайт тормозит и картинки не грузятся? Хостер у вас ругается что вы ему диск папками завалили или что еще?
Я не отрицаю что папки создаются! Их много, но это не смертельно! Это стандартная практика.

С таким подходом быстрее нарвёшься на тормоза файловой системы при еженочных операциях обслуживания

WebMan
Может менять подход к обслуживанию? Вот не вижу никакой потрености каждый день дергать скопу папок и файлов в них. Снимать дамп БД — возможно, но что вы делаете каждый день с файлами? Если постоянно пересохраняете резервные копии, то логично это делать еще на стадии загрузки отдельно для конкретного изображения.

И МегаРостов уже попал на такое ограничение.

WebMan
Как я понимаю МегаРостов пока единственный у кого возникли проблемы в первую очередь с запретами хостера! И ноги растут не от движка инстанта, а стороннего компонента. Если это так, то причем тут InstantCMS 2 с его структурой хранения загружаемых файлов? И в чем проблема?
Используя этот сайт, вы соглашаетесь с тем, что мы используем файлы cookie.