impressible / impressible-route
Wordpress 插件中编写现代 PHP 代码的路由框架。
v2.0-beta2
2022-08-27 01:02 UTC
Requires
- php: >=7.4
- guzzlehttp/psr7: ^2.2
- psr/container: ^2.0
- psr/http-factory: ^1.0
- psr/http-message: ^1.0
Requires (Dev)
This package is auto-updated.
Last update: 2024-09-27 05:54:47 UTC
README
Wordpress 插件中编写现代 PHP 代码的路由框架。
为什么选择它?
对于已经适应现代 PHP 应用方法(例如 composer 包管理、PSR-4 命名空间自动加载、服务容器等)的 PHP 开发者来说,在 Wordpress 环境中工作相当痛苦。
比如说你想
- 使用自定义路由编写你的 Wordpress 插件;你
- 希望将你的代码结构化到与 psr/http-message 请求和响应(为了未来的灵活性)一起工作的控制器中;并且
- 你想以自定义初始化逻辑或 PSR 兼容的 服务容器 懒加载你的控制器。
那么这个库就是为你准备的。
如何使用这个库?
在编写插件时,添加这个钩子实现
use Impressible\ImpressibleRoute\Http\Router;
use Impressible\ImpressibleRoute\LazyLoadObject;
require __DIR__ . '/vendor/autoload.php';
function my_plugin_register_routes() {
/**
* @var \wpdb $wpdb
*/
global $wpdb;
// Lazyload a MyController that, for demo purpose only, somehow need to use wpdb.
$controller = new LazyLoadObject(fn() => new MyController($wpdb));
// Create a router instance and register routes with it.
$router = Router::fromEnvironment(
'my_plugin_route', // query parameter used for routing.
__DIR__ // folder for Wordpress template.
)
->addRoute(new Route(
'mycontent$',
[$controller, 'handleContentIndex']
));
->addRoute(
(new Route(
'mycontent/mymedia/(\d+)$',
[$controller, 'handleMediaEndpoint'],
// Define query arguments supplied to the global \WP_Query
// that will be passed to the controller method.
[
'post_id' => '$matches[1]',
'post_type' => 'mymedia',
],
))->withPreGetPosts(function (\WP_Query $wpQuery) {
// Show all mymedia to the author (after login)
if (($userId = get_current_user_id()) != 0) {
$author = get_user_by('slug', $query->get('author_name'));
if ($userId === $author->ID) {
// Get post of all status to the post author.
$statuses = array_keys(get_post_statuses());
$query->set('post_status', $statuses);
}
}
})
)
// register the router methods to the Wordpress environment.
->register();
}
add_action('init', 'my_plugin_register_routes');
在你的控制器中,你可以灵活地使用旧式 Wordpress 方式,或者 PSR 服务器请求/响应方式
use Impressible\ImpressibleRoute\Http\TemplatedResponse;
use Impressible\ImpressibleRoute\Http\NotFoundResponse;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Psr7\Response;
class MyController
{
...
public function handleContentIndex(ServerRequestInterface $request)
{
return new TemplatedResponse('content-index.php');
}
public function handleMediaEndpoint(ServerRequestInterface $request)
{
/**
* @var \WP_Query
*/
$query = $request->getAttribute('wp_query');
if (!$query->have_posts()) {
return new NotFoundResponse();
}
$post = $query->next_post();
return new Response(
200,
['Content-Type' => $post->mymedia_content_type],
fopen($post->mymedia_content, 'r')
);
}
}
管理界面路由
我们也支持使用类似于 "admin_menu" 和 "admin_init" 钩子的方式来支持管理页面路由。
use Impressible\ImpressibleRoute\Http\AdminRouter;
use Impressible\ImpressibleRoute\Http\AdminRoute;
use Impressible\ImpressibleRoute\LazyLoadObject;
require __DIR__ . '/vendor/autoload.php';
function my_plugin_register_admin_routes() {
/**
* @var \wpdb $wpdb
*/
global $wpdb;
// Lazyload a MyController that, for demo purpose only, somehow need to use wpdb.
$controller = new LazyLoadObject(fn() => new MyAdminController($wpdb));
// Create a router instance and register routes with it.
$router = new AdminRouter()
->addRoute(AdminRoute::menu(
'My Admin Section',
'My Section',
'some-capability',
'menu_slug_1',
[$controller, 'handleAdminSection'],
'icon-1',
1 // position
))
->addRoute(AdminRoute::menu(
'menu_slug_1',
'My Admin Sub-section',
'My Subection',
'some-capability',
'menu_slug_2',
[$controller, 'handleAdminSubection'],
1 // position
));
// register the router methods to the Wordpress environment.
->register();
}
add_action('admin_menu', 'my_plugin_register_admin_routes');
在你的 MyAdminController 中,你可以灵活地
use Impressible\ImpressibleRoute\Http\TemplatedResponse;
use Impressible\ImpressibleRoute\Http\NotFoundResponse;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Psr7\Response;
class MyAdminController
{
...
public function handleAdminSection(ServerRequestInterface $request)
{
// For ordinary admin page responses.
return new AdminPageResponse(function () use ($request) {
// The code here will be delayed to execute the time
// ordinarly Wordpress admin menu callback is run.
require 'some/path/some/script.php';
});
}
public function handleAdminSubection(ServerRequestInterface $request)
{
// For export or other pages without dashboard top bar and sidebar.
// This will be executed when admin_init hook is run.
return new Response(
200,
[
'Content-Type' => 'application/json',
],
json_encode([
'status' => 'success',
'msg' => 'Successful API call',
])
);
}
}
许可证
这个库是在 MIT 许可证 下授权的。