Форум программистов, компьютерный форум, киберфорум
PHP для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.64/28: Рейтинг темы: голосов - 28, средняя оценка - 4.64
32 / 29 / 12
Регистрация: 04.03.2013
Сообщений: 895

Роуминг PHP: Как сделать редиректы и отдавать код ответа сервера?

16.11.2022, 17:32. Показов 6744. Ответов 90

Студворк — интернет-сервис помощи студентам
Здравствуйте!
Простите, если не сюда пишу.

Не силен в PHP.
Пишу роутинг.
Работаю на OpenServer.
index.php:
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
 
// FRONT COTROLLER
 
// 1. Общие настройки
 
ini_set('display_errors', 1);
error_reporting(E_ALL);
 
// 2. Подключение файлов системы
 
define('ROOT', dirname(__FILE__));
require_once(ROOT.'/components/Router.php');
require_once(ROOT.'/components/Db.php');
 
// 3. Установка соединения с БД
 
 
// 4. Вызов Router
 
$router = new Router();
$router->run();
htaccess:
PHP
1
2
3
4
5
6
7
8
AddDefaultCharset utf-8
 
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?route=$1 [L]
routes.php:
PHP
1
2
3
4
5
<?php
return array(
'news/([0-9]+)' => 'news/view/$1',
'news' => 'news/index', // actionIndex in NewsController
);
Router.php:
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?php
 
class Router {
 
private $routes;//создаем массив в кот. хранятся наши маршруты
 
public function __construct(){
    $routesPath = ROOT.'/config/routes.php';
    $this->routes = include($routesPath);
}
//метод возвращает строку
private function getURI () {
    if (!empty($_SERVER['REQUEST_URI'])) {
                  return trim($_SERVER['REQUEST_URI'], '/');
        }
}
public function run() {
 
    $uri = $this->getURI();
    
//проверить наличие такого запроса в routes.php
foreach ($this->routes as $uriPattern => $path) {
            
            //сравниваем $uriPattern и $uri
             if(preg_match("~$uriPattern~", $uri)) {
                                $internalRoute = preg_replace ("~$uriPattern~", $path, $uri);
                $segments = explode('/', $internalRoute);
                $controllerName = array_shift($segments).'Controller';
                $controllerName = ucfirst($controllerName);//первая буква строки заглавная
                $actionName = 'action'.ucfirst((array_shift($segments)));
 
                    $parameters = $segments;
 
                //подключить файл класса-контроллера
                $controllerFile = ROOT . '/controles/' .
                    $controllerName . '.php';
                    
                if (file_exists ($controllerFile)) {
                    include_once ($controllerFile);
                }
                
                $controllerObject = new $controllerName;
                
                $result = call_user_func_array (array($controllerObject, $actionName), $parameters);
                
                if ($result != null) {
                    break;
                }
                }
            }
        }
        }
NewsController.php:
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
 
include_once ROOT. '/models/News.php';
 
class NewsController {
    public function actionIndex()
        {
            $newsList = array();
            $newsList = News::getNewsList();
            
            require_once(ROOT. '/views/news/index.php');
            
            return true;
        }
    public function actionView($id)
    {
        if ($id) {
            $newsItem = News::getNewsItembyId($id);
            
            echo '<pre>';
            print_r($newsItem);
            echo '</pre>';
            
            echo 'actionView';
        }
        return true;
    }
        
}
News.php:
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?php
 
class News
{
        public static function getNewsItemById ($id)
        {
            $id = intval($id);
            
            if ($id) {
            $db = Db::getConnection();
 
            $result = $db->query('SELECT * FROM news WHERE id=' . $id);
            
            $result ->setFetchMode(PDO::FETCH_ASSOC);
            
            $newsItem = $result->fetch();
            
            return $newsItem;
            }
        }
        
