日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > php >内容正文

php

php mvc 路由,PHP手写MVC (五)—— 路由

發布時間:2023/12/10 php 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 php mvc 路由,PHP手写MVC (五)—— 路由 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

路由是一個框架中必不可少的組件,其作用是把 URL 按照預定規則解析到特定控制器中。

我們在這里定義了兩種路由規則:

查詢字符串。在路徑后面使用問號加參數,多個參數用 & 分隔。在配置文件使用 querystring 表示

#控制器/方法?參數1=值1&參數2=值2

http://domain/user/info?name=php&chapter=10

路徑,以路徑的形式將參數和值添加到后面,中間用 / 分隔。配置中使用 restful

#控制器/方法/參數1/值1/參數2/值2

https://domain/user/info/name/php/chapter/100

主控制器

在目錄 core 創建 Controller.php,該類繼承 Container

namespace core;

class Controller extends Container

{

}

主控制器可以添加控制器公共方法,如頁面渲染 render(),錯誤代碼等,所有控制器必須繼承主控制器。由于主控制器繼承 Container,因此,控制器也是分發器的子類,可以通過 register() 獲取實例。

控制器類

類命名規則

控制器命名遵循大寫開頭的駝峰命名規則,并且默認添加后綴 Controller,控制器文件命名和類命名一樣,如控制器類 UserController,其文件命名為 UserController.php。

方法命名規則

方法命名遵循小寫開頭的駝峰命名規則,并且默認添加請求方式(如,get,post,put等)前綴,如 getIndex(),postUpdate()。

以上例 UserController 為例

namespace controller;

use core\Controller;

class UserController extends Controller

{

/**

* HTTP 請求方式為 GET 時有效

* url 為 /user/info

*

*/

public function getInfo()

{

}

/**

* HTTP 請求方式為 POST 時有效

* url 為 /user/update

*

*/

public function postUpdate()

{

}

}

路由解析

在 core 目錄下創建 Router.php

$ cd tinyphp/core

$ touch Router.php

在構造函數中定義變量

namespace core;

use dispatcher\Container;

class Router extends Container

{

public $method;

public $uri;

public $path;

public function __construct()

{

$this->method = $_SERVER['REQUEST_METHOD'] ?? 'GET';

$this->uri = $_SERVER['REQUEST_URI'];

$this->path = $_SERVER['PATH_INFO'];

}

}

常見 $_SERVER 字段

$_SERVER['PATH_INFO'] URL的路徑信息,如 /user/info

$_SERVER['REQUEST_METHOD'] 請求方法,如 POST,GET

$_SERVER['REQUEST_URI'] 完整 URL,如 /user/info?id=1&name=Lucy

在 start() 方法中解析 URL

protected function start()

{

/**

* 也可以寫成 Config::get('default.route','querystring');

*

*/

$route = Config::get('default.route') ?? 'querystring';

//解析 controller 和 action

$path = explode('/',trim($this->path,'/'));

if (empty($path[0])) {

$path[0] = Config::get('default.controller','index');

}

$controller = ucfirst($path[0]).'Controller';

//獲取請求方法

$method = strtolower($this->method);

$action = $method.ucfirst($path[1] ?? Config::get('default.action','index'));

//獲取參數

$args = [];

if (method_exists($this,$route)) {

$args = call_user_func_array([$this,$route],[$this->uri]);

}

return ['controller'=>$controller,'action'=>$action,'args'=>$args];

}

querystring() 參數解析

private function querystring($url)

{

$urls = explode('?', $url);

if (empty($urls[1])) {

return [];

}

$param_arr = [];

$param_tmp = explode('&', $urls[1]);

if (empty($param_tmp)) {

return [];

}

foreach ($param_tmp as $param) {

if (strpos($param, '=')) {

list($key,$value) = explode('=', $param);

//變量名是否復合規則

if (preg_match('/^[A-Za-z_][A-Za-z0-9_]*$/', $key)) {

$param_arr[$key] = $value;

}

}

}

return $param_arr;

}

querystring 的參數為 ? 后面的部分,多個參數用 & 分隔。

