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

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

16.11.2022, 17:32. Показов 6738. Ответов 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
 Аватар для sad67man
2600 / 1504 / 689
Регистрация: 23.08.2015
Сообщений: 3,812
16.11.2022, 19:54
Цитата Сообщение от iiwanc Посмотреть сообщение
Как сделать, чтобы открывался ТОЛЬКО без слэша в конце?
Можно через htaccess

Code
1
2
RewriteCond %{REQUEST_URI} ^(.*)/$
RewriteRule ^(.*)/$  /$1 [R=302,L]
Можно программно

PHP
1
2
3
4
5
6
7
8
9
10
11
$url_parts = parse_url($_SERVER['REQUEST_URI']);
 
if (rtrim($url_parts['path'], '/') !== $url_parts['path']) {
    $redirect_url = rtrim($url_parts['path'], '/');
    if (!empty($url_parts['query'])) {
        $redirect_url .= '?' . $url_parts['query'];
    }
    http_response_code(301);
    header('Location: ' . $redirect_url);
    exit();
}
Цитата Сообщение от iiwanc Посмотреть сообщение
Как передавать код ответа сервера (404, 301 и т.д.)?
Отдавать статус через функцию
PHP
1
http_response_code(201);
Цитата Сообщение от iiwanc Посмотреть сообщение
Как сделать адрес полного текста статьи не domain.ru/news/123, а domain.ru/news/horoshie-novosti?
В базе данных создаете специальное поле slug и достаете по нему, а не по id.
1
32 / 29 / 12
Регистрация: 04.03.2013
Сообщений: 895
16.11.2022, 20:05  [ТС]
Большое спасибо за помощь.
Цитата Сообщение от sad67man Посмотреть сообщение
В базе данных создаете специальное поле slug и достаете по нему, а не по id.
Что должно быть в этом поле?
0
 Аватар для sad67man
2600 / 1504 / 689
Регистрация: 23.08.2015
Сообщений: 3,812
16.11.2022, 20:14
Цитата Сообщение от iiwanc Посмотреть сообщение
Что должно быть в этом поле?
Таблица news

Code
1
2
3
4
id | slug               | title          
------------------------------------------
1  | horoshie-novosti   | Хорошие новости
2  | plohie-novosti     | Плохие новости
0
32 / 29 / 12
Регистрация: 04.03.2013
Сообщений: 895
16.11.2022, 20:18  [ТС]
sad67man, подтвердили мои догадки Буду пробовать
0
1306 / 998 / 232
Регистрация: 01.10.2018
Сообщений: 3,874
16.11.2022, 23:56
Цитата Сообщение от iiwanc Посмотреть сообщение
Роуминг


Раз разбираете REQUEST_URI, что правильно, преобразовывать путь в параметр route не нужно.

Функция parse_url не предназначена для разбора REQUEST_URI (легко "обмануть", например //path, или даже вызвать фатальную ошибку). Или используйте более подходящие и простые методы, или хотя бы предварительно приводите значение в порядок вплоть до использования фильтра, выполняющего переадресацию на подобный адрес, но без нескольких подряд идущих слэшей.

Цитата Сообщение от iiwanc Посмотреть сообщение
подтвердили мои догадки
Я вам давал дамп таблицы, в которой присутствуют символьные идентификаторы. А вы все в догадках

Добавлено через 1 минуту
Скрипт управления контентом

Добавлено через 5 минут
Цитата Сообщение от iiwanc Посмотреть сообщение
'SELECT id, title, date, short_content '
. 'FROM news '
. 'ORDER BY date DESC '
. 'LIMIT 10 '
Можно обойтись без подобных "изысков". Строки PHP в тексте скрипта позволяют использовать "переносы строк" (без каких-либо специальных знаков).

Добавлено через 1 минуту
MySQL тоже позволяет.

Добавлено через 6 минут
Цитата Сообщение от iiwanc Посмотреть сообщение
$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++;
}
PHP
1
$newsList[$i] = $row;
А когда вы инициализируете переменную массива перед циклом, можно просто $newsList[].

И про fetchAll не забываем.
1
32 / 29 / 12
Регистрация: 04.03.2013
Сообщений: 895
18.11.2022, 07:33  [ТС]
Цитата Сообщение от estic Посмотреть сообщение
Я вам давал дамп таблицы, в которой присутствуют символьные идентификаторы. А вы все в догадках
Благодаря вашей таблицы у меня появились догадки
Спасибо за советы. Изучаю.
0
32 / 29 / 12
Регистрация: 04.03.2013
Сообщений: 895
18.11.2022, 18:28  [ТС]
Отредактировал 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
<?php
 
