php - 创建 PHP 'controller' 文件来构建网站上的所有页面

标签 php function url controller

我正在使用 CodeIgniter 框架开发另一个项目,该框架有一个主 Controller 文件,用于构建网站上的所有页面。

输入“domain.com/about”等网址将在 Controller 文件中运行“function about(){”,该文件会加载到该页面的各个组件中。

大部分的魔力都是由 CodeIgniter 或其他项目成员处理的,所以我不确定这是如何发生的。

我希望在不使用任何框架的情况下实现同样的目标,但完全不知道如何实现它。我知道我可以在“domain.com?load=about”的某个地方有一个 url,并使用它来运行该函数,但我希望该 URL 干净,并且易于访问者访问输入。

所以,我的问题是..我如何设置我的网站,使其始终指向单个文件“controller.php”,然后运行一个与 URL 中输入的内容相匹配的函数,并且具有该函数URL 没有引导我离开 Controller 页面? (也就是说,如果我输入“domain.com/about”,我不想进入 about.php 页面!)

如果这个问题很难理解,或者如果我对任何事情采取了错误的方法,我提前道歉。另外,由于缺乏示例和描述......我真的不知道如何更具体。如果您需要查看或了解任何内容,请提出,我会尽力澄清!

谢谢!

最佳答案

您对此没有太多好的答案。让我们添加更多细节。

CodeIgniter 的工作原理

URL 路由

CodeIgniter 的第一步实际上是在 CodeIgniter 本身之外完成的。您将在 HTTP 守护程序中找到此步骤。如果是Apache,你会看到类似这样的重写规则:

  RewriteRule ^(.+)$ /index.php?$1 [L]

如果你正在运行 nginx,你会看到:

  rewrite ^/(.+)$ /index.php?/$1 last;

这是每个框架的核心指令之一,并将导致它处理和解析每个请求(基于 RewriteCond/try_files 指令,可能会包括找到或未找到的文件)。用户提供的查询字符串将在 $_SERVER['QUERY_STRING'] 中提供。请记住这一点,我们将不止一次地讨论这一点。

进入框架

如果您计划构建一个框架,您的框架应该具有称为路由器的功能。这是一个简洁的小类(或类集合),它将处理路线的动态创建。路由是 URI(可能包含通配符)和 Controller 的函数(或多个函数)之间的定向映射。

这一点经常被第一次编写自己的框架的人所忽视,并且可以区分可以工作的东西和使用起来非常痛苦的东西(PHP 中的差异很小。这确实变得很明显其他技术)。

所以。路由器。获取路由列表,将它们转换为类和函数。我们需要缓存 Controller 并提供它们的动态分配,因此我们将引入一个新概念:控制反转。如果您使用过较新的框架(Kohona、Laravel 等),您会对此感到熟悉。实际上,它允许您将类名绑定(bind)到转到字符串,并通过中介器控制此类类的实例化(从而遵循好莱坞原则 - 您请求 Controller ,而不是实例化它)。

经典的 IoC 包装器如下所示:

 class IoC {
      private static $cache = array();
      private static $singletons = array();
      public static function register($name,$className,$isSingleton=false) {
          if (!isset(self::$cache[$name])) {
              self::$cache[$name] = array("class" => $className, "singleton" => !!$isSingleton);
          }
      }
      public static function instance($name) {
          if (!isset(self::$cache[$name])) throw new Exception("Class not found in IoC container");
          $cN = self::$cache[$name]['class'];
          if (!empty(self::$cache[$name]['singleton'])) {
               if (!isset(self::$singletons[$cN])) {
                     self::$singletons[$cN] = new $cN();
               }
               return self::$singletons[$cN];
          }
          else {
               return new $cN();
          }
      }
 }

这有很多好处:

  • 您很可能有一天决定将 Controller 从 Controller1 更改为 Controller2。通过使用 IoC 包装器来解决这个问题,您可以省去一些麻烦 - 不必遍历整个代码
  • 本地处理单例,而不会使它们难以进行单元测试

所以。凭借我们的知识,我们现在可以使用 IoC::instance("ourkeyword"); 基于我们选择的任意关键字实例化一个类。我们稍后会大量使用它。首先,有一个警告:此 IoC 包装器假定您将使用 spl_autoload 来延迟加载您的类

路由器本身将类似于:

 class Router {
      public $routes = array();
      public function register($route, $controller, $method, $request_type=7) {
           $this->routes[] = array("route" => $route, "call" => array($controller, $method), "request_type" => 7);
      }
      public function route($str) {
           foreach ($this->routes as $v) {
               // Do your request_type match here. Exercise left for the reader!
               if (preg_match($str, $v['route'], $matches)) {
                      try {
                         $controller = IoC::instance($v['call'][0]);
                         if (!method_exists($controller, $v['call'][1])) throw new Exception("Method not found: ".$v['call'][1]);
                         array_shift($matches);
                         call_user_func_array(array($controller,$v['call'][1]), $matches);
                      } catch (Exception $e) {
                      }
               }
           }
      }
 }

那是你的路由器!您可能想知道为什么 IoC 是纯粹的静态类,而 Router 是实例化的。原因很简单:您可能希望您的模块拥有自己的子路由器,而不必总是处理一个路由器。我经常这样做,这使我能够完全划分我的 PAC 结构并构建逻辑路由层次结构。

这就是所有的路由!从前面看,您的框架代码现在如下所示:

  IoC::register("controller1","My\\Controller");
  $router = new Router();
  $router->register(...);
  $router->route($_SERVER['QUERY_STRING']);

不错,简洁,抽象化了所有问题!由此,您可以构建遵循 MVC 架构或其任何变体的框架。这对于 PAC 来说效果非常好。

关于php - 创建 PHP 'controller' 文件来构建网站上的所有页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16843004/

相关文章:

python [:-1] vs remove

python - 对不同函数中的变量使用相同的名称?

javascript - 定义仅在运行 javascript 函数后附加的 URL 的最佳实践

.htaccess - 如何使用 .htaccess 重写 ssl 和友好的 URL

php - 网页抓取字体访问问题

PHP程序创建一个由 "*"个字符包围的 '@'个字符的方 block

php - 修改Yii CRUD生成(Gii)表单模板

JavaScript:创建返回基于输入参数返回值或对象的函数的函数

python - 网络爬虫url地址失败

php - php中的对象持久化