etten / app
v3.0.2
2018-03-10 08:28 UTC
Requires
- php: >=7.0
- nette/application: ^2.4
- nette/bootstrap: ^2.4
- nette/di: ^2.4
- nette/robot-loader: ^2.4
Requires (Dev)
- etten/codestyle: ^2.0
- kdyby/console: ^2.6
- kdyby/doctrine: ^3.1
- phpunit/phpunit: ^6.0
- squizlabs/php_codesniffer: ~2.6.0
README
此软件包为 etten/sandbox 提供工具。
应用
- 不要为您的应用编写冗长的引导代码 - 使用 App 帮助您创建清晰的代码。
- 配置在配置文件中设置,而不是在 PHP 代码中。
- 可以通过扩展提供额外的
Nette\Configurator
配置,而不是直接在冗长的引导 PHP 文件中。 - 以下是一个示例。
<?php
// app/bootstrap.php
namespace App;
use Etten;
require __DIR__ . '/../vendor/autoload.php';
// Create with a root directory path (for path mappings)
$app = new Etten\App\App(__DIR__ . '/..');
// Load boostrap configuration file
$app->addBootstrapFile(__DIR__ . '/config/bootstrap.neon');
// Load Nette application configuration
$app->addConfigFile(__DIR__ . '/config/config.neon');
// Local-specific config, eg. database credentials
// You can redefine it when you add another config with the same name ("local")
$app->addConfigFile(__DIR__ . '/config/config.local.neon', 'local');
// Load optional Extension which helps you keep this bootstrap file clean
$app->addExtension(new Etten\App\Extensions\SystemSetup());
return $app;
# app/config/bootstrap.neon
parameters:
# configure directory paths
appDir: %rootDir%/app
logDir: %rootDir%/log
tempDir: %rootDir%/temp
wwwDir: %rootDir%/www
developer:
# Run in development state for specific IPs
hosts:
- localhost
- 127.0.0.1
- ::1
# Additionally you can set secret token which is read prior to IP address
# Token is read from POST or COOKIE "etten-maintainer-token" parameter.
token: ''
configurator:
developer: %developer%
# Directories which are controlled by Nette\Loaders\RobotLoader
load:
- %appDir%
# CleanerCommand configuration (cache invalidation).
cleaner:
# Directories to purge.
# Defaults are %tempDir%/cache, %tempDir%/proxies
purge:
- %tempDir%/custom-cache-directory
# Ignore file patterns (like git).
# Defaults are .gitignore, .gitkeep
ignore:
- .notempty
# Cleaners are triggered when cache:clean commmand is executed.
# See \Etten\App\App for defaults.
cleaners:
- Etten\App\Cleaner\CleanerImpl
开发和生产模式
- 在生产模式和开发(=调试)模式下,App 的行为不同。
- 在生产中,错误不会显示给用户,但会被记录。没有人会看到数据库查询和其他调试信息。
- 在开发模式下,错误以 HTML 页面的形式显示(不进行记录),您可以看到包含有趣信息的调试栏。
- 有关更多信息,请参阅 Tracy 官方文档。
- App 帮助您进行条件模式切换。 它根据您的配置自动切换开发和生产模式。
- 您可以通过 主机名 强制开发模式。您可以在适当的配置部分
parameters -> developer -> hosts
中配置开发主机(参见上面的示例)。 - 您可以通过 带有秘密令牌的 COOKIE 强制开发模式。您可以在适当的配置部分
parameters -> developer -> token
中配置秘密令牌(参见上面的示例)。
维护
App
提供了维护您的应用的助手。您可以通过App::createMaintainer()
获取它。App\Maintenance\Maintainer
允许您为特定的动作(如应用关闭、迁移启动器、应用打开等)简单地添加事件监听器。
不使用维护者加载 App
<?php
// web/index.php
namespace Etten\App;
// Uncomment following line for turn-off an App
//return require __DIR__ . '/.maintenance.php';
/** @var App $app */
$app = require __DIR__ . '/../app/bootstrap.php';
$app->run();
使用维护者加载 App
<?php
// web/index.php
namespace Etten\App;
use Etten\App\Maintenance;
/** @var App $app */
$app = require __DIR__ . '/../app/bootstrap.php';
$maintainer = $app->createMaintainer();
$locker = $app->createLocker();
// Lock the Application
$maintainer->addJob('disable', function () use ($locker) {
$locker->lock();
exit;
});
// Clean caches, setup, migrations, warm-up.
$maintainer->addJob('enable', function () use ($app) {
// Clean all caches.
(new Maintenance\Cleaner($app))->clean();
// If you have Doctrine 2.
(new Maintenance\Console($app))->run('orm:generate-proxies');
// Run new migrations.
(new Maintenance\Console($app))->run('migrations:continue');
});
// Unlock the Application - it's ready.
$maintainer->addJob('enable', function () use ($locker) {
$locker->unlock();
exit;
});
$maintainer->runJobs();
// If locked, show a Maintenance site, otherwise run the App.
if ($locker->isLocked()) {
require __DIR__ . '/.maintenance.php';
} else {
$app->run();
}
您可以通过两种方式触发维护者的工作
- CLI 脚本,例如
php web/index.php maintainer:disable
,其中disable
是上面定义的工作。 - HTTP 请求,例如
https://example.com/?etten-maintainer-job=disable
。
因此,我们触发了 disable
作业。在我们的例子中,Maintenance\Locker
创建了一个锁。当存在锁时,应用不会启动并返回状态码 503。
当您触发 enable
作业(CLI 或 HTTP)时,Maintenance\Cleaner
清除所有必要的缓存,Maintenance\Console
运行一个 Symfony/Console 命令 migrations:continue
(必须注册到我们的 App 的 DI 容器中)。
HTTP 作业 仅在白名单 IP 或带有秘密令牌的请求上触发。它们可以通过配置文件定义 - App 的引导。
当可能时,请优先使用 CLI 作业(例如,通过 SSH)。
Nette DI 扩展
Etten\App
还提供了有用的 Nette DI 容器扩展。
CleanerExtension
这允许您通过 CLI 轻松清除所有缓存。
如上所述,维护者内部使用与 CleanerExtension 相同的 Console\Command。
因此,您也可以通过 CLI 以相同的方式删除所有缓存。
您必须在配置文件中注册扩展
# app/config.neon
extensions:
etten.cleaner: Etten\App\DI\CleanerExtension
然后您就可以通过 CLI 运行命令,例如。
php web/index.php cache:clean
具体路径取决于您使用 Etten\App 的实际应用。
测试(以下代码是为PHPUnit编写的)
- 在你的应用程序中,你应该创建测试(而不是像这个没有测试的包)。
- 当您创建集成测试时,您可能需要一个
Nette\DI\Container
实例。 - 在理想情况下,它应该像真实应用程序一样配置。
- 使用此包,您可以创建以下测试引导文件。
<?php
// tests/boostrap.php
namespace Tests;
use Etten;
/** @var Etten\App\App $app */
$app = require __DIR__ . '/../app/bootstrap.php';
// Store created App instance for TestCase which provides Nette\DI\Container instance
Etten\App\Tests\ContainerTestCase::$app = $app;
// Set additional bootstrap configuration
$app->addBootstrapFile(__DIR__ . '/bootstrap.neon');
// Rewrite "local" configuration file (we don't need exactly the same DB, cache, ...)
$app->addConfigFile(__DIR__ . '/config.local.neon', 'local');
return $app;
# tests/bootstrap.neon
parameters:
# reconfigure some directory paths
testDir: %rootDir%/tests
logDir: %rootDir%/tests/log
tempDir: %rootDir%/tests/temp
configurator:
load:
- %testDir%
单元测试(不需要DI\Container)
- 只需像往常一样创建测试。
- 您可以直接通过
\PHPUnit_Framework_TestCase
或\Etten\App\Tests\TestCase
扩展您的 TestCase。
集成测试(需要DI.Container)
- 创建 TestCase 并通过
\Etten\App\Tests\ContainerTestCase
扩展它。 - 它提供了一个
$container
属性,其中存储了\Nette\DI\Container
实例。
演示者测试(需要DI.Container)
- 因为 Nette 框架 是一个 MVP 框架,所以我们有特殊的类来处理 HTTP 请求/响应 - 演示者。
- 如果您通过
\Etten\App\Tests\PresenterTestCase
扩展您的 TestCase,您可以轻松测试它们。 - 示例测试可能如下所示。
<?php
namespace Tests;
use App;
use Etten;
use Nette;
class HomepagePresenterTest extends Etten\App\Tests\PresenterContainerTestCase
{
protected function getPresenterName():string
{
// You must configure FQN of currently tested Presenter
return 'Front:Homepage';
}
public function testHandleDelete()
{
// You can test signals
$response = $this->runSignal('delete');
$this->assertInstanceOf(Nette\Application\Responses\RedirectResponse::class, $response);
}
public function testRenderDefault()
{
// And actions too
$response = $this->runAction();
$this->assertInstanceOf(Nette\Application\Responses\TextResponse::class, $response);
}
}
Doctrine 测试(需要DI.Container)
- 创建 TestCase 并通过
\Etten\App\Tests\DoctrineTestCase
扩展它。 - 它提供了一个
$em
属性,其中存储了\Doctrine\ORM\EntityManager
实例。 - 您也可以轻松设置 SQL 固定数据 - 只需调用
$this->loadFixture(__DIR__ . '/fixture.sql')
。