impressible/impressible-route

Wordpress 插件中编写现代 PHP 代码的路由框架。

v2.0-beta2 2022-08-27 01:02 UTC

This package is auto-updated.

Last update: 2024-09-27 05:54:47 UTC


README

CI badge-coverage Packagist

Wordpress 插件中编写现代 PHP 代码的路由框架。

为什么选择它?

对于已经适应现代 PHP 应用方法(例如 composer 包管理、PSR-4 命名空间自动加载、服务容器等)的 PHP 开发者来说,在 Wordpress 环境中工作相当痛苦。

比如说你想

  1. 使用自定义路由编写你的 Wordpress 插件;你
  2. 希望将你的代码结构化到与 psr/http-message 请求和响应(为了未来的灵活性)一起工作的控制器中;并且
  3. 你想以自定义初始化逻辑或 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 许可证 下授权的。