【问题标题】:CSS problems with custom Router - PHP自定义路由器的 CSS 问题 - PHP
【发布时间】:2016-07-06 16:44:45
【问题描述】:

我正在为我的网络应用程序创建一个自定义路由器。 我使用 MVC。

例如,当我输入 fab.app/portfolio 时,一切都很好。 但是当我输入fab.app/portfolio/时,css、图片和js都没有显示出来。

这是因为路径发生了变化。在第一种情况下,它正在寻找图像的路径是fab.app/images/(the_image),但在第二种情况下,它是fab.app/portfolio/images/(the_image)。

此外,在 index.php 中,我必须在结尾处为带有和不带有斜杠的 url 输入一个条目。我不喜欢。我更喜欢不带斜线写它,它也应该与斜线一起使用。

你可以在下面找到路由器和index.php


index.php

<?php
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/../app/setup.php';

use Fab\Controllers;
use Fab\Router;

$router = new Router\Router();

$router->get('/', 'MainController', 'index');
$router->get('/portfolio', 'ItemsController', 'showAllItems');
$router->get('/portfolio/', 'ItemsController', 'showAllItems');
$router->get('/portfolio/[\w\d]+', 'ItemsController', 'single_item');
$router->get('/about', 'MainController', 'about');
$router->get('/contact', 'MainController', 'contact');
$router->get('/admin/dashboard', 'AdminController', 'index');
$router->get('/admin/dashboard/addItem', 'AdminController', 'addItem');
$router->get('/admin/dashboard/deleteItem', 'AdminController', 'deleteItem');
$router->get('/admin/dashboard/editItem', 'AdminController', 'editItem');
$router->get('/admin/dashboard/contactSupport', 'AdminController', 'contactSupport');

$router->post('/admin/addItem', 'AdminController', 'postAddItem');
$router->post('/admin/deleteItem', 'AdminController', 'postDeleteItem');
$router->post('/admin/editItem', 'AdminController', 'postEditItem');

//$router->get('/test', 'ItemsController', 'showAllItems');

////See inside $router
//echo "<pre>";
//print_r($router);

$router->submit();

路由器.php

<?php
/**
 * Created by PhpStorm.
 * User: antony
 * Date: 5/30/16
 * Time: 3:31 PM
 */
namespace Fab\Router;

class Router
{
    private $_getUri = array();
    private $_getController = array();
    private $_getMethod = array();
    private $_postUri = array();
    private $_postController = array();
    private $_postMethod = array();

    public function __construct()
    {
    }

    /**
     * Build a collection of internal GET URLs to look for
     * @param $uri - The url that the user types in the browser
     * @param $controller - The controller that will handle the url
     * @param $method - The method of the controller that will run
     */
    public function get($uri, $controller, $method)
    {
        $this->_getUri[] = $uri;
        $this->_getController[] = $controller;
        $this->_getMethod[] = $method;
    }

    /**
     * Build a collection of internal POST URLs to look for
     * @param $uri - The url that the user types in the browser
     * @param $controller - The controller that will handle the url
     * @param $method - The method of the controller that will run
     */
    public function post($uri, $controller, $method)
    {
        $this->_postUri[] = $uri;
        $this->_postController[] = $controller;
        $this->_postMethod[] = $method;
    }

    public function submit()
    {
        $found = 0;

        if ($_SERVER['REQUEST_METHOD'] === 'GET') {

            $path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); //get the url

            //Map URL to page
            foreach ($this->_getUri as $key => $value)
            {
                if ( $found = preg_match("#^$value$#", $path) )
                {
//                    echo $key . ' => ' . $value; //See what the $path returns

                    //Find parameter if passed
                    $parts = explode('/', $path);
                    count($parts) > 2 ? $parameter=$parts[2] : $parameter=null;

                    //Instantiate Controller
                    $controller = 'Fab\Controllers\\' . $this->_getController[$key];
                    $controller = new $controller($parameter);

                    //Call the appropriate method
                    $method = $this->_getMethod[$key];
                    $controller->$method();

                    break;
                }
            }

            //Show 404 page
            if ( $found == 0 )
            {
                //Instantiate Controller
                $controller = 'Fab\Controllers\MainController';
                $controller = new $controller();

                //Call the appropriate method
                $method = 'error404';
                $controller->$method();

                die();
            }

        } elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {

            $path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); //get the url

            foreach ($this->_postUri as $key => $value)
            {
                if ( $found = preg_match("#^$value$#", $path))
                {
//                    echo $key . ' => ' . $value; //See what the $path returns

                    //Find parameter if passed
                    $parts = explode('/', $path);
                    count($parts) > 2 ? $parameter=$parts[2] : $parameter=null;

                    //Instantiate Controller
                    $controller = 'Fab\Controllers\\' . $this->_postController[$key];
                    $controller = new $controller($parameter);

                    //Call the appropriate method
                    $method = $this->_postMethod[$key];
                    $controller->$method();

                    break;
                }
            }

            //Show 404 page
            if ( $found == 0 )
            {
                //Instantiate Controller
                $controller = 'Fab\Controllers\MainController';
                $controller = new $controller();

                //Call the appropriate method
                $method = 'error404';
                $controller->$method();

                die();
            }
        }

    }

}

.htaccess

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>

    RewriteEngine On

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)/$ /$1 [L,R=301]

    # Handle Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    AddType 'text/css; charset=UTF-8' css

</IfModule>

在html中调用css(也包括图片和js)的例子

&lt;link href="/css/my-admin-custom.css" rel="stylesheet"&gt;

----------------------------------------------- --------------------

为了清楚起见,这是我解决问题的方法(根据@Max13 的回答)。 这进入Router.php:

        /**
         * If last char in URL is '/' redirect without it 
         * and also check if url is root '/' because this would result 
         * in infinite loop
         */
        if ( ($path[strlen($path)-1] === '/') && !($path === '/') ) { //
            $newPath = substr($path, 0, -1);
            header("Location: $newPath", true, 302);
            exit;
        }

【问题讨论】:

  • 在不接触路由器的情况下,您只需在标题中添加base href 标签即可解决此问题。
  • 你没有常量或任何帮助存储诸如公共路径、应用程序目录路径之类的东西吗?
  • @Max13 我更新了问题。见最后一行
  • @mistermartin 这可以工作,但我不太喜欢。我更喜欢相对网址。
  • @chay22 不,我不喜欢相对网址

标签: php model-view-controller routing routes custom-routes


【解决方案1】:

带有和不带有斜杠并不意味着相同的目录级别,因此我认为在您的路由器中“接受”两者并不是一个好主意。

因此,恕我直言,一个好的解决方案是:在您检查期间,如果 path 以“/”结尾,则发送一个不带斜杠的 302 Found 标头。

-- 编辑 --

见(对于header重定向和meta标签重定向,经常同时使用):https://www.arclab.com/en/websitelinkanalyzer/http-and-meta-redirects.html

【讨论】:

  • @padawanTony 太好了。我敢肯定这对 95% 的情况来说已经足够了。我已经用链接更新了答案。我不知道是否有必要,但请查看添加的额外标头和元重定向。有时已知框架会同时添加(标题和元标记)
  • @padawanTony 别忘了告诉我们进展如何
  • 我仍然使用我们找到的解决方案(我的问题的最后一部分有代码)。不太喜欢元标记解决方案。感谢您的帮助。
  • @padawanTony 我并没有建议多种解决方案,只是我经常看到标头重定向 关联 与元重定向,以防标头被忽略。无论如何,如果它有效......我无话可说;-)
猜你喜欢
  • 2016-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多