restful() 參數解析

private function restful($url)

{

$path = explode('/', trim(explode('?', $url)[0], '/'));

$params = [];

$i = 2;

while (1) {

if (!isset($path[$i])) {

break;

}

$params[$path[$i]] = $path[$i+1] ?? '';

$i = $i+2;

}

return $params;

}

restful 的參數為方法后面的路徑。

完整代碼如下:

namespace core;

use dispatcher\Container;

class Router extends Container

{

public $method;

public $uri;

public $path;

public function __construct()

{

$this->method = $_SERVER['REQUEST_METHOD'] ?? 'GET';

$this->uri = $_SERVER['REQUEST_URI'];

$this->path = $_SERVER['PATH_INFO'];

}

protected function start()

{

$route = Config::get('default.route') ?? 'querystring';

//解析 controller 和 action

$path = explode('/',trim($this->path,'/'));

if (empty($path[0])) {

$path[0] = Config::get('default.controller','index');

}

$controller = ucfirst($path[0]).'Controller';

//獲取請求方法

$method = strtolower($this->method);

$action = $method.ucfirst($path[1] ?? Config::get('default.action','index'));

//獲取參數

$args = [];

if (method_exists($this,$route)) {

$args = call_user_func_array([$this,$route],[$this->uri]);

}

return ['controller'=>$controller,'action'=>$action,'args'=>$args];

}

/**

* 查詢字符串參數

* ?后,參數通過&&分隔

*

*/

private function querystring($url)

{

$urls = explode('?', $url);

if (empty($urls[1])) {

return [];

}

$param_arr = [];

$param_tmp = explode('&', $urls[1]);

if (empty($param_tmp)) {

return [];

}

foreach ($param_tmp as $param) {

if (strpos($param, '=')) {

list($key,$value) = explode('=', $param);

//變量名是否復合規則

if (preg_match('/^[A-Za-z_][A-Za-z0-9_]*$/', $key)) {

$param_arr[$key] = $value;

}

}

}

return $param_arr;

}

/**

* 路徑參數

* 控制器/方法/參數1/值1/參數2/值2

*

*/

http://domain/user/info/name/entner?name=php&chapter=10

private function restful($url)

{

$path = explode('/', trim(explode('?', $url)[0], '/'));

$params = [];

$i = 2;

while (1) {

if (!isset($path[$i])) {

break;

}

$params[$path[$i]] = $path[$i+1] ?? '';

$i = $i+2;

}

return $params;

}

}

路由調用方式為

$router = Rouer::start();

測試路由

在配置文件 app/conf/config.php 中設置默認路由為 querystring,

return [

'default' => [

'controller' => 'index',

'action' => 'index',

'route' => 'querystring',//還可以設置為 restful

],

'view' => [

'dir' => 'layout',

'file' => 'base',

]

];

在 core/Application.php 文件中 run() 方法實現路由調用

...

public function run()

{

$router = Router::start();

echo '

';

print_r($router);

}

...

啟動 PHP 內置服務器

$ cd tinyphp/public

$ php -S localhost:8080

在瀏覽器中輸入 http://localhost:8080/course/document?name=php&&chapter=10

輸出結果為

Array

(

[controller] => CourseController

[action] => getDocument

[args] => Array

(

[name] => php

[chapter] => 10

)

)

同理可以測試 restful 路由規則。

調用控制器方法

路由解析后,獲得需要調用的控制器名,方法和參數。由于控制器繼承分發器后,可以通過 register() 獲取實例,編輯 core/Applicaiton.php

...

public function run()

{

$router = Router::start();

//注意使用命名空間

$controller = "controller\\".$router['controller'];

$action = $router['action'];

$args = $router['args'];

echo call_user_func_array([$controller::register(),$action],$args);

}

...

通過這種方式可以實現方法調用,但是無法控制方法參數,比如,有時候我們需要在方法參數中使用某個對象實例,術語稱為依賴注入,即把需要使用的實例注入到方法中,那么可以通過PHP的高級特性反射來實現。

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的php mvc 路由,PHP手写MVC (五)—— 路由的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。