class News
{
        //полный текст статьи
        public static function getNewsItemById ($ssylka)
        {
            $ssylka = intval($ssylka);
            
            if ($ssylka) {
            $db = Db::getConnection();
 
            $result = $db->query('SELECT * FROM news WHERE ssylka=' . $ssylka);
            
            $result ->setFetchMode(PDO::FETCH_ASSOC);
            
            $newsItem = $result->fetch();
            
            return $newsItem;
            }
        }
        
        //список всех новостей
        public static function getNewsList ()
        {
            $db = Db::getConnection();
            
            $newsList = array();
            
            $result = $db->query('SELECT ssylka, title, date, short_content '
                . 'FROM news '
                . 'ORDER BY date DESC '
                . 'LIMIT 10 '); //количество выводимых превью новостей
            //$i = 0;
            while($row = $result->fetch()) {
                $newsList[] = $row;
            }
            return $newsList;
        }
}
routes.php
PHP
1
2
3
4
5
6
<?php
return array(
'news/([a-z]+)' => 'news/view/$1',
'news' => 'news/index', // actionIndex in NewsController
 
);
ssylka - это поле в БД, которые содержит данные вида:
horoshie-novosti

Список всех новостей выводит, но полный текст статьи не хочет. Пустой лист.

Дело в типах данных?
Какой тип данных в моем случае задать полю "ssylka" в моей БД?
В коде тоже нужно что-то исправить?
0
 Аватар для sad67man
2600 / 1504 / 689
Регистрация: 23.08.2015
Сообщений: 3,812
18.11.2022, 18:42
iiwanc,
Цитата Сообщение от iiwanc Посмотреть сообщение
PHP
1
$ssylka = intval($ssylka);
Вы приводите значение к числу, поэтому и не находит новость.

Цитата Сообщение от iiwanc Посмотреть сообщение
$result = $db->query('SELECT * FROM news WHERE ssylka=' . $ssylka);
Лучше используйте подготовленные запросы, чтоб не было SQL-инъекций

Добавлено через 3 минуты
iiwanc, И метод тогда будет называться не getNewsItemById, а getBySsylka - не нужно уточнять getNewsBySsylka, это и так по контексту понятно, что метод вызывается из класса News

Лучше все-таки использовать английские названия.
0
1306 / 998 / 232
Регистрация: 01.10.2018
Сообщений: 3,874
18.11.2022, 18:44
Цитата Сообщение от iiwanc Посмотреть сообщение
Какой тип данных в моем случае задать полю "ssylka" в моей БД?
Дамп таблицы в том числе содержит запрос для ее создания, т.е. полное определение Или внимательно посмотрите на скриншот в сообщении по ссылке выше.

Также учтите, что поле должно иметь уникальный индекс (или быть первичным ключом).
0
 Аватар для sad67man
2600 / 1504 / 689
Регистрация: 23.08.2015
Сообщений: 3,812
18.11.2022, 18:49
Цитата Сообщение от iiwanc Посмотреть сообщение
PHP
1
$result ->setFetchMode(PDO::FETCH_ASSOC);
FetchMode можно установить глобально при подключении к БД