        public static function getNewsList ()
        {
            $db = Db::getConnection();
            
            $newsList = array();
            
            $result = $db->query('SELECT id, title, date, short_content '
                . 'FROM news '
                . 'ORDER BY date DESC '
                . 'LIMIT 10 '); //количество выводимых превью новостей
            $i = 0;
            while($row = $result->fetch()) {
                $newsList [$i]['id'] = $row ['id'];
                $newsList [$i]['title'] = $row ['title'];
                $newsList [$i]['date'] = $row ['date'];
                $newsList [$i]['short_content'] = $row ['short_content'];
                $i++;
            }
            return $newsList;
        }
}
У меня несколько вопросов.
Сейчас открывается:
  • domain.ru/news
  • domain.ru/news/
  1. Как сделать, чтобы открывался ТОЛЬКО без слэша в конце?
Нужен вид domain.ru/news
Просто domain.ru открывается без слэша. Если слэш поставить, то перекидывает на domain.ru (т.е. без слэша).
  1. Как сделать адрес полного текста статьи не domain.ru/news/123, а domain.ru/news/horoshie-novosti?
Расширение .php в конце не должно быть.
  1. Как передавать код ответа сервера (404, 301 и т.д.)?

Буду благодарен советам и помощи.
Прошу сильно не пинать
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
16.11.2022, 17:32
Ответы с готовыми решениями:

Как получить код ответа сервера?
Есть какая нибудь функция, чтобы узнать код ответа? Типа даёшь урл, а он тебе возвращает 200, 404 и т.п.?

Как получить код ответа сервера?
Нужно получить заголовок страницы. Что-то вроде: -задаем url страницы - получаем &quot;200&quot; или &quot;301&quot; или...

Как с NodeJs или JavaScript получить код ответа сервера?
Есть какая нибудь функция, чтобы узнать код ответа? Типа даёшь урл, а он тебе возвращает 200, 404 и т.п.?

90
1306 / 998 / 232
Регистрация: 01.10.2018
Сообщений: 3,874
22.12.2022, 18:47
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от iiwanc Посмотреть сообщение
Получается, необходимо описать класс NotFoundException?
Да. И перехват исключения тоже нужно прописать. Лучше вне контроллера. Можно перехватывать все исключения, используя базовый тип Exception:
PHP
1
2
3
4
5
try
{
    // ...
}
catch (Exception $e) { error($e->getCode()); }
Добавлено через 3 минуты
Для генерации тоже можно использовать базовый тип, тогда другие классы описывать не нужно:
PHP
1
throw new Exception('Not Found', 404);
Добавлено через 2 минуты
Теории DDD пока можно не касаться Тем более что есть и другие.

Добавлено через 6 минут
Цитата Сообщение от estic Посмотреть сообщение
error($e->getCode());
"Расшифровку" ошибки (текстовое сообщение) тоже можно получать от источника исключения (из $e->getMessage()).
0
 Аватар для sad67man
2600 / 1504 / 689
Регистрация: 23.08.2015
Сообщений: 3,812
22.12.2022, 19:00
Цитата Сообщение от estic Посмотреть сообщение
Теории DDD пока можно не касаться Тем более что есть и другие.
Просто мне не нравятся флаги). И я попытался это хоть как-то обосновать)

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

Поэтому я бы не советовал использовать флаги в принципе. Либо с осторожностью и в очень редких случаях.
0
1306 / 998 / 232
Регистрация: 01.10.2018
Сообщений: 3,874
22.12.2022, 19:54
sad67man, насчет "хоть как-то" я понял. Как будто в интерфейсе нельзя использовать флаги или не может быть "двойственной" функции (метода)...

Добавлено через 6 минут
Я даже в прикладные API люблю добавлять "двойственные" функции. Чтобы пользователь прошел небольшой квест, прежде чем понять всю их мощь
0
 Аватар для sad67man
2600 / 1504 / 689
Регистрация: 23.08.2015
Сообщений: 3,812
22.12.2022, 20:47
Цитата Сообщение от estic Посмотреть сообщение
Как будто в интерфейсе нельзя использовать флаги или не может быть "двойственной" функции (метода)...
Получается, что метод делает одно, но если вы передали флаг = true, то нечто другое. По мне так двойственности быть не должно. Лучше разделить на 2 метода либо использовать другие способы.

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

