Oop php前端控制器问题

时间:2017-06-30 07:41:50

标签: php

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

谢谢你们,我需要建议我现在有点迷失

2 个答案:

答案 0 :(得分:2)

你需要建立一个基本的路由器,它的作用。

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

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

因此,对于此示例,我们的网址将是

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

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

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

-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),这样你就可以看到我们如何添加更多的控制器和方法,只需要将它们编码到控制器中。

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

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

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

在使用mod重写的.htaccess中,您可以执行此操作以从网址中删除index.php

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

然后你可以使用没有index.php的网址,比如这个

  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

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

答案 1 :(得分:1)

这是一个简单的演示过程(不会起作用,只是一个例子)。

<强>的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]]);

          }
     }
}

基本演示,一些框架的功能。