Php 如何在类似MVC的页面中加载基于漂亮URL的类?
我想问一些关于如何解决这个问题的建议。我正在尝试建立我自己的MVC网站。我学习了URL的基本知识Php 如何在类似MVC的页面中加载基于漂亮URL的类?,php,.htaccess,url-routing,Php,.htaccess,Url Routing,我想问一些关于如何解决这个问题的建议。我正在尝试建立我自己的MVC网站。我学习了URL的基本知识 http://example.com/blog/cosplay/cosplayer-expo-today blog->controllercosplay->controller中的方法cosplayer expo today->variable in method 如果我在我的博客控制器中动态扩展类别会怎么样?我是否需要创建该方法,或者是否有一些技巧可以自动创建该方法?我是说。。。我现在有这些类别
http://example.com/blog/cosplay/cosplayer-expo-today
blog->controllercosplay->controller中的方法
cosplayer expo today->variable in method 如果我在我的博客控制器中动态扩展类别会怎么样?我是否需要创建该方法,或者是否有一些技巧可以自动创建该方法?我是说。。。我现在有这些类别:角色扮演,游戏,电影,系列。所以我需要在controller中创建这些方法,但它们都做相同的事情,即从数据库中选择其他类别
- 函数cosplay()=example.com/blog/cosplay/
- 函数game()=example.com/blog/game/
- 函数movie()=example.com/blog/movie/
- 函数系列()=example.com/blog/series/
class Autoload
{
var $url;
var $controller;
function __construct()
{
$this->url = $_GET['url'];
//HNEM ÜRES AZ URL
if($this->url!='' && !empty($this->url))
{
require 'application/config/routes.php';
//URL VIZSGÁLATA
$this->rewrite_url($this->url);
//URL SZÉTBONTÁSA
$this->url = explode('/', $this->url);
$file = 'application/controllers/'.$this->url[0].'.php';
//LÉTEZIK A CONTROLLER?
if(file_exists($file))
{
require $file;
$this->controller = new $this->url[0];
//KÉRELEM ALATT VAN AZ ALOLDAL?
if(isset($this->url[1]))
{
//LÉTEZIK A METÓDUS? ENGEDÉLYEZVE VAN?
if(method_exists($this->controller, $this->url[1]) && in_array($this->url[1], $route[$this->url[0]]))
{
if(isset($this->url[2]))
{
$this->controller->{$this->url[1]}($this->url[2]);
}
else
{
$this->controller->{$this->url[1]}();
}
}
else
{
header('location:'.SITE.$this->url[0]);
die();
}
}
}
else
{
header('location:'.SITE);
die();
}
}
else
{
header('location:'.SITE.'blog');
die();
}
}
/**
* Első lépésben megvizsgáljuk, hogy a kapott szöveg tartalmaz-e nagybetűt. Amennyiben igen átalakítjuk kisbetűsre.<br/>
* Második lépésben megnézzük, hogy a kapott szöveg '/'-re végződik-e. Amennyiben igen levágjuk azt.<br/>
* Harmadik lépésben újra töltjük az oldalt a formázott szöveggel.
*
* @param string $url Korábban beolvasott URL.
*/
private function rewrite_url($url)
{
//HA NAGYBETŰ VAN AZ URL-BEN VAGY '/'-RE VÉGZŐDIK
if(preg_match('/[A-Z]/', $url) || substr($url, -1)=='/')
{
//NAGYBETŰS AZ URL KICSIRE ALAKÍTJUK
if(preg_match('/[A-Z]/', $url))
{
$url = strtolower($url);
}
//HA '/'-RE VÉGZŐDIK LEVÁGJUK
if(substr($url, -1)=='/')
{
$url = substr($url, 0, strlen($url)-1);
}
header('location:'.SITE.$url);
die();
}
}
}
我想你对这件事想得太多了 因此,控制器/资源是一个blog…所有控制器/资源运行的方法都是“read”(使用crud…我通常称之为data,但基本上是您自己选择的)。现在,让您的方法接受一个类别值,该值将根据url自动映射 这是一个示例…完全未经测试,但只是为了向您展示这个想法(使用pdo) 仅供参考:有几件事你做错了。我将试着逐一解释问题、误解和可能的解决方案 自动加载和路由是分开的。 从您发布的代码来看,很明显,您只有一个类,负责以下任务:
- 路由:它将URL拆分为对其他应用程序有一定意义的部分
- 自动加载:类接受分离的URL段并尝试包含相关代码
- 工厂:初始化新实例并对其调用某些方法
- 响应:在某些情况下,类以HTTP头的形式向用户发送响应
自动加载类至少4个不同的职责
这些常规任务中的每一个都应该由单独的类来处理,而不是您现在所拥有的。在自动加载器的情况下,你只需一个功能就可以脱身
如何编写自己的自动加载代码?
我看到的部分问题是关于自动加载在PHP中实际如何工作的混淆。在创建实例的地方不需要调用include
或require
。相反,您注册了一个处理程序(使用函数),当您尝试使用以前未定义的类时,会**自动*调用该处理程序
最简单的例子是:
spl_autoload_register( function( $name ) use ( $path ) {
$filename = $path . '/' . $name . '.php';
if ( file_exists( $filename ) === true ) {
require $filename;
return true;
}
return false;
});
这个特定的示例使用了,这是PHP5.3中引入的功能之一,但是spl\u autoload\u register()
的手册页面也将向您展示如何使用对象或普通函数实现相同的功能
另一个与自动加载密切相关的新特性是。在这种情况下,名称空间将给您带来两个直接的好处:能够拥有多个同名类,以及从多个目录加载类文件的选项
例如,您可以使用如下代码:
$controller = new \Controllers\Overview;
$view = new \Views\Overview;
$controller->doSomething( $request );
。。在这种情况下,您可以让autoloader分别从/project/controllers/overview.php
和/project/views/overview.php
文件获取类。因为spl\u autoload\u register()
将“\Controllers\Overview”
和“\Views\Overview”
传递给处理程序函数
还有一个关于如何实现自动加载器的建议。你可以找到它。虽然它有一些重大问题,但它应该为您提供一个良好的基础
如何解析漂亮的URL?
Apache的mod_重写在处理漂亮的URL方面非常有限,这不是什么秘密。而且,虽然它是一个广泛使用的服务器,但它不是Web服务器的唯一选择。这就是为什么为了获得最大的灵活性,PHP开发人员选择在PHP端处理URL
任何新手都会做的第一件事就是爆炸('/',…)
。这是一个自然的选择,但您很快就会注意到,它的实际功能也非常有限。路由机制将开始增长。首先基于段数,然后在段中添加需要不同行为的不同条件值
从本质上讲,这将导致巨大、脆弱和无法控制的混乱局面。坏主意
相反,您应该做的是有一个正则表达式列表,您可以根据给定的漂亮URL进行匹配。例如:
'#/(?P<resource>[^/\\\\.,;?\n]+)/foobar#'
您可以使用以下代码来处理:
// CHANGE THIS
$url = '/12345/product';
$current = null;
// matching the route
foreach ($routes as $name => $route) {
$matches = [];
if ( preg_match( $route['pattern'], $url, $matches ) ) {
$current = $name;
$matches = $matches + $route['default'];
break;
}
}
// cleaning up results
foreach ( array_keys($matches) as $key ) {
if ( is_numeric($key) ) {
unset( $matches[$key] );
}
}
// view results
var_dump( $current, $matches );
实时代码:或
注意:如果使用
'(?p…)
符号,匹配项将返回带有'name'
键的数组。比路由更有用的技巧
您可能希望从一些可读性更强的符号生成匹配的正则表达式。例如,在配置文件中,此表达式:
'#^/(?P<id>[0-9]+)(?:/(?P<resource>[^/\\\\.,;?\n]+)(?:/(?P<action>[^/\\\\.,;?\n]+))?)?$#'
其中,:param
表示URL段,[…]
表示URL的可选部分
基于此,您应该能够充实自己的路由系统。上面的代码片段只是简化核心功能的示例。要了解它在完全实现时的外观,可以查看中的代码。它应该给你这样的机会
$routes = [
'primary' => [
'pattern' => '#/(?P<resource>[^/\\\\.,;?\n]+)/foobar#',
'default' => [
'action' => 'standard',
],
],
'secundary' => [
'pattern' => '#^/(?P<id>[0-9]+)(?:/(?P<resource>[^/\\\\.,;?\n]+)(?:/(?P<action>[^/\\\\.,;?\n]+))?)?$#',
'default' => [
'resource' => 'catalog',
'action' => 'view',
]
],
'fallback' => [
'pattern' => '#^.*$#',
'default' => [
'resource' => 'main',
'action' => 'landing',
],
],
];
// CHANGE THIS
$url = '/12345/product';
$current = null;
// matching the route
foreach ($routes as $name => $route) {
$matches = [];
if ( preg_match( $route['pattern'], $url, $matches ) ) {
$current = $name;
$matches = $matches + $route['default'];
break;
}
}
// cleaning up results
foreach ( array_keys($matches) as $key ) {
if ( is_numeric($key) ) {
unset( $matches[$key] );
}
}
// view results
var_dump( $current, $matches );
'#^/(?P<id>[0-9]+)(?:/(?P<resource>[^/\\\\.,;?\n]+)(?:/(?P<action>[^/\\\\.,;?\n]+))?)?$#'
'/:id[[/:resource]/:action]'
$matches = $router->parse( $url );
$controller = new {'\\Controller\\'.$matches['controller']};
$controller->{$matches['action']( $matches );
public function getCategory( $request ) {
$category = $request->getParameter('category');
// ... rest of your controller method's code
}