Интерфейс служит для инверсии зависимости, и как правило он принадлежит тому классу, который его использует, а не тот который его реализует. И тот кто его использует по сути и диктует правила, какие параметры будут передаваться и что должно вернуться. С этой точки зрения для него нет смысла добавлять некие бессмысленные параметры.
0
1306 / 998 / 232
Регистрация: 01.10.2018
Сообщений: 3,874
22.12.2022, 23:36
Цитата Сообщение от sad67man Посмотреть сообщение
Получается, что метод делает одно, но если вы передали флаг = true, то нечто другое.
В том примере я предлагал неявно передавать true (в значении "генерировать ошибку"), но не суть.

Цитата Сообщение от sad67man Посмотреть сообщение
Получается что метод всегда может вернуть null, а это значит что мы не можем полагаться на передаваемый флаг и обязаны делать проверку...
Если метод возвращает null вопреки интерфейсу, то это ошибочная реализация (интерфейс в этом не виноват). Если флаг приходит "сверху", то и результат обычно передается "наверх" без проверки.
0
32 / 29 / 12
Регистрация: 04.03.2013
Сообщений: 895
28.12.2022, 15:29  [ТС]
estic, решил здесь написать, т.к. я все еще допиливаю роутинг
В файле Router.php прописал:
PHP
1
2
3
4
5
6
if (preg_match("#\b$uriPattern\b#i", $uri)){
   echo 'test';
}else {
   http_response_code(404);
   echo 'NEtest';
}
В файле контроллера:
PHP
1
2
3
4
5
6
7
8
9
10
public function actionView($ssylka)
{
   if ($ssylka) {
      $newsItem = News::getNewsItembyId($ssylka);
      if(! $newsItem = News::getNewsItembyId($ssylka)) {
         http_response_code(404);
         echo 'Новость не найдена';
}
}
}
В ссылках такого вида хорошо отрабатывает: domain.ru/news/horoshie-novosti
Если "пользователь" допишет адресную строк (пример: domain.ru/news/horoshie-novosti/user), то откроется белая страница и нет кода 404.

Как в таком случае вывести 404?
0
1306 / 998 / 232
Регистрация: 01.10.2018
Сообщений: 3,874
28.12.2022, 16:19
Цитата Сообщение от iiwanc Посмотреть сообщение
В ссылках такого вида хорошо отрабатывает: domain.ru/news/horoshie-novosti
Я вам в другой теме написал, что \b не заменяет в полной мере ^ и $ (и даже один контрпример привел: /bad/news/1).

