etten/app

Etten\App

v3.0.2 2018-03-10 08:28 UTC

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')