【问题标题】:Oop php front controller issue哎呀php前端控制器问题
【发布时间】:2017-06-30 07:41:50
【问题描述】:

我在为我在学校的一个项目构建前端控制器时遇到问题。 事情是这样的,我为每个实体创建了几个控制器,即一个用于选择,另一个用于删除等......这适用于帖子和 cmets。所以我有 6 个控制器,然后我被要求在这些控制器之上构建前端控制器,但我继续添加层(全部路由到 index.php,然后从那里实例化前端控制器,然后将请求发送到相关控制器带有标头(位置:...),它变得混乱且非常复杂,因为对于某些请求,我需要在 url 中为数据库请求传递一些 id... 我不能使用任何框架,所以有没有一种更简洁的方法来构建一个前端控制器,它可以处理带有 url 中参数的请求,而有些则没有? 我是否必须将所有内容路由到单个页面(使用 htaccess 我创建了一个简单的规则将所有内容发送到 index.php)? 然后从那里再次实例化前端控制器? 如果您需要一些代码,我会与您分享,但它是一团糟:)

谢谢大家,我需要建议我现在有点迷路了

【问题讨论】:

  • 所以基本上你的前端控制器更像是路由器而不是控制器?不要重定向,如果它更像是一个路由器,只需从“前端控制器”实例化并调用其他控制器方法。
  • 是的,它确实更像是一个路由器而不是一个控制器!但是然后我需要为其他控制器构建类,例如使用构造函数?因为它的作用是实例化特定类的方法(选择、插入、水合等方法...)

标签: php


【解决方案1】:

你会想要构建一个基本的路由器,它是做什么的。

路由器将解析路径并获取其中的一部分并定位控制器文件。然后在该文件中运行带有参数的方法。我们将使用这种格式的网址

  www.yoursite.com/index.php/{controller}/{method}/{args}

所以对于这个例子,我们的 url 将是

  www.yoursite.com/index.php/home/index/hello/world

index.php 可以使用一些基本的 .htaccess (Mod Rewrite) 隐藏

所以让我们定义一些东西,首先我们将有文件夹

-public_html
  index.php
  --app
    ---controller
       home.php

所以主文件夹是public_html,其中index.php 和一个名为app 的文件夹。在app 里面是一个名为controller 的文件夹,里面是我们的home.php 控制器

现在是代码(是的)

index.php(基本路由器)

<?php
//GET URI segment from server, everything after index.php ( defaults to home )
$path_info = isset( $_SERVER['PATH_INFO'] ) ? $_SERVER['PATH_INFO'] : '/home';
//explode into an array - array_filter removes empty items such as this would cause  '/home//index/'  leading /, trailing / and // double slashes.
$args = array_filter( explode('/', $path_info) );

$controller_class = array_shift($args); //remove first item ( contoller )
$method = count( $args ) > 0 ? array_shift($args) : 'index'; //remove second item or default to index ( method )

$basepath = __DIR__.'/app/controller/'; //base path to controllers

if(!file_exists($basepath.$controller_class.".php") ){
    echo "SHOW 404";
    exit();
}

//instantiate controller class
require_once $basepath.$controller_class.".php";
$Controller = new $controller_class;

//check if method exists in controller
if(!method_exists( $Controller, $method ) ){
    echo "Method not found in controller / or 404";
    exit(); 
}

//call methods with any remaining args
call_user_func_array( [$Controller, $method], $args);

home.php(控制器)

<?php

class home{

    public function index( $arg1="", $arg2=""){
        echo "Arg1: ".$arg1 . "\n";
        echo "Arg2: ".$arg2 . "\n";
    }

    public function test( $arg1 = "" ){
        echo "Arg1: ".$arg1 . "\n";         
    }   
}

现在,如果您输入这些网址中的任何一个

  www.yoursite.com/index.php
  www.yoursite.com/index.php/home
  www.yoursite.com/index.php/home/index

它应该打印(默认)

  Arg1: 
  Arg2: 

如果你做这个网址

  www.yoursite.com/index.php/home/index/hello/world

应该打印出来

 Arg1: hello
 Arg2: world

如果你这样做了

  www.yoursite.com/index.php/home/test/hello_world

它会打印出来

  Arg1: hello_world

最后一个,在第二个方法test(没有echo arg2)中运行,这样你可以看到我们如何添加更多的控制器和方法,只需将它们编码到一个控制器中。

此方法仍然允许您使用 url 的 $_GET 部分以及 URI 部分将信息传递给控制器​​。所以这仍然有效

  www.yoursite.com/index.php/home/test/hello_world?a=1

并且您可以(在 home::test() 中)毫无问题地输出 $_GET 的内容,这对于搜索表单等很有用。一些漂亮的 url 方法可以防止这种情况,这只是......好吧......废话。

.htaccess 中使用 mod rewrite 您可以这样做以从 url 中删除 index.php

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ index.php?/$1 [L]
</IfModule>

然后你可以使用不带index.php的url比如这个

  www.yoursite.com/home/index/hello/world

这是我能在这么短的时间内想到的最简单的路由器,是的,我刚刚创建了它。但这与许多 MVC 框架中使用的非常相似(尽管是简化的)实现

PS。请理解这一切是如何完成的,所以你实际上学到了一些东西......

可以进行许多改进,例如允许这些网址

   www.yoursite.com/hello/world

   www.yoursite.com/home/hello/world

   www.yoursite.com/index/hello/world

这将全部退回到家庭控制器和索引方法的默认值,但这需要一些额外的检查(对于未找到的文件和方法)我现在不能打扰......

【讨论】:

  • 当然,很高兴我能帮上忙。学学就行了,更多的是方法和推理,然后是代码……
  • PS,URL 是物理地址的真实路径,URI 是物理地址的虚构路径(至少我是这样定义 2 的)
  • 但是谢谢,因为说实话很难找到好的材料
  • 这些年来我已经写了一些,我目前正在构建一个事件驱动的框架(慢慢地构建它......哈哈),当我有时间在工作之外时,github.com/ArtisticPhoenix/Evo
【解决方案2】:

这是一个简单的演示过程(行不通,只是一个示例)。

index.php

//Say you called /index.php/do/some/stuff
$route = $_SERVER["PATH_INFO"]; //This will contain /do/some/stuff

$router = new Router();
$router->handle($route);

router.php

class Router {
     private static $routeTable = [
         "do/some/stuff" => [ "DoingSomeController" => "stuff" ]
     ];

     public function handle($route) {
          if (isset(self::$routeTable[trim($route,"/"])) {
              $controller = new self::$routeTable[trim($route,"/"][0];
              call_user_func([$controller,self::$routeTable[trim($route,"/"][1]]);

          }
     }
}

基本演示,一些框架的作用。

【讨论】:

    猜你喜欢
    • 2012-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-22
    • 1970-01-01
    • 2013-02-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多