我正在尝试建立用户可以使用WYSIWYG编辑器发布内容的网站。在我的.htaccess文件中我有
FallbackResource index.php
成功将所有请求发送到index.php文件。然后我使用PHP来获取所需的文件
$path = explode('/', $_SERVER['REQUEST_URI']);
//[SCRIPT_FILENAME] => C:/xampp/htdocs/tests/index.php
if($path[2] == 'notifications'){
require_once 'notifications.php';
}
这一切都很好。当我尝试重定向到google.com等外部链接时出现问题。链接本身被重定向到索引页面而不是被重定向。 这是关键,因为用户可以使用WYSIWYG编辑器在其文本中插入其他网站的标记作为参考。所以我的问题是,我这样做是对吗还是我需要一种不同的方法?如果是的话,采用哪种方法?我非常感谢facebook或twitter等网站使用的类似方法。
答案 0 :(得分:0)
AS的方法我将使用类似于CodeIgniter或其他MVC框架的方法(但更简单)。
首先你必须设计一个模式,我的意思是这样的
www.yoursite.com/index.php/{controller}/{method}/args ...
然后你会构建一个路由器去解析url。我可以给你写一个,但这需要一分钟。
更新
您可以在我的github页面here
上找到它但是对于参考,这里是代码:
SimpleRouter.php
/**
* A simple 1 level router
*
* URL schema is http://example.com/{controller}/{method}/{args ... }
*
* @author ArtisticPhoenix
* @package SimpleRouter
*/
class SimpleRouter{
/**
* should be the same as rewrite base in .htaccess
* @var string
*/
const REWRITE_BASE = '/MISC/Router/';
/**
* path to controller files
*
* @var string
*/
const CONTOLLER_PATH = __DIR__.'/Controllers/';
/**
* route a url to a controller
*/
public static function route(){
//normalize
if(self::REWRITE_BASE != '/'){
$uri = preg_replace('~^'.self::REWRITE_BASE.'~i', '',$_SERVER['REQUEST_URI']);
}
$uri = preg_replace('~^index\.php~i', '',$uri);
$uri = trim($uri,'/');
//empty url, like www.example.com
if(empty($uri)) $uri = 'home/index';
//empty method like www.example.com/home
if(!substr_count($uri, '/')) $uri .= '/index';
$arrPath = explode('/', $uri);
$contollerName = array_shift($arrPath);
$methodName = array_shift($arrPath);;
$contollerFile = self::CONTOLLER_PATH.$contollerName.'.php';
if(!file_exists($contollerFile)){
//send to error page
self::error404($uri);
return;
}
require_once $contollerFile;
if(!class_exists($contollerName)){
self::error404($uri);
return;
}
$Controller = new $contollerName();
if(!method_exists($Controller, $methodName)){
self::error404($uri);
return;
}
if(!count($arrPath)){
call_user_func([$Controller, $methodName]);
}else{
call_user_func_array([$Controller, $methodName], $arrPath);
}
}
/**
* call error 404
*
* @param string $uri
*/
protected static function error404($uri){
require_once self::CONTOLLER_PATH.'home.php';
$Controller = new home();
$Controller->error404($uri);
}
}
默认控制器home.php
/**
*
* The default controller
*
* @author ArtisticPhoenix
* @package SimpleRouter
*/
class home{
public function index($arg=false){
echo "<h3>".__METHOD__."</h3>";
echo "<pre>";
print_r(func_get_args());
}
public function otherpage($arg){
echo "<h3>".__METHOD__."</h3>";
echo "<pre>";
print_r(func_get_args());
}
public function error404($uri){
header('HTTP/1.0 404 Not Found');
echo "<h3>Error 404 page {$uri} not found</h3>";
}
}
第二控制器(示例)user.php
/**
*
* An example users router
*
* @author ArtisticPhoenix
* @package SimpleRouter
*/
class user{
public function index(){
echo "<h3>".__METHOD__."</h3>";
}
public function login(){
echo "<h3>".__METHOD__."</h3>";
}
}
重写(删除index.php).htaccess
RewriteEngine On
# For sub-foder installs set your RewriteBase including trailing and leading slashes
# your rewrite base will vary, possibly even being / if no sub-foder are involved
RewriteBase /MISC/Router/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
最后是index.php
require_once __DIR__.'/SimpleRouter.php';
SimpleRouter::route();
我对路由器进行static
调用只是为了简单起见,这样就不需要只有2个方法(1个公共)的类的实例。
我将它构建为单级路由器,我的意思是你不能将控制器放在子文件夹中,例如Controllers/user/home.php
而不是Controllers/user.php
。对于中小型站点,这应该没问题,但对于不同的大型站点,可能需要嵌套控制器。然而,这增加了一堆复杂性。
这种方式的优势应该是显而易见的,而不是单独创建路线。只要路径(网址)遵循我概述的简单模式,您就不必触摸代码。这还允许您按功能在自己的文件中组织站点的各个部分。例如,取user.php
控制器。是否允许您将所有功能放在一个位置,例如登录,配置文件,注销页面等......
如果您要添加member.php
控制器,您可以将您想要显示的所有内容放入登录用户。然后在该控制器的__construct
方法中检查当前会话是否已登录,并且它涵盖了该文件的所有方法。
网址架构是http://example.com/{controller}/{method}/{args ... }
。但您也可以使用此http://example.com/index.php/{controller}/{method}/{args ... }
这样的网址。我正在使用Mod Rewrite来删除URL中的index.php
,所以如果你没有,那么你必须将index.php
放在URL中(或者将其删除意味着)
REWRITE_BASE 在我的本地测试服务器上,我只是将所有内容放在自己的文件夹中,因为我懒得设置虚拟主机。因此,您希望更改此常量,并将匹配的.htaccess值设置为您的子文件夹(可能没有)。我只是把它留在这里,例如如何在子文件夹中使用它。
最后,这是传统MVC架构中的C
。您应该避免在控制器中执行所谓的“业务逻辑”,您还应该避免直接从控制器输出HTML(尽管我在示例中这样做了)。我建议使用像Blade
或Twig
这样的模板引擎,而不是输出HTML,这些引擎可以免费提供。想象一个控制器就像“胶水”一样,将“模型(业务逻辑)”加入到“视图(模板)”中。业务逻辑就像User类(大写U像名词,而不是我们的用户控制器中的小写),为用户处理数据库功能。因此,不是将该代码放在Controller中,而是构建一个“用户模型”并将其导入控制器。这是做到这一点的“正确方法”,但当然它预先增加了一些复杂性,但你会发现它的组织后来远远超过节省的时间。
现在有些例子
404错误(和错过的路线):
http://example.com/foo
路由到home::error404()
和输出<h3>Error 404 page foo/index not found</h3>
http://example.com/home/foo
路由到home::error404()
和输出<h3>Error 404 page home/foo not found</h3>
默认主页:
http://example.com/
路由到home::index()
http://example.com/index.php
路由到home::index()
http://example.com/home
路由到home::index()
http://example.com/home/index
路由到home::index()
http://example.com/home/index/hello
路由到home::index('hello')
http://example.com/home/index/hello/world
路由到home::index('hello','world')
就目前而言,你必须把完整的路径放在home的参数中,上面的代码可以改为考虑到这一点,但它对丢失的页面有一些影响。基本上任何缺失的页面都将成为控制器的参数。因此,如果您有http://example.com/user/foo
,那么如果已完成,则会调用user::index('foo')
。当然,这也可以解释,但复杂性开始叠加。
http://example.com/home/otherpage
路由到home::otherpage()
,但会发出错误参数警告。
http://example.com/home/otherpage/hello
路由到home::otherpage('hello')
http://example.com/index.php/home/otherpage/hello
路由到home::otherpage('hello')
如果你看:home::index($arg=false)
定义了一个默认值,这个方法没有。所以这个方法需要一个参数。其余部分应该是非常自我解释的。
第二个控制器用户示例:
http://example.com/user
路由到user::index()
http://example.com/user/index
路由到user::index()
http://example.com/user/login
路由到user::login()
其余部分基本相同,我只想展示如何通过功能为网站整理控制器。
我应该注意,这可以在网址中的{method}
之后处理无限数量的参数。
享受!