Принцип KISS и директивы mod_rewrite

    Пребывая в перманентных нелёгких раздумьях относительно web-технологий и своей к ним причастности, решил поделиться одной простой мыслью.

    Было: Принцип KISS в настоящее время используется плохо, и это — плохо!

    UPD 1: Афтыр пытается изобрести велосипед, поможем ему в этом? :)
    UPD 2: Автору уже не помочь… :)

    Было: Такой нелепый вывод был сделал на основе анализа настроек .htaccess для нескольких ультра-популярных систем.

    UPD 3: Автор приносит извинения всем почитателям таких настроек, но до сих пор ещё пытается понять «что проще», автор не отрицает, что он «ещё учится»… :)



    Чем именно? ::
    За прошедшие пару месяцев я вынужденно ознакомился с «коробочными» настройками mod_rewrite в .htaccess файлах следующих систем:

    • 1C-Bitrix
    • Amiro
    • Drupal
    • Joomla
    • Wordpress
    • TYPO3
    • Cogear


    Только не подумайте, что они мне не нравятся, как раз наоборот! Они хороши, все, по своему хороши для «своих» задач! И, да, я их все «смотрел»/«использовал» так, или иначе!

    Принцип, по которому устроены настройки соответствует следующей логике:

    Если нет файла, то перейти к движку.

    А именно, в общих чертах примерно так:

    	<IfModule mod_rewrite.c>
    		RewriteCond %{REQUEST_FILENAME} !-f
    		RewriteCond %{REQUEST_FILENAME} !-d
    		RewriteRule ^ <u>index.php</u> [L]
    	</IfModule>
    


    Почему этот принцип используется настолько повсеместно – ответить не смог.

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

    Что нам даёт использование этого принципа:
    1. Движок анализирует URL, ищет для него запись в БД.
    2. Если записи нет, выдается 404.
    3. Если доступ текущему пользователю «запрещён» – 403.
    4. В общем случае мы лишены возможности «вывести» стандартную 404 ошибку сервера.
    5. Порой, для тех страниц, которые «есть» мы вынуждены в коде писать вставки для «подтягивания» движка и шаблонизатора и т.п. Хотя, вообще, конечно, можно от этого избавиться, дописав их в движок, если их там нет.


    Кстати, в AmiroСMS и ряде других, подозреваю, вообще используется «архаика» на основе обработки 404 ошибки, это – «ze best»! Хотя система (не сочтите за рекламу) в целом — не плохая (ну, должен же я сказать что-то положительное, раз уже сказал что-то отрицательное).

    И, вот, собственно, вопрос – что делать, как быть?

    Для самописных (с нуля) сайтиков-визиток с десятком страниц я теперь поступаю вот так:
    	<IfModule mod_rewrite.c>
    
    		RewriteEngine On
    
    		RewriteCond %{REQUEST_FILENAME} -s
    		RewriteCond %{REQUEST_FILENAME} !-l
    		RewriteCond %{REQUEST_FILENAME} !-d
    		RewriteRule ^(.*)$ ../index.php?fn=%{REQUEST_FILENAME} [NS,NC,L]
    
    	</IfModule>
    


    Что это мне дает:

    1. «Статика» начинает обрабатываться только в том случае, если она есть.
    2. Если статики нет, значит так должно быть, отдаем 404 «из умолчания».
    3. К статике не нужно «привязывать» шаблон, он в самом движке, сразу.


    Что представляет собой моя «статика»?

    Текстовые файлы, банальные текстовые файлы…
    Первая строчка это TITLE.
    Вторая строчка это HEAD INCLUDE: всё, что мне нужно вставить до конца head.
    Всё, что ниже третьей строчки — тельце странички…

    Шаблон обычный, обычный такой шаблон, подключается в движок после того, как я «выберу» из статики три эти «переменные». Я могу сделать сколько угодно переменных, могу разделить их «спецпоследовательностью-спецсимволов», чтобы «чОтко» всё было.

    Быстро ли работает?
    Я тестов не делал, но, ИМХО – не медленнее.

    А что с данными БД?

    Так, а кто мешает сделать страничку под каждый «контроллер», или встроить «контроллеры» в тельце странички и обрабатывать «по параметрам».

    Безопасность?

    В PHP я – неофит, встроил такую проверку в начало «движка», но, полагаю, что при правильных настройках доступа она вообще не нужна.

    
    <?php
    if(isset($_GET["fn"])){
    	if(stristr($_SERVER["REQUEST_URI"], $_SERVER["SCRIPT_NAME"]) === false) {
    		$fn = $_GET["fn"];
    		if(file_exists($fn) === true){
    			$direct = 'y';
    			require_once('core.php');
    		}else{
    			$type = 404;
    			require_once('error_report.php');
    		}
    		require_once('core.php');
    	}else{
    		require_once('error_report.php');
    	}
    }else{
    	require_once('error_report.php');
    }
    ?>
    
    


    С удовольствием выслушаю комментарии относительно её ошибочности.

    Спасибо за внимание!
    Поделиться публикацией

    Похожие публикации

    Комментарии 42

      +2
      Эмм… спасибо, хороший пост, но почему вы это его в Песочницу запостили? O_O
        0
        Куда его постить, скажите, я запутался… Разработка, Веб-дев… куда?
      +3
      Посмотрите, как это сделано в фреймворках (даже лёгких, типа Кохана).
      По хорошему, в document root должны лежать только публичные файлы, всё остальное — выше document root.
      Есть два отличных способа решать, как поступать с запросом.
      Первый — это «если файл есть — открываем файл, иначе — передаем на анализ движку»
      Второй — это «если в запрос начинается с /static — давать статику, иначе — передать движку»

      Преимущество в том, что только движок может знать о том, какие страницы есть. Это могут быть страницы с числовым или даже символьным идентификатором, который хранится в базе данных. К примеру «habrahabr.ru/blogs/algorithm/» — скорее всего название блога содержится в базе данных и, естественно, физического файла такого нету.
        0
        Не спорю, на счет frameworks — абсолютно согласен, там каждый сам себе «творец».
        Тем более, что тут ничего практически не знаю и практически ни с чем толком не знаком.

        Я имел в виду принцип, когда не нужен фреймворк, когда нужно то — десяток файлов на статике, и к ним один-два шаблона.

        И за ради такого «щастя» люди ставят CMS и начинают её «мучить».

        Когда достаточно банальной статики с «нормальным» вызовом из mod_rewrite.

        Хотя, конечно, тут я уже и сам себе противоречу.
          0
          С другой стороны, при чём тут вообще движок.
          Файловая система УЖЕ знает какие файлы есть.
          Зачем подключать движок, когда эту «обработку» можно сделать самой операционкой?
            0
            Не вижу ничего плохого в подходе с проверкой на существование файлов и директорий. Сам пользую этот метод.
            Да, стандартную 404 или 403 я не показываю, да мне это и не надо. Если человек зашел на мой сайт по битой ссылке, уж лучше я ему покажу нормальный дизайн, нормаьлное меню сайта (еще и рекламу), чем просто голую страницу и кусок текста.
            Из личного опыта — зашел на сайт по ссылке, увидел белую 404-ю, закрыл вкладку и полез искать дальше. Увидел бы перед собой поиск — воспользовался бы!

            Для мелких частов (аля визитки) — да, можно без движка обойтись, но, даже если обработку нужных страниц вы сделаете не в .htaccess, а в index.php — уверяю. на скорости работы это не сильно скажется.

            И еще, простите уж, зацепился. Не обязательно даже БД дергать для обработки ЧПУ, имея хорошо продуманную структуру урла. /{module}/{task}/{param}/
            Разделили на куски и пользуем.
              0
              Та и храня урлы в БД, делал кеш попоулярных страниц — потери производительности не замечал.
        +1
        Есть достаточно способов обучить apache (мы ведь про него говорим, верно?) обрабатывать файлы с заданным расширением заданным скриптом, в том числе без применения реврайтов. Если бы мы говорили про CGI, я бы указал Вам на директивы AddHandler и Action (вероятно, с php они тоже прокатят). Дальше — проще. У вас есть некие текстовики, которые должны обрабатываться особым образом. Даете этим файлами нужное вам расширение и раскидываете их по дереву. При необходимости добавляете нужный файл в DirectoryIndex, чтобы отдавался для директории. По-моему, это чуть более правильный вариант того, что Вы хотите :)
          0
          Да, здесь речь про Apache была.

          AddHandler server-parsed .txt?

          Конечно, вполне, почему нет, и перенаправить на обработчик SSI, который вызовет PHP и там уже будет обработка этого самого TXT.

          Можно поставить на директорию директиву, при которой TXT файлы подставляются вместо вызовов PHP файлов (тем же rewrite).

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

          Попробовав сделать «иначе» я понял, что в данном конкретном случае (а ведь вмето TXT может идти просто PHP с переменными или IF вставками: if($title){?> код <?php }) может быть очень просто организовать хранение статики, и нет необходимости «оснащать» эту статику вызовами шаблонов, и можно оставить «родную» 404 и 403, и всё это, по сути, гораздо меньше напряжет движок, чем «дерганье» базы каждый раз, когда нам нужно узнать есть ли такой URL(FILE) у нас или нет. Как-то так…

          Но, опять же, это никоим образом не умаляет достоинств тех или иных систем.
            +1
            Еще проще, без обработчика SSI для вызова php. Вот фрагмент апачевой доки на Action:
            AddHandler my-file-type .xyz
            Action my-file-type /cgi-bin/program.cgi

            Для некоторых случаев вполне прокатывает перегенерация таких файликов из базы по запросу из админки. Работать будет быстро. Впрочем, как раз в этом случае можно вспомнить про старый добрый SSI и сделать еще быстрее, без php вообще. Ну и конечно же не надо файлы называть *.txt, это аукнется при сохранении файлов на компе пользователя. Можно обозвать реальные html-ки расширением htm, а обрабатываемые файлы — html, или придумать еще что-нить в этом роде. Тогда вся система будет выглядеть снаружи более адекватно. Вообще идея Ваша на мой взгляд вполне правильная — по крайней мере, для тех случаев, когда раскидать такие файлы по диску будет достаточно просто.
              0
              О! Спасибо!

              Да, я уже делал и с SSI.
              Движок в этом случае «инклюдит» страничку несколько раз.
              В страничке IF проверяет, что именно из неё инклюдить.
              Немного «парит», конечно, выписывать IF, если ручками, но принципиально ничем не отличается в итоге. К тому же в SSI можно PHP вставки сделать, если надо.
          +1
          Моя старенькая CMS (которая до сих пор используется, многое допилено, но этот момент тянется уже много лет из версии в версию), расчитанной на небольшие проекты, обходилась без htaccess и mod_rewrite впринципе. На каждый раздел сайта или страницу внутри раздела создается свой index.php (имя может быть другое, если нужно), который подключает движок. Помимо непосредственно подключения системы этот индексный файл может содержать какие-то дополнительные параметры для модулей (например, id записи, которая должна находится по данному пути, действие, которое необходимо выполнить и т. д.).
          В итоге система получает только те запросы, которые действительно должна обрабатывать (т. е. только запросы страниц сайта, созданных через CMS) и без оверхеда на подзапросы (хотя этим можно принебречь). На отдачу статики не влияет. А если по запрошенному URL ничего нет — отдается обычная 404, сгенерированная самим сервером без помощи скриптов.
            0
            Да, про то же самое говорю, только в случае с mod_rewrite можно не писать «вызов» шаблона в теле странички, единственное, по сути, отличие в «архитектуре».
            +1
            И чем же вам не нравится наша «архаика» в виде ErrorDocument 404, позвольте поинтересоваться? =)
              0
              Почему не нравится? Как раз наоборот, мне нравится, когда эта архаика используется так, как было задумано создателями web-сервера.

              И использование её в качестве обработчика запросов я тоже не порицаю, конечно, всё же работает, зачем что-то менять?

              Утверждаю, что есть «простой» выбор и «сложный». Мне почему-то думается, что «ErrorDocument 404» — это просто немного «сложней» чем непосредственный вызов страницы.

              Хотя, конечно, холиварить не хочется. 10 лет назад это уже было обсуждено.

                +1
                Нет уж, позвольте. Вы противопоставляете mod_rewrite и ErrorDocument, утверждая, что последний хуже в рамках рассматриваемой задачи. Я задаю конкретный вопрос: чем он хуже?
                  +1
                  Да не хуже он, принципиальной разницы нет, получается одно и то же в итоге.

                  Лишены будете стандартной 404, это факт. Но, «обработав» ситуацию, получите тот же результат. Контроля у Вас будет не меньше, а процессорного времени, при хорошем подходе к кодированию вряд ли займёте больше.

                  Понимаете, своим утверждением, что я их противопоставляю, Вы заставляете меня сравнивать ежа с ужом. Я их не противопоставляю, это разный подход.

                  Приведенный вариант с "-s" обрабатывает только статические страницы, файлы для которых действительно существуют и не являются символическими ссылками.
                  Т.е. подход к разработке — «от статики к динамике».

                  Подход «ErrorDocument 404» он «из другого принципа», он «из динамики к статике».

                  Задачи разные, понимаете?

                  Вот я и пытаюсь понять, чем плох принцип "-s", а всем почему-то кажется, что я их обвиняю…

                    –1
                    принцип плох тем, что как только вы придёте к необходимости создать нечто большее, чем набор из десяти статичных страниц (каталог товаров, например, себе представляете?), весь ваш принцип придётся срочно перетачивать на роутинг изнутри cms без вмешательства вебсервера.
                    надеюсь, что к тому времени вы ещё не успеете написать много кода =))
                      0
                      А что помешает мне в этом случае использовать «обычную» директиву и другой «движок» в другом «каталоге»?
                        0
                        Максим, простите, но я дейсвтиетльно пытаюсь понять чем плох этот подход, если уж говорить о «говносайтах».

                        1. Вы отрицаете, что эта директива проста?

                        2. Или Вы отрицаете что директива, выполняющая проверку на присутствие файла, проще, чем директива, выполняющая проверку на отсутствие?

                        3. Или Вы утверждаете, что проверка на отсутствие «логически мощней» (алгоритмически более верна), чем проверка на присутствие?
                        Т.е. что:

                        if (something === true)

                        Хуже чем:

                        if (something !== false)

                        Так?
                          0
                          Простите,

                            0
                            Т.е. что:

                            if (something === true)

                            Хуже чем:

                            if (something !== true)
                              +1
                              Если говорить о статичных малостраничниках, то подход имеет право на жизнь, я ж разве спорю…

                              Но как только речь зайдёт о расширении, вы сядете в лужу. Другой движок в другом каталоге? Не смешно. В усложнённом проекте нужна унификация, нужен полный контроль за роутингом, итп. Возможно, это будет сюрпризом, но как раз здесь и реализован KISS ;)
                                0
                                Спасибо, Максим, буду дальше над этим думать, если придумаю — покажу.
                              +1
                              у меня роутинг через FS решился одной маааленькой функцией (15 строк), которая создает php-файл буквально из 3 строк (+ доп. параметры, если нужны, чтобы не ходить за ними в БД). При занесении новой записи через админку файл автоматом генерится (+1 строчка в исходнике) и при удалении записи соответственно удаляется файл (еще +1 строчка). Такая система работает уже лет 6.
                              Для действительно крупных проектов, конечно, с таким подходом иногда могут возникать неудобства при разработке (хотя и все зависит от конкретной реализации, архитектуры системы и структуры сайта). Но как правило проекты такой величины разрабатываются либо на сильно кастомизированной CMS, либо под них система с нуля пишется.
                              В случае каталога продукции разницы не ощущается — либо разбирать урл и писать роутинг, либо в момент создания/редактирования/удаления записей вызывать одну функцию, которая сгенерирует файл с одним инклудом и несколькими параметрами (которые в случае mod_rewrite мы получаем именно через разбор URL'а и обращения к БД).
                              У меня лично проблема возникла, когда на одном из собственных проектов понадобилось создать по странице на каждый город мира с хоть сколько-нибудь значительным населением. Начался адъ, когда решил откопировать директорию проекта на локальной машинке (несколько десятков тысяч маленьких индексных файлов).
                              Уйти от такой схемы более чем просто — много кода менять не приходится.
                                0
                                Да, я тоже уже понял, что, например, даже новостную ленту с таким подходом «организовать» — уже дело.
                          +2
                          просто тот ад с использованием FS, который вы предложили, создаёт у меня впечатление, что вы несколько некомпетентны в рассматриваемой теме, и только-только начали изобретать свой велосипед. в то время как разработчики всех перечисленных вами CMS прошли эту стадию много лет назад =)
                            0
                            Совершенно верно, я же говорю, я — неофит.
                              0
                              Специально для этого комментария сделал UPD в начале топика…
                            0
                            Ну как вариант можно тупо начать долбить Ваш «архаичный» сайт случайными урлами, и Вы будете за каждым из них ходить в базу, чтобы убедиться, что его там действительно нет.
                              0
                              mod_rewrite поведёт себя иначе? %)
                                +1
                                В том виде, как его предлагает автор статьи — да, там проверяется только наличие файла на диске. Чуть выше в комментах я предложил способ выполнить эту проверку без участия php вовсе, только средствами апача.
                                  0
                                  в том виде, как предлагает автор статьи, механизм роутинга годится только для говносайтов на 10-15 страниц. впрочем, справедливости ради стоит отметить, что автор ни на что большее не претендует и явно указывает это в статье.

                                  ошибка автора в том, что он сравнивает свой наколенный подход с крупными коробочными CMS, применительно к которым роутинг через файловую систему слегка отдаёт сумасшедшинкой.
                                    0
                                    Почему то мне кажется, что Вы не попробовали, а просто защищаете известный подход. Я — пробовал, мне нравится и так и так. Все хорошо в меру.
                              0
                              Кстати, Максим, я вот сейчас, наконец, увидел слова «наша „архаика“».
                              Если Вы имеете отношение Амиро, то знайте — мне действительно понравилась система.
                              Я был слегка удивлен тому, что она через ErrorDocument, но, ведь это ничего не меняет в функционале.
                              А в функционале она очень даже хороша. Если что — это не реклама, это ответ на указанные слова.
                                +1
                                Спасибо =)

                                Я у ErrorDocument по сравнению с mod_rewrite вижу несколько плюсов и только один минус. Так что, похоже, он будет жить ещё долго =)
                                  0
                                  А можете озвучить ради интереса эти плюсы? Мне как-то ближе mod_rewrite в том плане, что ErrorDocument это все-таки обработка ошибки в первую очередь. Но хотелось бы услышать альтернативное мнение по этому поводу.
                                    0
                                    сразу оговорим, что плюсы эти не вселенского масштаба, а мелкие, иначе все уже давно сидели бы на ErrorDocument =)
                                    1. mod_rewrite есть не везде
                                    2. где он есть — очень часто бывает отключен. включить его, даже из панели управления хостингом, среднестатистическому пользователю CMS — маленький подвиг.
                                    3. для пользователя интструкция «добавить вот эту простую строку в любое место файла» гораздо понятнее аналога для mod_rewrite
                                    4. mod_rewrite может активно использоваться на сайте для SEO, например, при этом придётся внедрять обработку 404 в существующие правила. либо наоборот, настроена обработка 404 через mod_rewrite, и нужно внести несколько правил для SEO — просто скопировав правила из инстуркций в интернете (а так все и делают, поверьте) юзер всё разломает.

                                    сразу скажу единственный известный мне минус: апач не умеет отключать нотификацию в error_log о том, что файл не найден, при срабатывании ErrorDocument 404. получаем по одной записи в error_log для каждого срабатывания. есть патчи, отключающие это, но на shared их естественно вам никто не поставит.
                                      0
                                      то есть, по сути, используя ErrorDocument в противовес mod_rewrite, мы сужаем список техтребований для хостинга (крайне незначительно, я прекрасно понимаю, но «бесплатно» — почему бы и нет), и резко снижаем трудозатраты первой линии саппорта на техподдержку связанную с механизмом роутинга.
                              0
                                0
                                что-то с клавиатурой

                                maxout,

                                Спасибо!!!

                                Это в любом случае было конструктивно!

                                Топик слило, так что — всё, наверное.

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

                              Самое читаемое