tobento / app-slugging
应用别名支持。
Requires
- php: >=8.0
- psr/container: ^2.0
- tobento/app: ^1.0.7
- tobento/app-database: ^1.0
- tobento/app-migration: ^1.0
- tobento/service-autowire: ^1.0.9
- tobento/service-repository: ^1.0
- tobento/service-repository-storage: ^1.0
- tobento/service-slugifier: ^1.0
Requires (Dev)
- phpunit/phpunit: ^9.5
- tobento/app-http: ^1.0 || ^1.1
- tobento/app-testing: ^1.0
- tobento/service-container: ^1.0
- tobento/service-validation: ^1.0
- vimeo/psalm: ^4.0
README
使用 Slugifier 服务 为应用提供别名支持。
目录
入门
运行此命令安装应用别名项目的最新版本。
composer require tobento/app-slugging
要求
- PHP 8.0 或更高版本
文档
应用
如果您正在使用骨架,请查看 应用骨架。
您还可以查看 应用 了解有关应用的一般信息。
别名启动
别名启动执行以下操作:
- 安装和加载别名配置文件
- 实现别名接口
use Tobento\App\AppFactory; use Tobento\App\Slugging\SlugRepositoryInterface; use Tobento\Service\Slugifier\SlugifierFactoryInterface; use Tobento\Service\Slugifier\SlugifierInterface; use Tobento\Service\Slugifier\SlugifiersInterface; use Tobento\Service\Slugifier\SlugsInterface; // Create the app $app = (new AppFactory())->createApp(); // Add directories: $app->dirs() ->dir(realpath(__DIR__.'/../'), 'root') ->dir(realpath(__DIR__.'/../app/'), 'app') ->dir($app->dir('app').'config', 'config', group: 'config') ->dir($app->dir('root').'public', 'public') ->dir($app->dir('root').'vendor', 'vendor'); // Adding boots $app->boot(\Tobento\App\Slugging\Boot\Slugging::class); $app->booting(); // Implemented interfaces: $slugifierFactory = $app->get(SlugifierFactoryInterface::class); $slugifier = $app->get(SlugifierInterface::class); $slugifiers = $app->get(SlugifiersInterface::class); $slugs = $app->get(SlugsInterface::class); $slugRepository = $app->get(SlugRepositoryInterface::class); // Run the app $app->run();
别名配置
别名配置位于默认应用骨架配置位置(在 app/config/slugging.php
文件中),您可以在其中指定应用的别名以及其他配置。
生成别名
要生成别名,请使用别名接口
use Tobento\Service\Slugifier\SlugifierInterface; use Tobento\Service\Slugifier\SlugifiersInterface; class SomeService { public function __construct( protected SlugifierInterface $slugifier, protected SlugifiersInterface $slugifiers, ) {} private function slugify() { // using the default slugifier: $slug = $this->slugifier->slugify(string: 'Lorem Ipsum!', locale: 'de'); // using a custom slugifier: $slug = $this->slugifiers->get('custom')->slugify('Lorem Ipsum!'); } }
您可以通过查看 别名服务 了解更多信息。
添加别名
您可以将别名添加到防止重复别名或用于路由目的,例如在路由中使用 别名匹配。
从配置中
您可以直接在 别名配置 中使用资源添加别名。
使用应用
有时,在应用内部使用资源添加别名可能会有用
use Tobento\Service\Slugifier\Resource\ArrayResource; use Tobento\Service\Slugifier\SlugsInterface; // Adding slugs resources only if requested: $app->on(SlugsInterface::class, static function(SlugsInterface $slugs): void { $slugs->addResource(new ArrayResource( slugs: ['login'], )); });
仓库资源
使用 RepositoryResource
类,您可以将任何实现 RepositoryInterface
的仓库添加为资源。
use Tobento\App\Slugging\Resource\RepositoryResource; use Tobento\Service\Repository\RepositoryInterface; use Tobento\Service\Slugifier\SlugsInterface; // Adding slugs resources only if requested: $app->on(SlugsInterface::class, static function(SlugsInterface $slugs, BlogRepositoryInterface $blogRepo): void { $slugs->addResource(new RepositoryResource( repository: $blogRepo, priority: 100, // higher priority will be first. resourceKey: 'blog', // or null // or using a closure: resourceKey: static function (null|object $blog): null|string { return $blog->resourceKey(); }, resourceId: static function (object $blog): null|string|int { return $blog->id(); }, // or null if none: resourceId: null, // you may customize the where query parameters: whereParameters: static function (string $slug, string $locale): array { return $locale === '' ? ['slug' => $slug] // locale independent (default) : ['slug' => $slug, 'locale' => $locale]; // locale dependent // JSON SYNTAX: return ['slug->'.$locale => $slug]; // locale dependent }, )); });
别名仓库
默认情况下,别名仓库会添加到 别名配置 中的别名中,从而防止重复别名。
使用别名仓库的优势在于,在生成别名或使用 别名匹配 时,如果它是唯一的 添加别名资源,则只会进行一次查询。
保存别名
使用 saveSlug
方法保存别名
use Tobento\App\Slugging\SlugRepositoryInterface; use Tobento\Service\Slugifier\Slug; $slugRepository = $app->get(SlugRepositoryInterface::class); $savedSlug = $slugRepository->saveSlug(new Slug( slug: 'lorem-ipsum', locale: 'en', resourceKey: 'blog', // null|string resourceId: 125, // null|int|string ));
删除别名
使用 deleteSlug
方法删除别名
use Tobento\App\Slugging\SlugRepositoryInterface; use Tobento\Service\Slugifier\Slug; $slugRepository = $app->get(SlugRepositoryInterface::class); $deletedSlug = $slugRepository->deleteSlug(new Slug( slug: 'lorem-ipsum', locale: 'en', ));
路由
首先,您需要安装 App Http。
别名匹配
您可以使用 SlugMatches
类来使用仅带有别名的不同控制器进行多个路由的匹配,基于 resouceKey
参数。
use Tobento\App\Slugging\Routing\SlugMatches; $app->route( method: 'GET', uri: '{slug}', //handler: [BlogController::class, 'show'], handler: function (string $slug) { return $createdResponse; }, )->matches(new SlugMatches(resourceKey: 'blog')); $app->route( method: 'GET', uri: '{slug}', //handler: [ProductController::class, 'show'], handler: function (string $slug) { return $createdResponse; }, )->matches(new SlugMatches(resourceKey: 'product'));
使用地区
您可以使用 withLocale
参数来定义 URI 地区参数的名称。一旦定义,别名将根据地区进行匹配。
use Tobento\App\Slugging\Routing\SlugMatches; $app->route( method: 'GET', uri: '{?locale}/{slug}', handler: function (string $slug) { return $createdResponse; }, ) ->locales(['de', 'en']) ->localeOmit('en') ->matches(new SlugMatches( resourceKey: 'blog', withLocale: 'locale', ));
使用资源 ID
您可以使用withUriId
参数来定义传递给处理器的参数名称,其中将传递来自slug实体的资源ID$slug->resourceId()
。
use Tobento\App\Slugging\Routing\SlugMatches; $app->route( method: 'GET', uri: '{slug}', handler: function (int|string $id) { return $createdResponse; }, )->matches(new SlugMatches( resourceKey: 'blog', withUriId: 'id', ));
自定义Slug URI
您可以使用uriSlugName
参数来更改slug的URI名称。
use Tobento\App\Slugging\Routing\SlugMatches; $app->route( method: 'GET', uri: '{alias}', handler: function (string $alias) { return $createdResponse; }, )->matches(new SlugMatches( resourceKey: 'blog', uriSlugName: 'alias', ));
唯一别名验证规则
要求
composer require tobento/app-validation
别忘了启动验证器
use Tobento\App\AppFactory; // Create the app $app = (new AppFactory())->createApp(); // Adding boots $app->boot(\Tobento\App\Validation\Boot\Validator::class); $app->boot(\Tobento\App\Slugging\Boot\Slugging::class); // Run the app $app->run();
唯一Slug规则
use Tobento\App\Slugging\Validation\UniqueSlugRule; $validation = $validator->validate( data: [ 'slug' => 'login', 'slug.de' => 'anmelden', 'slug.en' => 'login', ], rules: [ 'slug' => [ new UniqueSlugRule( locale: 'en', // you may specify a custom error message: errorMessage: 'Custom error message', ), ], 'slug.de' => [ new UniqueSlugRule(), // locale is automatically determined as 'de'. ], 'slug.en' => [ new UniqueSlugRule(), // locale is automatically determined as 'en'. ], ] );
跳过验证
您可以使用skipValidation
参数在某些条件下跳过验证
use Tobento\App\Slugging\Validation\UniqueSlugRule; $validation = $validator->validate( data: [ 'slug.en' => 'login', ], rules: [ 'slug.en' => [ // skips validation: new UniqueSlugRule(skipValidation: true), // does not skip validation: new UniqueSlugRule(skipValidation: false), // skips validation: new UniqueSlugRule(skipValidation: fn (mixed $value): bool => $value === 'foo'), ], ] );