Добавлено через 2 минуты
Цитата Сообщение от iiwanc Посмотреть сообщение
if ($ssylka) {


Цитата Сообщение от iiwanc Посмотреть сообщение
$newsItem = News::getNewsItembyId($ssylka);
if(! $newsItem = News::getNewsItembyId($ssylka))


Добавлено через 6 минут
По первому "почесыванию": если вы хотите проверить поступающий идентификатор на пустоту строки, делайте это явно, т.к. в PHP много чего приводится к bool false. И реакцию на некорректное значение нужно должным образом оформить.
PHP
1
if (strlen($id) == 0) fail(); // или strlen($id) > 0 or fail(); или strlen($id) == 0 and fail();
null, кстати, тоже приводится к пустой строке. Если для вас важно это различать, можно использовать $id === '' ($id !== '').
1
32 / 29 / 12
Регистрация: 04.03.2013
Сообщений: 895
28.12.2022, 16:24  [ТС]
Большое спасибо за разъяснения и терпение.
Многое стало понятно
0
1306 / 998 / 232
Регистрация: 01.10.2018
Сообщений: 3,874
28.12.2022, 16:44
Цитата Сообщение от iiwanc Посмотреть сообщение
Большое спасибо за разъяснения и терпение.
Не за что. Хотя "спасибки" получать всегда приятно

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

Добавлено через 4 минуты
Кстати, у числовых идентификаторов, состоящих только из цифр, еще могут быть подобные дубли: 01 Нужно использовать или более строгий шаблон (чтобы в начале числа не мог появиться ноль), или какие-то специальные техники.

Добавлено через 1 минуту
В моих сайтах с этим все в порядке: hyde.pageshop.ru/news/01
1
32 / 29 / 12
Регистрация: 04.03.2013
Сообщений: 895
29.12.2022, 13:18  [ТС]
estic, наконец-то я столкнулся с подключением стилей
Ранее в своих HTML файлах делал так:
HTML5
1
<link rel="stylesheet" type="text/css" href="style/style.css">
А теперь как нужно делать?
В интернете не смог найти понятную для себя информацию
0
1306 / 998 / 232
Регистрация: 01.10.2018
Сообщений: 3,874
29.12.2022, 15:56
Цитата Сообщение от iiwanc Посмотреть сообщение
А теперь как нужно делать?
Это к маршрутизации не относится

Я вам давал ссылку на шаблон. Или baseurl используете (конфигурационный параметр приложения или обычную константу), или просто на ветвь текущего хоста со статическими файлами ссылаетесь: /assets/... - обратите внимание на первый слэш, это важно.

Добавлено через 3 минуты
Проблема с расположением файлов относительно index.php

Добавлено через 5 минут
Если боитесь случайно повторно задействовать эту ветвь для динамического содержимого, можно сразу создать какой-нибудь блокирующий маршрут для /assets/...

Добавлено через 4 минуты
Лишних каталогов в корне лучше не создавать, чтобы меньше "блокировать" и провоцировать подобные потенциальные конфликты. В моих CMS, если статические файлы размещаются на том же хосте, обычно используются assets (или аналог), images для графических файлов, относящихся к основному содержимому, и files для всех прочих типов файлов, относящихся к основному содержимому. По аналогии с images в общем-то можно создавать videos и т.п. Если используется файловый кэш, в корне может быть и cache, но не обязательно (если кэш читает непосредственно код приложения, он вполне может это сделать из каталога вне корня).

На блокирующие маршруты при необходимости можно "навесить" и полезную функциональность, например генерацию статических файлов "по первому запросу", вывод "несуществующих" файлов и т.п. Примером вывода "несуществующего" файла может быть вывод atom.xml на демонстрационном сайте, который я показывал: hyde.pageshop.ru/atom.xml (код вывода содержимого этого файла есть в упомянутом шаблоне). Кстати, для файлов, расположенных непосредственно в корневом каталоге, тоже могут понадобиться блокирующие маршруты, если вы боитесь потери вывода одноименных динамических страниц из-за приоритета статических файлов.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
29.12.2022, 15:56
Помогаю со студенческими работами здесь

Как узнать статус код ответа сервера WebRequest и WebResponse?
Здрасте! Такой вопросец нагрянул, надо написать функцию обращения к серверу и получения ответа, но если статус код не 200, а например 404...

Как получить и вывести код ответа сервера при запросах по протоколу HTTP?
Всем привет! Cкажите, плиз, как получить и вывести код ответа сервера при запросах по протоколу HTTP на языке программирования HTML,...

Как отдавать файлы с сервера по запросу?
Здравствуйте! Непосредственно к вопросу: я научился загружать файлы на сервер через POST запрос достаю через request.FILES и...

Парсинг ответа от php сервера
как привести строку вида object(stdClass)#2 (1) { =&gt; object(stdClass)#3 (1) { =&gt; array(42) { =&gt; object(stdClass)#4 (2) { =&gt; string(0)...

Код ответа от сервера
В двух словах нужно на C# сделалать прогу для анализа битых ссылок. Для уточнения битые ссылки будут проверяться только для скачивания...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
91
Ответ Создать тему
Новые блоги и статьи
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка. Рецензия / Мнение Это мой обзор планшета X220 с точки зрения школьника. Недавно я решила попытаться уменьшить свой. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru