inanepain / routing
使用属性进行 HTTP 路由。
Requires
- php: >=8.1
- inanepain/http: >=0.1.3 || dev-master || dev-develop
This package is auto-updated.
Last update: 2024-09-20 09:41:56 UTC
README
()
使用 php 属性 进行 HTTP 路由。
简介:属性
什么是 属性?它是一个类,就像任何其他类一样,只是有一个 Attribute
属性。那么为什么你更像是对待一个只能持有几个值的 enum
或 Map
呢?你不会用你在自定义属性上使用的类这样做!但是我不怪你,这都归咎于文档中使用的某些糟糕的措辞。
那么我应该怎么想 属性 呢?就像类一样。更确切地说,是那些执行任务的对象的类。像 #[Route(name: 'home', path: '/')]
这样的用法,当你这样看待它时可能会更有意义:$route = new Route('/', 'home');
。这里有一个有趣的实验可以尝试;从 Route
中移除 Attribute
,然后让 Router
接受一个包含 Route
参数的数组作为参数。很简单,不是吗?通过练习,你会发现在更多类上可以这样做。
希望这能让您以新的、更现实的方式思考 属性,从而在更多类中添加 #[Attribute]
行。
安装
composer require inanepain/routing
使用方法
快速概述显示两个示例中与 Route
属性
相关的部分。虽然它们都不是完整的,但简单的示例可以轻松运行。请参阅附录以获取您将需要与 index.php
文件一起使用的 .htaccess
文件。
示例:简单
使用 php 内置的 web 服务器的一个简单示例,php -S localhost:8080 -t public index.php
。
MainController.php
class MainController { ... #[Route(path: '/', name: 'home')] public function home(): void { ... echo <<<HTML ... HTML; } ... #[Route(path: '/product/{product}', name: 'product', )] public function productTask(array $params): void { $sql = "...where product_id = '{$params["product"]}'"; ... echo <<<HTML ... HTML; } ... }
index.php
use App\Controller\MainController; use Inane\Routing\Router; require_once 'vendor/autoload.php'; $file = 'public' . $_SERVER['REQUEST_URI']; // Server existing files in web dir if (file_exists($file) && !is_dir($file)) return false; $router = new Router(); $router->addRoutes([MainController::class]); if ($match = $router->match()) { $controller = new $match['class'](); $controller->{$match['method']}($match['params']); } else { throw new Exception('Request Error: Unmatched `file` or `route`!'); }
示例:应用程序
一个稍微复杂一些的示例。
各个部分
IndexController.php
class IndexController extends AbstractController { ... #[Route(path: '/', name: 'home')] public function indexTask(): array { ... } ... #[Route(path: '/product/{product}', name: 'product', )] public function productTask(): array { ... } ... #[Route(path: '/product/{product}/review/{id<\d+>}', name: 'product-review')] public function reviewTask(): array { ... } ... }
index.phtml(视图模板)
... <a class="menu-item" href="<?=$route->url('product', ['product' => $item['id']])?>"><?=$item['name_long']?></a> ...
website(渲染的视图)
<a class="menu-item" href="/product/mega-maid">Mega Maid (Household Robot Helper)</a>
将所有部分组合起来
Application.php
class Application { ... protected function initialise(): void { ... $this->router = new Router([ IndexController::class, ... WhoopsController::class, ... ]); ... } ... public function run(): void { ... if ($match = $this->router->match()) { $controller = new $match['class']($match['params']); $data = $controller->{$match['method']}(); ... $body = $this->renderer->render($template, $data); ... } ... } ... }
附录:.htaccess
您还需要在您的 .htaccess
文件中进行一些魔法操作,以便 index.php
处理所有请求。
RewriteEngine On
# The following rule tells Apache that if the requested filename exists, simply serve it.
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [L]
# The following rewrites all other queries to index.php. The
# condition ensures that if you are using Apache aliases to do
# mass virtual hosting or installed the project in a subdirectory,
# the base path will be prepended to allow proper resolution of
# the index.php file; it will work in non-aliased environments
# as well, providing a safe, one-size fits all solution.
RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
RewriteRule ^(.*)$ %{ENV:BASE}/index.php [L]
<Limit GET HEAD POST PUT DELETE OPTIONS>
# Deprecated apache 2.2 syntax:
# Order Allow,Deny
# Allow from all
# Apache > 2.4 requires:
Require all granted
</Limit>