Не знаю по какой причине, но ранее это не замечал. Имею единую точку входа. .htaccess Код (Text): AddDefaultCharset utf-8 RewriteEngine On RewriteRule (.*) public/$1 .htaccess Код (Text): RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d 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
Последняя строка – это твое предположение или результат эксперимента? Правило в достаточной степени кривое, поэтому апач может не сориентироваться и «бить» QUERY_STRING, добавляя внутрь строки параметров разделитель «?». Попробуй в правиле написать index.php?path=$1 [L,QSA] или index.php/$1 [L] (последнее называется передачей пути через PATH_INFO: для извлечения параметра нужно использовать соотв. переменную; флаг QSA тут без надобности, потому что когда ты не прописываешь свою строку параметров в подстановке, исходная наследуется дефолтом). В общем же какая-либо внутренняя трансляция пути в строку параметров и т.п. – это уже олдскул. Профит стремится к нулю, в остальном проблемы. Уже наверно давал почитать: Как сделать единую точку входа с ЧПУ? --- Добавлено --- P.S. Вот это тоже правило для ламеров: Код (Text): RewriteRule (.*) public/$1 Его прописывают просто как заглушку для будущей норм. подкрутки сайта. --- Добавлено --- P.P.S. Многие хостеры в шареде различают каталог сайта/проекта и его корневой/публичный каталог.
Если речь про это: $_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): AddDefaultCharset utf-8 RewriteEngine On RewriteRule (.*) public/$1 И отправляет в директорию "public" в котором находится index.php и .htaccess с содержимым: Код (Text): RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule (.*) index.php?$1 [L,QSA] в index.php подключается файл конфига и вызывается класс Application в котором вызывается обработчик ошибок и фронт контроллер
Ну значит я прав: апач не может норм. обработать такой «странный» способ передачи пути совместно с флагом QSA. Попробуй первый предложенный мной вариант. Думаю, все придет в норму, т.е. будет path=test/index.php&... Я же написал, что по сути это заглушка. В реале public делают корнем соотв. директивой сервера, а всю внутр. кухню оставляют выше/рядом с корнем. Т.е. этот .htaccess вообще не нужен, если ты оставляешь .htaccess в public (иногда делают наоборот). --- Добавлено --- P.S. Вот жена там же статейку по этому поводу писала: https://gency.ru/g-drive-setup (см. от «Одной из самых востребованных настроек...» и до конца).
Благодарю! PS: Вот тут на форуме периодически спрашивают, как учиться PHP и т.п. некоторые проходят курсы, ютубы и т.п., вот по сути и результат таких вот обучений (я не проходил просто видосы вот таких вот обучалок смотрел, да и часто встречал именно такой вариант "единой точки входа", а люди платят за это $$$ и приобретают заведомо неправильную информацию.)
P.P.S. Только там внутр. обвес в каталоге mods был закрыт правилом-заглушкой, а у тебя правилом-заглушкой как бы корень смещается глубже. Но назначение этих манипуляций по сути одно и то же. В реале эти заглушки лучше не использовать. Ну старайся общаться со спецами. Я курсов не проходил, на ютьюбе всякую хрень с целью обучения не смотрел (иногда см., чисто чтобы поржать). Писал и получал в плечо от старших товарищей за косяки, особенно когда что-то из сказанного ими «посмел» прослушать. В общем спрашивай. Чем смогу помогу. Когда вижу на форуме вопросы, в кот. прослеживается желание разобраться, стараюсь по возможности отвечать.
Благодарю за советы, рекомендации. Общаться со спецами, так чтоб спросить, как лучше и почему так или иначе в живую или режиме реалтайм. Если только, тут, на форуме.
@miketomlin сейчас в корне .htaccess и index.php .htaccess Код (Text): RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^.* /index.php AddDefaultCharset utf-8 index.php PHP: <?php echo "<pre>"; print_r($_SERVER['REQUEST_URI']); echo "</pre>"; ?> И получается так, что если файла нет, то идет запрос к index.php, а если файл есть, то он открывается или исполняется. Там же в статье написано, что для этого нужно в правиле прописать Код (Text): RewriteBase / вместо Код (Text): %{REQUEST_FILENAME} !-f и тут у меня возник вопрос, а как будут вести себя изображения, файлы стилей и т.п.? получается в данном варианте с RewriteBase все запросы будут проходить через index.php? Ведь в данном случае возрастает нагрузка, ведь либо отдать статику через прямой запрос, либо все пустить через обработку. Возможно вопрос и глупый и я что-то не до понимаю, но если не сложно, поясните. Еще там написано: Просто у меня идет еще проксирование и статика отдается не через apache, а nginx (если я не ошибаюсь.)
Нашел еще вот такой вариант единой точки входа: https://github.com/nazar-pc/CleverStyle-Framework/blob/master/.htaccess
Это в моем первом комменте для обратного случая написано, т.е. когда «файл-обработчик должен перехватывать все входящие запросы, включая обращения к существующим файлам». В этом случае либо фронт должен выдавать в том числе и статик, либо нужно размещать статик на др. хосте (за вычетом всяких фэйвайконов, роботсов и т.п.). И RewriteBase тут играет важную роль, но не определяющую, т.е. ее можно было использовать и для случая с исключением статика совместно с той же RewriteCond. --- Добавлено --- Есть ситуации, когда это нужно, например отдача статика только авторизованным (для оптимизации выдачи контента статика там используют спец. методы оптимизации, т.е. контент выдается непосредственно пыхом только кодом-заглушкой, а в реале опять по-другому ). --- Добавлено --- Все норм. Тоже вариант, когда статик отдается сервером-фронтом, а все промахи уходят в бэк. Только тут сервер бэком сильно смахивает на пятое колесо. Лучше сразу поставить бэком пых. --- Добавлено --- P.S. Это к стертому посту: Я уже написал, что это может быть функциональная необходимость. За счет оптимизации повышение нагрузки можно свести к минимуму. В реале пых не отдает контент сам (важный фактор), а возвращает серверу спец. «заголовок», чтобы тот выдал нужный контент (статик файл).
Само разделение выдачи статика и динамика между разными хостами – хорошая оптимизация. Не нужно при обработке каждого запроса делать тест на наличие статика. P.S. Кэширование динамика на стороне сервера в расчет не беру. Это отдельная сложная тема.
Такое бывает например, на сайтах знакомств и т.п., где обычным пользователям представлены только миниатюры, а авторизированным уже полноразмерные - в таком варианте это уже логично использовать фронт, но если речь идео элементов дизайна, то тут не рационально прогонять каждый запрос через фронт поэтому для этого нужно прописывать условие в RewriteCond, чтоб всё это тянулось с определенной директории. --- Добавлено --- Большое спасибо за ответы!
См. пред. пост. И не думай о «сайтах» слишком узко. Если это какая-то закрытая панель, то к примеру для антидетекта можно и названный статик обвес закрыть. Или опять-таки подтягивать его с совершенно другого хоста.
Вернулся к разбору, закинул HTML код в шаблон и в тех местах где должны выводиться изображения, разумеется ничего не выводится, т.к. все эти ссылки обрабатываются фронтендом, к примеру: HTML: <link rel="stylesheet" href="assets/css/main.css" /> Идет обращение к контроллеру "assets" и далее по вложенности, обратится к экшену "css" и тут я не могу сообразить, как в данном случае отдавать контент. Т.е. физически контент лежит по одному пути, а возвращать его нужно, как буд-то он находится по тому адресу, по которому идет запрос в html коде. Вроде все должно быть довольно просто, но как-то туплю.
Получается, "main.css" – параметр, идентифицирующий таблицу стилей. Нужно по нему прочитать контент (из ФС или БД) и вывести, сопроводив соответствующим заголовком Content-Type. P.S. "css" как экшин – по-моему не очень. Его можно использовать, как часть идентификатора или как параметр, указывающий на тип (хотя расширение для определения типа значительно лучше подойдет). --- Добавлено --- P.P.S. В ссылках на обвес значительно лучше использовать абс. адресацию (адреса начинающиеся со слэша или дв. слэша), если не используется тэг base.
Если у тебя сервер не вычитывает «автоматом» статик, то он может спокойно лежать и по тому же пути, а твой скрипт просто будет выполнять роль сервера в пределах конкретной адресной ветки (/assets/). В реале они обычно совместно работают, когда речь идет о считывании из ФС: скрипт выдает протокольные заголовки и спец. заголовок на считывание файла, который перехватывает модуль сервера и по нему читает и выдает содержимое файла.
Для определения реального местоположения файла можно использовать только адрес. Либо реальное местоположение файла нужно хранить отдельно (в БД), например при обработке запросов по шаблону files/{id} ты можешь использовать простейшую таблицу соответствия Код (Text): id path 1 /var/www/static/files/main.css Путь в базе можно хранить и относительный, что по неск. причинам предпочтительнее.
Ок, благодарю, сейчас обмозгую всю эту инфу. Тут была идея в том, чтоб можно было по определенным правилам создавать "templates" шаблон сайта, кидать это всё в одну директорию и просто в админке подключать тот или иной шаблон, по типу как в вордпрессе. И тут получилось так, что собственно HTML он отображает, а вот ссылки которые обращаются к контенту (ico, css, jpg, png и т.п.) не обрабатываются и контент не подтягивается.
Лучше, чтобы при переключении шаблонов адреса обвеса менялись (или в пути, или в строке параметров). Например, см. адреса обвеса у сайта по ссылкам выше: /a/first/* (first – это имя шаблона). По идее можно использовать и какой-то такой формат /a/*?t=first. Это связано с кэшированием статика в браузере. В разметке шаблона это в общем-то можно и захардкодить, но наверно лучше использовать какую-то переменную/константу, потому что, даже если всегда использовать только префикс в пути, тот же компонент /a/ по идее может меняться (например, в наших сайтах помимо /a/ также часто используется /assets/). P.S. Сейчас на том сайте не используется динамическая выдача статика (кроме сайтмапа, который к тому же может кэшироваться в соотв. файле). Но если бы использовалась, основная часть статик обвеса (речь не о файлах, относящихся к осн. контенту, а о файлах, относящихся именно к оформлению) выдавалась бы наверное универсальным экшином, прикрепленным к ветке /a/. Еще частенько в наших сайтах используется такое соответствие между адресами и путями ФС: /prefix/* -> КОРЕНЬ_САЙТА/*, т.е. по идее каталог first мог бы физически располагаться и прямо в корне, а /a/ был бы чисто вирт. префиксом, являющимся «ручкой» к программному обработчику. Но это все фигня инфа к сведению, в кот. можно особо не вникать. --- Добавлено --- P.P.S. Естественно, выше речь только о публичном обвесе. Даже если сервер сам и не читает приватный статик, его все равно лучше не размещать в паблик каталоге.
Речь о подобном? PHP: <?php header("Content-Type: image/png"); echo file_get_contents("./images/img.jpg"); ?> или PHP: <?php header("Content-Type: image/png"); readfile("./images/img.jpg"); ?>
Да. А когда я далее писал про универсальность, речь была о значении Content-Type и об имени читаемого/выводимого файла. Плюс можно добавить вилку: например, в зависимости от параметра конфигурации читать/выводить файл либо штатными средствами пыха, либо «попросить» сервер прочитать/вывести файл самостоятельно.
Поищи примеры по ключам «псевдозаголовок/спец. заголовок X-Sendfile», «псевдозаголовок/спец. заголовок X-Accel-Redirect» и т.п.
Благодарю за помощь и ответы. Наткнулся на вот это: https://habr.com/ru/post/151795/ почитал комменты и пришел к выводу, что самый оптимальный вариант для Apache или Nginxs это: PHP: function file_force_download($file) { if (file_exists($file)) { header('X-SendFile: ' . realpath($file)); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename=' . basename($file)); exit; } } т.к. использование readfile() создает больше нагрузки и чревато проблемами. Правда статье 7 лет, но не думаю что, что-то кардинально изменилось. Единственный момент, который не дает покоя, т.к. еще не занялся решением вопроса, - это то, что из HTML, кода будут идти запросы, к примеру: HTML: <section class="box feature"> <a href="#" class="image featured"><img src="images/pic02.jpg" alt="" /></a> <div class="inner"> <header> <h2>An interesting title</h2> <p>This is also an interesting subtitle</p> </header> <p>Phasellus quam turpis, feugiat sit amet in, hendrerit in lectus. Praesent sed semper amet bibendum tristique fringilla.</p> </div> </section> но будет ли сервер отдавать и выводить изображение в том месте, где этого требует HTML.