tobento / apps
支持多个应用程序。每个应用程序将在其自己的应用程序中运行。
Requires
- php: >=8.0
- tobento/app: ^1.0.7
- tobento/app-console: ^1.0
- tobento/app-http: ^1.0
- tobento/app-migration: ^1.0
Requires (Dev)
- phpunit/phpunit: ^9.5
- tobento/app-testing: ^1.0
- tobento/app-user-web: ^1.0
- vimeo/psalm: ^4.0
README
支持多个应用程序。每个应用程序将在其自己的应用程序中运行。
目录
入门
使用此命令添加运行此应用程序项目的最新版本。
composer require tobento/apps
要求
- PHP 8.0 或更高版本
文档
应用程序
如果您使用的是骨架,请查看 应用程序骨架。
您还可以查看 应用程序 以了解有关应用程序的一般信息。
创建新应用程序
要创建新应用程序,只需扩展 AppBoot::class
并按需定义常量。
use Tobento\Apps\AppBoot; class Backend extends AppBoot { /** * Specify your app boots: */ protected const APP_BOOT = [ //\Tobento\App\Console\Boot\Console::class, //\Tobento\App\User\Web\Boot\UserWeb::class, ]; /** * Set a unique app id. Must be lowercase and * only contain [a-z0-9-] characters. * Furthermore, do not set ids with two dashes such as 'foo--bar' * as supapps id will be separated by two dashes. */ protected const APP_ID = 'backend'; /** * You may set a slug for the routing e.g. example.com/slug/ * Or you may set the slug to an empty string e.g. example.com/ */ protected const SLUG = 'admin'; /** * You may set a domains for the routing e.g. ['api.example.com'] * In addition, you may set the slug to an empty string, * otherwise it gets appended e.g. api.example.com/slug */ protected const DOMAINS = []; /** * You may set a migration to be installed on booting e.g Migration::class */ protected const MIGRATION = ''; }
允许子应用程序
如果您的应用程序支持子应用程序,请将 supportsSubapps
属性设置为 true
。
use Tobento\Apps\AppBoot; class DomainFoo extends AppBoot { /** * Specify your app boots: */ protected const APP_BOOT = [ Backend::class, Frontend::class, ]; /** * Set a unique app id. Must be lowercase and * only contain [a-z0-9-] characters. * Furthermore, do not set ids with two dashes such as 'foo--bar' * as supapps id will be separated by two dashes. */ protected const APP_ID = 'domain-foo'; /** * You may set a slug for the routing e.g. example.com/slug/ * Or you may set the slug to an empty string e.g. example.com/ */ protected const SLUG = ''; /** * You may set a domains for the routing e.g. ['api.example.com'] * In addition, you may set the slug to an empty string, * otherwise it gets appended e.g. api.example.com/slug */ protected const DOMAINS = ['example.com']; /** * @var bool */ protected bool $supportsSubapps = true; }
启动应用程序
创建应用程序后,您需要启动您的应用程序
use Tobento\App\AppFactory; // 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(DomainFoo::class); $app->boot(DomainBar::class); $app->boot(Backend::class); // Adding app specific boots: $app->booting(); $app->get(Backend::class)->addBoot(BackendSpecificBoot::class); // Run the app: $app->run();
在启动中使用应用程序的示例
use Tobento\App\Boot; class Blog extends Boot { public const BOOT = [ Backend::class, Frontend::class, ]; public function boot(Backend $backend, Frontend $frontend): void { $backend->addBoot(BlogBackend::class); $frontend->addBoot(BlogFrontend::class); } }
接下来,启动您的 Blog
启动
use Tobento\App\AppFactory; // 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(Blog::class); // Run the app: $app->run();
应用程序配置
应用程序配置位于默认应用程序骨架配置位置的 app/config/apps.php
文件中。
目录结构
目录结构将如下所示
your-project/
app/ #root app
config/
src/
...
apps/
backend/
config/
views/
...
public/
apps/
backend/
assets/
assets/
index.php
vendor/
共享配置
您可以使用 app:root
或 app:parent
目录来共享配置,以指向相同的目录
在应用程序中的每个 config/database.php
'defaults' => [ 'pdo' => 'mysql', 'storage' => 'file', 'shared:storage' => 'shared:file', ], 'databases' => [ 'shared:file' => [ 'factory' => \Tobento\Service\Database\Storage\StorageDatabaseFactory::class, 'config' => [ 'storage' => \Tobento\Service\Storage\JsonFileStorage::class, 'dir' => directory('app:parent').'storage/database/file/', ], ], ],
并在您的应用程序中
use Tobento\Service\Database\DatabasesInterface; $storageDatabase = $app->get(DatabasesInterface::class)->default('shared:storage'); // or $fileDatabase = $app->get(DatabasesInterface::class)->get('shared:file');
访问应用程序
您可以通过使用 AppsInterface::class
并检索所需的应用程序来从另一个应用程序访问应用程序。
use Tobento\Apps\AppBoot; use Tobento\Apps\AppsInterface; use Tobento\Service\Routing\RouterInterface; // Boot the app if it has not booted yet: $app->booting(); // Get the apps: $apps = $app->get(AppsInterface::class); // Get any desired app: var_dump($apps->get('frontend') instanceof AppBoot); // bool(true) $frontendApp = $apps->get('frontend')->app(); $frontendApp->booting(); // For instance, get all frontend app routes: $routes = $frontendApp->get(RouterInterface::class)->getRoutes();
子应用程序
访问父应用程序时,您必须首先启动父应用程序,否则子应用程序将找不到!
use Tobento\Apps\AppsInterface; use Tobento\Service\Routing\RouterInterface; // Boot the app if it has not booted yet: $app->booting(); // Get the apps: $apps = $app->get(AppsInterface::class); // Boot parent app: $apps->get('domain-foo')->app()->booting(); // Get sub app: $frontendApp = $apps->get('domain-foo--frontend')->app(); $frontendApp->booting(); // For instance, get all frontend app routes: $routes = $frontendApp->get(RouterInterface::class)->getRoutes();
控制台
以下命令应在根应用程序控制台运行。
应用程序列表命令
apps:list
命令提供了所有应用程序的概述
php ap apps:list
应用程序命令
使用 apps
命令,您可以在每个应用程序中运行任何命令。
在所有应用程序上运行 route:list
命令
php ap apps route:list
仅在前端和后端应用程序上运行 route:list
命令
php ap apps route:list --aid=frontend --aid=backend
应用程序创建控制台命令
您可以使用 apps:create-console
命令为每个应用程序创建控制台。
php ap apps:create-console
一旦创建,控制台就在每个应用程序目录中可用
your-project/
apps/
backend/
config/
views/
ap #console
测试
当使用 应用程序测试 包时,您需要在 createApp
方法上返回您想要测试的特定应用程序。
use Tobento\App\Testing\TestCase; use Tobento\App\AppInterface; use Tobento\Apps\AppsInterface; final class BackendAppTest extends TestCase { public function createApp(): AppInterface { $app = require __DIR__.'/../app/app.php'; $app->booting(); // Return the app you want to test: return $app->get(AppsInterface::class)->get('backend')->app(); } }
使用临时应用程序
use Tobento\App\Testing\TestCase; use Tobento\App\AppInterface; use Tobento\Apps\AppsInterface; final class BackendAppTest extends TestCase { public function createApp(): AppInterface { $app = $this->createTmpApp(rootDir: __DIR__.'/..'); // Boot your apps: $app->boot(Backend::class); $app->booting(); // Get the app you want to test: $app = $app->get(AppsInterface::class)->get('backend')->app(); // You may boot additional boots for testing: $app->boot(\Tobento\App\Seeding\Boot\Seeding::class); return $app; } }
使用子应用程序的示例
use Tobento\App\Testing\TestCase; use Tobento\App\AppInterface; use Tobento\Apps\AppsInterface; final class BackendAppTest extends TestCase { public function createApp(): AppInterface { $app = $this->createTmpApp(rootDir: __DIR__.'/..'); // Boot your apps: $app->boot(DomainFoo::class); $app->booting(); // Get and boot parent app: $app = $app->get(AppsInterface::class)->get('domain-foo')->app(); $app->booting(); // Get sub app: $app = $app->get(AppsInterface::class)->get('domain-foo--backend')->app(); // You may boot additional boots for testing: $app->boot(\Tobento\App\Seeding\Boot\Seeding::class); return $app; } }