承接 polidog/usephp-approuter 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

polidog/usephp-approuter

最新稳定版本:v0.1.0

Composer 安装命令:

composer require polidog/usephp-approuter

包简介

Next.js App Router style file-based routing for usePHP

README 文档

README

Next.js App Router style file-based routing for PHP, built on usePHP.

Requirements

Installation

composer require polidog/usephp-approuter

Quick Start

<?php
// public/index.php
require_once __DIR__ . '/../vendor/autoload.php';

use Polidog\UsephpApprouter\AppRouter;

$app = AppRouter::create(__DIR__ . '/../src/app');
$app->run();

Directory Structure

app/
  layout.php          -> Root layout (wraps all pages, or layout.psx)
  page.psx            -> /
  error.php           -> Error page (404 etc., or error.psx)
  about/
    page.psx          -> /about
  counter/
    page.psx          -> /counter
  todo/
    page.psx          -> /todo
  form/
    page.psx          -> /form
  blog/
    [slug]/
      page.psx        -> /blog/:slug (dynamic route)

Page Types

Function Page (closure-based)

Pages return a closure that receives a PageContext. The closure returns a render function. Use page.psx to write the inner render in TSX-like markup.

<?php
// app/about/page.psx
declare(strict_types=1);

use Polidog\UsePhp\Runtime\Element;
use Polidog\UsephpApprouter\Component\PageContext;

return function (PageContext $ctx) {
    $ctx->metadata(['title' => 'About']);

    return function (): Element {
        return (
            <div className="container">
                <h1>About</h1>
                <p>Written in PSX.</p>
            </div>
        );
    };
};

Helpers stay encapsulated inside the outer closure:

return function (PageContext $ctx) {
    $ctx->metadata(['title' => 'About']);

    $renderCard = function (string $title): Element {
        return (
            <div>
                <h3>{$title}</h3>
            </div>
        );
    };

    return function () use ($renderCard): Element {
        return (
            <div>
                {$renderCard('Hello')}
            </div>
        );
    };
};

Dynamic Routes

Directory names wrapped in brackets (e.g. [slug]) become URL parameters, accessible via $ctx->params:

// app/blog/[slug]/page.psx
return function (PageContext $ctx) {
    $slug = $ctx->params['slug'] ?? '';
    $ctx->metadata(['title' => ucwords($slug) . ' - Blog']);

    return function () use ($slug): Element {
        return (
            <div>Blog post: {$slug}</div>
        );
    };
};

useState Hook

use function Polidog\UsePhp\Runtime\useState;

return function (PageContext $ctx) {
    return function (): Element {
        [$count, $setCount] = useState(0);

        return (
            <div>
                <span>{(string) $count}</span>
                <button onClick={fn() => $setCount($count + 1)}>+</button>
            </div>
        );
    };
};

Class Page

Class-based pages are also supported by extending PageComponent. Use page.psx to write the render method in TSX-like markup:

<?php
// app/form/page.psx
declare(strict_types=1);

namespace App\Form;

use Polidog\UsePhp\Runtime\Element;
use Polidog\UsephpApprouter\Component\PageComponent;

class FormPage extends PageComponent
{
    public function render(): Element
    {
        $this->setMetadata(['title' => 'Form']);
        [$data, $setData] = $this->useState([]);
        $action = $this->action([$this, 'handleSubmit']);

        return (
            <form action={$action}>
                <input type="text" name="name" />
                <button type="submit">Send</button>
            </form>
        );
    }

    protected function handleSubmit(array $formData): void
    {
        // handle form submission
    }
}

Compiling .psx files

.psx files must be compiled. Output goes to var/cache/psx/ by default (sha1-named files plus manifest.php); the source tree only ever contains .psx.

# Production / CI: pre-compile once
./vendor/bin/usephp compile src/app
./vendor/bin/usephp compile src/app --check   # CI guard

# Dev loop: watch and recompile on save
./vendor/bin/usephp compile src/app --watch

# Override the cache location
./vendor/bin/usephp compile src/app --cache=build/psx

Or let AppRouter compile on demand during development:

// Default cache: <appDir>/../var/cache/psx
$app = AppRouter::create(__DIR__ . '/../src/app', autoCompilePsx: true);

// Or pass an explicit cache directory (must match the CLI if you also
// use `vendor/bin/usephp compile`):
$app = AppRouter::create(
    __DIR__ . '/../src/app',
    autoCompilePsx: true,
    psxCacheDir: __DIR__ . '/../build/psx',
);

page.psx and page.php cannot coexist in the same directory — the scanner errors if both are present.

Add the cache directory to .gitignore:

/var/cache/psx/

Layouts

Each directory can have a layout.php (or layout.psx) that wraps all pages beneath it. Layouts implement LayoutInterface. Only one extension per directory — having both layout.psx and layout.php side by side is rejected as ambiguous.

Configuration

$app = AppRouter::create(__DIR__ . '/../src/app');
$app->setJsPath('/assets/app.js');
$app->addCssPath('/assets/style.css');
$app->setContainer($container); // PSR-11 container (optional)
$app->run();

Running Tests

vendor/bin/phpunit

License

MIT

统计信息

  • 总下载量: 2
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 5
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-03-01

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固