PHP
1
2
3
4
$pdo = new PDO($dsn, $user, $password, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
0
1306 / 998 / 232
Регистрация: 01.10.2018
Сообщений: 3,874
18.11.2022, 18:58
Для выбора по символьному идентификатору вместо подготовленного запроса можно использовать проверку символов, из которых состоит поступивший идентификатор. Набор символов сильно ограничен. Можно и коды %XX исключить, т.е. символ %

Добавлено через 5 минут
Латинские буквы (можно только в нижнем регистре), цифры, точка, дефис, подчеркивание, тильда. Для "составных" можно еще слэш добавить.
0
 Аватар для sad67man
2600 / 1504 / 689
Регистрация: 23.08.2015
Сообщений: 3,812
18.11.2022, 19:00
Цитата Сообщение от estic Посмотреть сообщение
Для выбора по символьному идентификатору вместо подготовленного запроса можно использовать проверку символов
Можно, но зачем? Проверку символов нужно, если создаете/редактируете новость.
Если введут в адресную строку что-то не то, то у нас не найдется статья и отдадим 404. Нам не нужно думать, какие там могут быть символы.
0
1306 / 998 / 232
Регистрация: 01.10.2018
Сообщений: 3,874
18.11.2022, 19:16
К предыдущему сообщению. Оптимизированное множество для регулярного выражения: [--9_a-z~] (это вместе со слэшем).

Добавлено через 7 минут
Цитата Сообщение от sad67man Посмотреть сообщение
Можно, но зачем?
Цитата Сообщение от sad67man Посмотреть сообщение
Если введут в адресную строку что-то не то, то у нас не найдется статья и отдадим 404.
Чтобы напрасно запрос не делать при наличии "мусора" в адресе. К тому же запросы с использованием подготовленных выражений более ресурсоемкие для простых SELECT-ов. Здесь может быть только одна проблема - слишком длинная строка на входе, даже с учетом ограничений сервера.
0
 Аватар для sad67man
2600 / 1504 / 689
Регистрация: 23.08.2015
Сообщений: 3,812
18.11.2022, 19:24
Цитата Сообщение от estic Посмотреть сообщение
Чтобы напрасно запрос не делать при наличии "мусора" в адресе. Запросы с использованием подготовленных выражений более ресурсоемкие для простых SELECT-ов. Здесь может быть только одна проблема - слишком длинная строка на входе, даже с учетом ограничений сервера.
Это лишнее усложнение, особенно когда еще нет инцидентов. Не такие уж они и ресурсоемкие. Пожалейте автора темы)
0
1306 / 998 / 232
Регистрация: 01.10.2018
Сообщений: 3,874
18.11.2022, 19:27
Но автор все равно использует регулярное выражение с допустимыми символами в шаблоне маршрута. Я просто уточнил множество допустимых символов. Может пригодиться.
0
32 / 29 / 12
Регистрация: 04.03.2013
Сообщений: 895
18.11.2022, 19:28  [ТС]
Цитата Сообщение от sad67man Посмотреть сообщение
$ssylka = intval($ssylka);
Вы приводите значение к числу, поэтому и не находит новость.
Какое лучше значение тогда поставить?
Пробую strval - не работает.
Или тут замена не проходит?
Нужно немного код переписать?
0
32 / 29 / 12
Регистрация: 04.03.2013
Сообщений: 895
18.11.2022, 19:30  [ТС]
Структура таблицы
Миниатюры
Роуминг PHP: Как сделать редиректы и отдавать код ответа сервера?  
0
 Аватар для sad67man
2600 / 1504 / 689
Регистрация: 23.08.2015
Сообщений: 3,812
18.11.2022, 19:37
Цитата Сообщение от estic Посмотреть сообщение
Но автор все равно использует регулярное выражение с допустимыми символами в шаблоне маршрута. Я просто уточнил множество допустимых символов. Может пригодиться.
Я вас понял, это вторая причина, почему новость может не найтись)

Добавлено через 3 минуты
Цитата Сообщение от iiwanc Посмотреть сообщение
Пробую strval - не работает.
Цитата Сообщение от iiwanc Посмотреть сообщение
PHP
1
2
3
4
5
<?php
return array(
    'news/([a-z]+)' => 'news/view/$1',
    'news' => 'news/index', // actionIndex in NewsController
);
Тут смотрите в регулярке допускаете только латинские буквы, нужно еще тире добавить.

PHP
1
2
3
4
return array(
    'news/([-a-z]+)' => 'news/view/$1',
    'news' => 'news/index', // actionIndex in NewsController
);
0
1306 / 998 / 232
Регистрация: 01.10.2018
Сообщений: 3,874
18.11.2022, 19:41
Цитата Сообщение от iiwanc Посмотреть сообщение
Структура таблицы
ssylka - это то, что делает тег A Здесь у нас символьный идентификатор (слаг).

Тут смотрите в регулярке допускаете только латинские буквы, нужно еще тире добавить.
Да. В регулярных выражениях дефис нужно добавлять или в самом начале множества, или в самом конце.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
18.11.2022, 19:41
Помогаю со студенческими работами здесь

Как узнать статус код ответа сервера 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# сделалать прогу для анализа битых ссылок. Для уточнения битые ссылки будут проверяться только для скачивания...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
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