Я делаю инструментарий для приложений php. Я создал систему маршрутизации, основанную на некоторых соглашениях, она работает хорошо, но я хотел бы узнать, как сделать mod_rewrite правила или любые другие вещи, чтобы наконец сделать url хорошо видеть и хорошо для seo.
Система маршрутов начинается с файла конфигурации, который устанавливает корни приложения и URL-адреса.
$app_root = $_SERVER["DOCUMENT_ROOT"].dirname($_SERVER["PHP_SELF"])."/"; $app_url = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/'; define("APP_URL",$app_url); define("APP_ROOT",$app_root);
Маршрут всегда начинается с index.php, который делает экземпляры контроллеров @ действиями из контроллеров параметров GET =? & Action =?
Это index.php
<?php include_once 'controller/Frontend.php'; require 'libraries/Router.php'; $params=array(); if(isset($_GET['controller'])&&isset($_GET['action'])){ $c = $_GET['controller']; $a = $_GET['action']; // add all query string additional params to method signature ie &id=x&category=y $queryParams = array_keys($_GET); $queryValues = array_values($_GET); for ($i=2;$i<count($queryParams);$i++) { $params[$queryParams[$i]] = $queryValues[$i]; } if ($_POST) { // add all query string additional params to method signature ie &id=x&category=y $queryParams = array_keys($_POST); $queryValues = array_values($_POST); for ($i=0;$i<count($_POST);$i++) { $params[$queryParams[$i]] = $queryValues[$i]; } } include_once APP_ROOT."/controller/$c.php"; $controller = new $c(); $controller->$a($params); } else { //attiva controller predefinito $controller = new Frontend(); $controller->index(); }
Это позволяет выбрать, какой контроллер и какие действия должен выполнять маршрутизатор.
Здесь функция маршрутизатора получает URL-адрес APP из файла settings.php в корневом каталоге. Вы даете им два параметра управления action-action как строку, и он делает URL следующим образом: index.php? Controller = X & action = Y & [params …]
<?php
require './settings.php';
function router($controller,$action,$query_data="") { $param = is_array($query_data) ? http_build_query($query_data) : "$query_data"; $url = APP_URL."index.php?controller=$controller&action=$action&$param"; return $url; } function relativeRouter ($controller,$action,$query_data=""){ $param = is_array($query_data) ? http_build_query($query_data) : "$query_data"; $url = "index.php?controller=$controller&action=$action&$param"; return $url; } function redirectToOriginalUrl() { $url = $_SERVER['HTTP_REQUEST_URI']; header("location: $url"); } function switchAction ($controller, $action) { $r = router($controller, $action); header("location:$r", true, 302); }
В файле шаблонов я вызываю маршрутизатор («контроллер», «действие»), чтобы извлечь URL-адреса для действий, а также передать данные GET / POST (собранные из index.php, которые помещают их в подпись метода как массив).
Не обвиняйте меня в том, что вы используете глобальный POST / GET без фильтрации, я все еще разрабатываю вещь, вещи безопасности будут сделаны после;)
Что я хотел бы спросить, может ли кто-нибудь поделиться некоторыми мыслями о том, как сделать довольно URL-адреса, такие как site / page / action … Например, www.site.com/blog/post?id=1
(На самом деле N параметров в функции маршрутизатора ($ query_data) работает таким образом, вы передаете массив ['id' => '1'], и вы получаете? Id = 1)
Каковы наилучшие стратегии для создания хороших URL-адресов? Большое вам спасибо, все еще изучая PHP.
Если есть лучший способ сделать такие вещи, просто дайте свои отзывы.
Я нашел ответ на вопрос, я могу написать здесь, может быть, это полезно.
Я добавил файл .htaccess в корневой каталог:
Options -MultiViews RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.php [QSA,L]
Это вернет каждый запрос в файл root / index.php.
Файл индекса собирает маршруты из HTTP-запроса, проверяет, существует ли маршрут в файле «routes.json».
URL-адрес написан таким образом: site.com/controller/action. Параметры GET записываются следующим образом: site.com/controller/action/[params] / [value] …… Этот вывод, например, site.com/blog/post/id/1 Это тоже отлично подходит для REST.
Здесь index.php
<?php require 'controller/Frontend.php'; require 'Class/Router.php'; //require 'libraries/Router.php'; /* * ** ROUTING SETTINGS ** */ $app_root = $_SERVER["DOCUMENT_ROOT"].dirname($_SERVER["PHP_SELF"])."/"; $app_url = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/'; define("APP_URL",$app_url); define("APP_ROOT",$app_root); $basepath = implode('/', array_slice(explode('/', $_SERVER['SCRIPT_NAME']), 0, -1)); $uri = substr($_SERVER['REQUEST_URI'], strlen($basepath)); //echo $uri; if ($uri == "/") { $frontend = new Frontend(); $frontend->index(); } else { $root = ltrim ($uri, '/'); //$paths = explode("/", $uri); $paths = parse_url($root, PHP_URL_PATH); $route = explode("/",$paths); $request = new \PlayPhp\Classes\Request(); // controller $c = $route[0]; // action $a = $route[1]; $reverse = Router::inverseRoute($c,$a); $rest = $_SERVER['REQUEST_METHOD']; switch ($rest) { case 'PUT': //rest_put($request); break; case 'POST': if (Router::checkRoutes($reverse, "POST")) { foreach ($_POST as $name => $value) { $request->setPost($name,$value); } break; } else { Router::notFound($reverse,"POST"); } case 'GET': if (Router::checkRoutes($reverse, "GET")) { for ($i = 2; $i < count($route); $i++) { $request->setGet($route[$i], $route[++$i]); } break; } else { Router::notFound($reverse,"GET"); } break; case 'HEAD': //rest_head($request); break; case 'DELETE': //rest_delete($request); break; case 'OPTIONS': //rest_options($request); break; default: //rest_error($request); break; } include_once APP_ROOT.'controller/'.$c.'.php'; $controller = new $c(); $controller->$a($request); }
Класс маршрутизатора:
<?php include 'config/app.php'; /* * Copyright (C) 2015 yuri.blanc */ require 'Class/http/Request.php'; class Router { protected static $routes; private function __construct() { Router::$routes = json_decode(file_get_contents(APP_ROOT.'config/routes.json')); } public static function getInstance(){ if (Router::$routes==null) { new Router(); } return Router::$routes; } public static function go($action,$params=null) { $actions = explode("@", $action); $c = strtolower($actions[0]); $a = strtolower($actions[1]); // set query sting to null $queryString = null; if(isset($params)) { foreach ($params as $name => $value) { $queryString .= '/'.$name.'//'.$value; } return APP_URL."$c/$a$queryString"; } return APP_URL."$c/$a"; } public static function checkRoutes($action,$method){ foreach (Router::getInstance()->routes as $valid) { /* echo $valid->action . ' == ' . $action . '
'; echo $valid->method . ' == ' . $method . '
';*/ if ($valid->method == $method && $valid->action == $action) { return true; } } } public static function inverseRoute($controller,$action) { return ucfirst($controller)."@".$action; } public static function notFound($action,$method) { die("Route not found:: $action with method $method"); } }
Я использую функцию json_decode для синтаксического анализа объекта json в stdClass ().
Файл json выглядит следующим образом:
{"routes":[ {"action":"Frontend@index", "method":"GET"}, {"action":"Frontend@register", "method":"GET"}, {"action":"Frontend@blog", "method":"GET"} ]}
Таким образом, я могу белить списки маршрутов с помощью своих методов и возвращать 404 ошибки, пока их не найти.
Система все еще довольно простая, но дает и идеи и работы, надеюсь, что кто-то найдет полезной.