За последние 24 часа нас посетили 22619 программистов и 1146 роботов. Сейчас ищут 678 программистов ...

Просветите по QUERY_STRING и REQUEST_URI

Тема в разделе "PHP для новичков", создана пользователем AlexandrS, 12 сен 2019.

  1. AlexandrS

    AlexandrS Активный пользователь

    С нами с:
    30 сен 2017
    Сообщения:
    659
    Симпатии:
    103
    Адрес:
    Краснодар
    Не знаю по какой причине, но ранее это не замечал.
    Имею единую точку входа.

    .htaccess

    Код (Text):
    1. AddDefaultCharset utf-8
    2. RewriteEngine On
    3. RewriteRule (.*) public/$1
    .htaccess

    Код (Text):
    1. RewriteCond %{REQUEST_FILENAME} !-f
    2. RewriteCond %{REQUEST_FILENAME} !-d
    3. RewriteRule (.*) index.php?$1 [L,QSA]
    И вот я обратил внимание, что значения в QUERY_STRING и REQUEST_URI совершенно одинаковые, кроме первого слеша (в QUERY_STRING он отсутствует).

    Правильно ли я понимаю, что это связано с тем, что в .htaccess прописано RewriteRule (.*) index.php?$1 [L,QSA] и по этой причине все запросы приходящие с адресной строки браузера, вместе с именами директорий (path) преобразовываются в запрос.

    Т.е. в обычной ситуации :

    $_SERVER['REQUEST_URI'] => /test/index.php?id=1&test=wet&id_theme=512
    $_SERVER['QUERY_STRING'] => id=1&test=wet&id_theme=512

    а с .htaccess при единой точке входа это уже:

    $_SERVER['REQUEST_URI'] => /test/index.php?id=1&test=wet&id_theme=512
    $_SERVER['QUERY_STRING'] => test/index.php?id=1&test=wet&id_theme=512
     
  2. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.792
    Симпатии:
    650
    Последняя строка – это твое предположение или результат эксперимента?

    Правило в достаточной степени кривое, поэтому апач может не сориентироваться и «бить» QUERY_STRING, добавляя внутрь строки параметров разделитель «?». Попробуй в правиле написать index.php?path=$1 [L,QSA] или index.php/$1 [L] (последнее называется передачей пути через PATH_INFO: для извлечения параметра нужно использовать соотв. переменную; флаг QSA тут без надобности, потому что когда ты не прописываешь свою строку параметров в подстановке, исходная наследуется дефолтом).

    В общем же какая-либо внутренняя трансляция пути в строку параметров и т.п. – это уже олдскул. Профит стремится к нулю, в остальном проблемы. Уже наверно давал почитать: Как сделать единую точку входа с ЧПУ?
    --- Добавлено ---
    P.S. Вот это тоже правило для ламеров:
    Код (Text):
    1. RewriteRule (.*) public/$1
    Его прописывают просто как заглушку для будущей норм. подкрутки сайта.
    --- Добавлено ---
    P.P.S. Многие хостеры в шареде различают каталог сайта/проекта и его корневой/публичный каталог.
     
    AlexandrS нравится это.
  3. AlexandrS

    AlexandrS Активный пользователь

    С нами с:
    30 сен 2017
    Сообщения:
    659
    Симпатии:
    103
    Адрес:
    Краснодар
    Если речь про это:

    $_SERVER['REQUEST_URI'] => /test/index.php?id=1&test=wet&id_theme=512
    $_SERVER['QUERY_STRING'] => test/index.php?id=1&test=wet&id_theme=512

    То это таким образом у меня отображаются $_SERVER['REQUEST_URI'] и $_SERVER['QUERY_STRING'], т.е. это не предположение, а по сути факт :)

    Судя по той статье на которую ты дал ссылку, там речь про .htaccess который единожды присутствует, у меня получается что первый запрос , перехватывается тут:


    Код (Text):
    1. AddDefaultCharset utf-8
    2. RewriteEngine On
    3. RewriteRule (.*) public/$1
    И отправляет в директорию "public" в котором находится index.php и .htaccess с содержимым:

    Код (Text):
    1. RewriteCond %{REQUEST_FILENAME} !-f
    2. RewriteCond %{REQUEST_FILENAME} !-d
    3. RewriteRule (.*) index.php?$1 [L,QSA]
    в index.php подключается файл конфига и вызывается класс Application в котором вызывается обработчик ошибок и фронт контроллер
     
  4. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.792
    Симпатии:
    650
    Ну значит я прав: апач не может норм. обработать такой «странный» способ передачи пути совместно с флагом QSA. Попробуй первый предложенный мной вариант. Думаю, все придет в норму, т.е. будет path=test/index.php&...

    Я же написал, что по сути это заглушка. В реале public делают корнем соотв. директивой сервера, а всю внутр. кухню оставляют выше/рядом с корнем. Т.е. этот .htaccess вообще не нужен, если ты оставляешь .htaccess в public (иногда делают наоборот).
    --- Добавлено ---
    P.S. Вот жена там же статейку по этому поводу писала: https://gency.ru/g-drive-setup (см. от «Одной из самых востребованных настроек...» и до конца).
     
    AlexandrS нравится это.
  5. AlexandrS

    AlexandrS Активный пользователь

    С нами с:
    30 сен 2017
    Сообщения:
    659
    Симпатии:
    103
    Адрес:
    Краснодар
    Благодарю!

    PS: Вот тут на форуме периодически спрашивают, как учиться PHP и т.п. некоторые проходят курсы, ютубы и т.п., вот по сути и результат таких вот обучений (я не проходил просто видосы вот таких вот обучалок смотрел, да и часто встречал именно такой вариант "единой точки входа", а люди платят за это $$$ и приобретают заведомо неправильную информацию.)
     
  6. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.792
    Симпатии:
    650
    P.P.S. Только там внутр. обвес в каталоге mods был закрыт правилом-заглушкой, а у тебя правилом-заглушкой как бы корень смещается глубже. Но назначение этих манипуляций по сути одно и то же. В реале эти заглушки лучше не использовать.

    Ну старайся общаться со спецами. Я курсов не проходил, на ютьюбе всякую хрень с целью обучения не смотрел (иногда см., чисто чтобы поржать). Писал и получал в плечо от старших товарищей за косяки, особенно когда что-то из сказанного ими «посмел» прослушать. В общем спрашивай. Чем смогу помогу. Когда вижу на форуме вопросы, в кот. прослеживается желание разобраться, стараюсь по возможности отвечать.
     
    #6 miketomlin, 12 сен 2019
    Последнее редактирование: 12 сен 2019
    AlexandrS нравится это.
  7. AlexandrS

    AlexandrS Активный пользователь

    С нами с:
    30 сен 2017
    Сообщения:
    659
    Симпатии:
    103
    Адрес:
    Краснодар
    Благодарю за советы, рекомендации. Общаться со спецами, так чтоб спросить, как лучше и почему так или иначе в живую или режиме реалтайм. Если только, тут, на форуме.
     
  8. acho

    acho Активный пользователь

    С нами с:
    28 дек 2016
    Сообщения:
    854
    Симпатии:
    210
    Адрес:
    Санкт-Петербург
    оффтоп: у нас ещё есть тележка :)
     
  9. AlexandrS

    AlexandrS Активный пользователь

    С нами с:
    30 сен 2017
    Сообщения:
    659
    Симпатии:
    103
    Адрес:
    Краснодар
    @miketomlin
    сейчас в корне .htaccess и index.php

    .htaccess
    Код (Text):
    1. RewriteEngine On
    2.  
    3. RewriteCond %{REQUEST_FILENAME} !-f
    4. RewriteRule ^.* /index.php
    5.  
    6. AddDefaultCharset utf-8
    index.php
    PHP:
    1. <?php
    2.  
    3. echo "<pre>";
    4. print_r($_SERVER['REQUEST_URI']);
    5. echo "</pre>";
    6.  
    7. ?>
    И получается так, что если файла нет, то идет запрос к index.php, а если файл есть, то он открывается или исполняется.

    Там же в статье написано, что для этого нужно в правиле прописать
    Код (Text):
    1. RewriteBase /
    вместо
    Код (Text):
    1. %{REQUEST_FILENAME} !-f
    и тут у меня возник вопрос, а как будут вести себя изображения, файлы стилей и т.п.? получается в данном варианте с RewriteBase все запросы будут проходить через index.php?

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

    Возможно вопрос и глупый и я что-то не до понимаю, но если не сложно, поясните.

    Еще там написано:
    Просто у меня идет еще проксирование и статика отдается не через apache, а nginx (если я не ошибаюсь.)
     
  10. AlexandrS

    AlexandrS Активный пользователь

    С нами с:
    30 сен 2017
    Сообщения:
    659
    Симпатии:
    103
    Адрес:
    Краснодар
  11. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.792
    Симпатии:
    650
    Это в моем первом комменте для обратного случая написано, т.е. когда «файл-обработчик должен перехватывать все входящие запросы, включая обращения к существующим файлам». В этом случае либо фронт должен выдавать в том числе и статик, либо нужно размещать статик на др. хосте (за вычетом всяких фэйвайконов, роботсов и т.п.). И RewriteBase тут играет важную роль, но не определяющую, т.е. ее можно было использовать и для случая с исключением статика совместно с той же RewriteCond.
    --- Добавлено ---
    Есть ситуации, когда это нужно, например отдача статика только авторизованным (для оптимизации выдачи контента статика там используют спец. методы оптимизации, т.е. контент выдается непосредственно пыхом только кодом-заглушкой, а в реале опять по-другому :)).
    --- Добавлено ---
    Все норм.

    Тоже вариант, когда статик отдается сервером-фронтом, а все промахи уходят в бэк. Только тут сервер бэком сильно смахивает на пятое колесо. Лучше сразу поставить бэком пых.
    --- Добавлено ---
    P.S. Это к стертому посту:
    Я уже написал, что это может быть функциональная необходимость. За счет оптимизации повышение нагрузки можно свести к минимуму. В реале пых не отдает контент сам (важный фактор), а возвращает серверу спец. «заголовок», чтобы тот выдал нужный контент (статик файл).
     
    AlexandrS нравится это.
  12. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.792
    Симпатии:
    650
    Само разделение выдачи статика и динамика между разными хостами – хорошая оптимизация. Не нужно при обработке каждого запроса делать тест на наличие статика.

    P.S. Кэширование динамика на стороне сервера в расчет не беру. Это отдельная сложная тема.
     
    AlexandrS нравится это.
  13. AlexandrS

    AlexandrS Активный пользователь

    С нами с:
    30 сен 2017
    Сообщения:
    659
    Симпатии:
    103
    Адрес:
    Краснодар
    Такое бывает например, на сайтах знакомств и т.п., где обычным пользователям представлены только миниатюры, а авторизированным уже полноразмерные - в таком варианте это уже логично использовать фронт, но если речь идео элементов дизайна, то тут не рационально прогонять каждый запрос через фронт поэтому для этого нужно прописывать условие в RewriteCond, чтоб всё это тянулось с определенной директории.
    --- Добавлено ---
    Большое спасибо за ответы!
     
  14. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.792
    Симпатии:
    650
    См. пред. пост. И не думай о «сайтах» слишком узко. Если это какая-то закрытая панель, то к примеру для антидетекта можно и названный статик обвес закрыть. Или опять-таки подтягивать его с совершенно другого хоста.
     
    #14 miketomlin, 15 сен 2019
    Последнее редактирование: 15 сен 2019
    AlexandrS нравится это.
  15. AlexandrS

    AlexandrS Активный пользователь

    С нами с:
    30 сен 2017
    Сообщения:
    659
    Симпатии:
    103
    Адрес:
    Краснодар
    Вернулся к разбору, закинул HTML код в шаблон и в тех местах где должны выводиться изображения, разумеется ничего не выводится, т.к. все эти ссылки обрабатываются фронтендом, к примеру:
    HTML:
    1. <link rel="stylesheet" href="assets/css/main.css" />
    Идет обращение к контроллеру "assets" и далее по вложенности, обратится к экшену "css" и тут я не могу сообразить, как в данном случае отдавать контент. Т.е. физически контент лежит по одному пути, а возвращать его нужно, как буд-то он находится по тому адресу, по которому идет запрос в html коде.

    Вроде все должно быть довольно просто, но как-то туплю.
     
    #15 AlexandrS, 13 ноя 2019
    Последнее редактирование: 13 ноя 2019
  16. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.792
    Симпатии:
    650
    Получается, "main.css" – параметр, идентифицирующий таблицу стилей. Нужно по нему прочитать контент (из ФС или БД) и вывести, сопроводив соответствующим заголовком Content-Type.

    P.S. "css" как экшин – по-моему не очень. Его можно использовать, как часть идентификатора или как параметр, указывающий на тип (хотя расширение для определения типа значительно лучше подойдет).
    --- Добавлено ---
    P.P.S. В ссылках на обвес значительно лучше использовать абс. адресацию (адреса начинающиеся со слэша или дв. слэша), если не используется тэг base.
     
    #16 miketomlin, 13 ноя 2019
    Последнее редактирование: 13 ноя 2019
    AlexandrS нравится это.
  17. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.792
    Симпатии:
    650
    Если у тебя сервер не вычитывает «автоматом» статик, то он может спокойно лежать и по тому же пути, а твой скрипт просто будет выполнять роль сервера в пределах конкретной адресной ветки (/assets/). В реале они обычно совместно работают, когда речь идет о считывании из ФС: скрипт выдает протокольные заголовки и спец. заголовок на считывание файла, который перехватывает модуль сервера и по нему читает и выдает содержимое файла.
     
    AlexandrS нравится это.
  18. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.792
    Симпатии:
    650
    Для определения реального местоположения файла можно использовать только адрес. Либо реальное местоположение файла нужно хранить отдельно (в БД), например при обработке запросов по шаблону files/{id} ты можешь использовать простейшую таблицу соответствия
    Код (Text):
    1. id path
    2. 1  /var/www/static/files/main.css
    Путь в базе можно хранить и относительный, что по неск. причинам предпочтительнее.
     
    AlexandrS нравится это.
  19. AlexandrS

    AlexandrS Активный пользователь

    С нами с:
    30 сен 2017
    Сообщения:
    659
    Симпатии:
    103
    Адрес:
    Краснодар
    Ок, благодарю, сейчас обмозгую всю эту инфу.
    Тут была идея в том, чтоб можно было по определенным правилам создавать "templates" шаблон сайта, кидать это всё в одну директорию и просто в админке подключать тот или иной шаблон, по типу как в вордпрессе.
    И тут получилось так, что собственно HTML он отображает, а вот ссылки которые обращаются к контенту (ico, css, jpg, png и т.п.) не обрабатываются и контент не подтягивается.
     
  20. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.792
    Симпатии:
    650
    Лучше, чтобы при переключении шаблонов адреса обвеса менялись (или в пути, или в строке параметров). Например, см. адреса обвеса у сайта по ссылкам выше: /a/first/* (first – это имя шаблона). По идее можно использовать и какой-то такой формат /a/*?t=first. Это связано с кэшированием статика в браузере. В разметке шаблона это в общем-то можно и захардкодить, но наверно лучше использовать какую-то переменную/константу, потому что, даже если всегда использовать только префикс в пути, тот же компонент /a/ по идее может меняться (например, в наших сайтах помимо /a/ также часто используется /assets/).

    P.S. Сейчас на том сайте не используется динамическая выдача статика (кроме сайтмапа, который к тому же может кэшироваться в соотв. файле). Но если бы использовалась, основная часть статик обвеса (речь не о файлах, относящихся к осн. контенту, а о файлах, относящихся именно к оформлению) выдавалась бы наверное универсальным экшином, прикрепленным к ветке /a/. Еще частенько в наших сайтах используется такое соответствие между адресами и путями ФС: /prefix/* -> КОРЕНЬ_САЙТА/*, т.е. по идее каталог first мог бы физически располагаться и прямо в корне, а /a/ был бы чисто вирт. префиксом, являющимся «ручкой» к программному обработчику. Но это все фигня инфа к сведению, в кот. можно особо не вникать.
    --- Добавлено ---
    P.P.S. Естественно, выше речь только о публичном обвесе. Даже если сервер сам и не читает приватный статик, его все равно лучше не размещать в паблик каталоге.
     
    AlexandrS нравится это.
  21. AlexandrS

    AlexandrS Активный пользователь

    С нами с:
    30 сен 2017
    Сообщения:
    659
    Симпатии:
    103
    Адрес:
    Краснодар
    Речь о подобном?

    PHP:
    1. <?php
    2.  
    3. header("Content-Type: image/png");
    4. echo file_get_contents("./images/img.jpg");
    5.  
    6. ?>
    или

    PHP:
    1. <?php
    2.  
    3. header("Content-Type: image/png");
    4. readfile("./images/img.jpg");
    5.  
    6. ?>
     
  22. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.792
    Симпатии:
    650
    Да. А когда я далее писал про универсальность, речь была о значении Content-Type и об имени читаемого/выводимого файла. Плюс можно добавить вилку: например, в зависимости от параметра конфигурации читать/выводить файл либо штатными средствами пыха, либо «попросить» сервер прочитать/вывести файл самостоятельно.
     
    AlexandrS нравится это.
  23. AlexandrS

    AlexandrS Активный пользователь

    С нами с:
    30 сен 2017
    Сообщения:
    659
    Симпатии:
    103
    Адрес:
    Краснодар
    А где-то есть примеры чтоб посмотреть, как это делается?
     
  24. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.792
    Симпатии:
    650
    Поищи примеры по ключам «псевдозаголовок/спец. заголовок X-Sendfile», «псевдозаголовок/спец. заголовок X-Accel-Redirect» и т.п.
     
    AlexandrS нравится это.
  25. AlexandrS

    AlexandrS Активный пользователь

    С нами с:
    30 сен 2017
    Сообщения:
    659
    Симпатии:
    103
    Адрес:
    Краснодар
    Благодарю за помощь и ответы.
    Наткнулся на вот это: https://habr.com/ru/post/151795/ почитал комменты и пришел к выводу, что самый оптимальный вариант для Apache или Nginxs это:

    PHP:
    1. function file_force_download($file) {
    2.   if (file_exists($file)) {
    3.     header('X-SendFile: ' . realpath($file));
    4.     header('Content-Type: application/octet-stream');
    5.     header('Content-Disposition: attachment; filename=' . basename($file));
    6.     exit;
    7.   }
    8. }
    т.к. использование readfile() создает больше нагрузки и чревато проблемами. Правда статье 7 лет, но не думаю что, что-то кардинально изменилось.

    Единственный момент, который не дает покоя, т.к. еще не занялся решением вопроса, - это то, что из HTML, кода будут идти запросы, к примеру:

    HTML:
    1.  
    2. <section class="box feature">
    3.     <a href="#" class="image featured"><img src="images/pic02.jpg" alt="" /></a>
    4.     <div class="inner">
    5.         <header>
    6.             <h2>An interesting title</h2>
    7.             <p>This is also an interesting subtitle</p>
    8.         </header>
    9.         <p>Phasellus quam turpis, feugiat sit amet in, hendrerit in lectus. Praesent sed semper amet bibendum tristique fringilla.</p>
    10.     </div>
    11.  
    но будет ли сервер отдавать и выводить изображение в том месте, где этого требует HTML.