Skip to content

Instantly share code, notes, and snippets.

@yuki777
Last active September 17, 2021 06:51
Show Gist options
  • Select an option

  • Save yuki777/2f16f59f637a348bcd87da7ddfc47284 to your computer and use it in GitHub Desktop.

Select an option

Save yuki777/2f16f59f637a348bcd87da7ddfc47284 to your computer and use it in GitHub Desktop.
bear-sunday-tutorial1-php8-v2.bash
#!/bin/bash
set -eux
## Usage:
# cd /tmp
# composer create-project bear/skeleton MyVendor.Weekday
# What is the vendor name ? MyVendor
# What is the project name ? Weekday
# wget https://gist.github.com/yuki777/2f16f59f637a348bcd87da7ddfc47284/raw/df38a01423ba9b4b49fc8e590905f9fc5c3f56f4/bear-sunday-tutorial1-php8-v2.bash
# /bin/bash ./bear-sunday-tutorial1-php8-v2.bash
# composer.jsonを変更して https://github.com/koriym/BEAR.Package/tree/scan-binding-update を使う
rm -f composer.lock vendor
$(cat << 'EOF' > composer.json
{
"name": "my-vendor/weekday",
"type": "project",
"license": "proprietary",
"description": "",
"repositories": [
{
"type": "vcs",
"url": "https://github.com/koriym/BEAR.package"
}
],
"require": {
"php": "^8.0.0",
"ext-json": "*",
"bear/aura-router-module": "^2.0",
"bear/dotenv": "^1.0",
"bear/package": "dev-scan-binding-update as 1.10",
"bear/resource": "^1.15",
"bear/sunday": "^1.5",
"ray/aop": "^2.10",
"ray/di": "^2.11"
},
"require-dev": {
"bear/api-doc": "1.x-dev",
"bear/devtools": "^0.1",
"bamarni/composer-bin-plugin": "^1.4",
"phpunit/phpunit": "^9.5",
"roave/security-advisories": "dev-master"
},
"autoload": {
"psr-4": {
"MyVendor\\Weekday\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"MyVendor\\Weekday\\": "tests/"
}
},
"scripts": {
"post-update-cmd": "@setup",
"post-install-cmd": "@composer bin all install --ansi",
"setup": "php bin/setup.php",
"compile": "./vendor/bin/bear.compile 'MyVendor\\Weekday' prod-app ./",
"doc": "./vendor/bin/apidoc",
"test": "./vendor/bin/phpunit",
"coverage": "php -dzend_extension=xdebug.so -dxdebug.mode=coverage ./vendor/bin/phpunit --coverage-text --coverage-html=build/coverage",
"pcov": "php -dextension=pcov.so -d pcov.enabled=1 ./vendor/bin/phpunit --coverage-text --coverage-html=build/coverage --coverage-clover=coverage.xml",
"cs": "./vendor/bin/phpcs",
"cs-fix": "./vendor/bin/phpcbf src tests",
"metrics": "./vendor/bin/phpmetrics --report-html=build/metrics --exclude=Exception src",
"clean": [
"./vendor/bin/phpstan clear-result-cache",
"./vendor/bin/psalm --clear-cache",
"rm -rf ./var/tmp/*.php"
],
"sa": [
"./vendor/bin/phpstan analyse -c phpstan.neon",
"psalm --show-info=true"
],
"tests": [
"@cs",
"@sa",
"@test"
],
"build": [
"@clean",
"@cs",
"@sa",
"@pcov",
"@compile",
"@metrics"
],
"serve": "php -dzend_extension=xdebug.so -S 127.0.0.1:8080 -t public",
"app": "php bin/app.php",
"page": "php bin/page.php"
},
"scripts-descriptions": {
"setup": "Setup the project",
"compile": "Compile scripts for the production",
"doc": "Generate API document",
"test": "Run unit tests",
"tests": "Run tests and quality checks",
"coverage": "Generate test coverage report",
"pcov": "Generate test coverage report (pcov)",
"cs": "Checks the coding standard",
"cs-fix": "Fix the coding standard",
"sa": "Run static analysis",
"metrics": "Build metrics report",
"clean": "Clear cache files",
"serve": "Start built-in server",
"app": "Request app resource",
"page": "Request page resource"
},
"config": {
"sort-packages": true,
"process-timeout": 0
}
}
EOF
)
# リソース
mkdir -p src/Resource/App/
$(cat << 'EOF' > src/Resource/App/Weekday.php
<?php
declare(strict_types=1);
namespace MyVendor\Weekday\Resource\App;
use BEAR\Resource\ResourceObject;
use DateTimeImmutable;
class Weekday extends ResourceObject
{
public function onGet(int $year, int $month, int $day): static
{
$dateTime =DateTimeImmutable::createFromFormat('Y-m-d', "$year-$month-$day");
$weekday = $dateTime->format('D');
$this->body = ['weekday' => $weekday];
return $this;
}
}
EOF
)
# テストコード
mkdir -p tests/Resource/App
$(cat << 'EOF' > tests/Resource/App/WeekdayTest.php
<?php
declare(strict_types=1);
namespace MyVendor\Weekday\Resource\App;
use BEAR\Resource\ResourceInterface;
use MyVendor\Weekday\Injector;
use PHPUnit\Framework\TestCase;
class WeekdayTest extends TestCase
{
private ResourceInterface $resource;
protected function setUp(): void
{
$injector = Injector::getInstance('app');
$this->resource = $injector->getInstance(ResourceInterface::class);
}
public function testOnGet(): void
{
$ro = $this->resource->get('app://self/weekday', ['year' => '2001', 'month' => '1', 'day' => '1']);
$this->assertSame(200, $ro->code);
$this->assertSame('Mon', $ro->body['weekday']);
}
}
EOF
)
# 例外作成
mkdir -p src/Exception
$(cat << 'EOF' > src/Exception/InvalidDateTime.php
<?php
declare(strict_types=1);
namespace MyVendor\Weekday\Exception;
use RuntimeException;
class InvalidDateTime extends RuntimeException
{
}
EOF
)
# App/Weekday
$(cat << 'EOF' > src/Resource/App/Weekday.php
<?php
declare(strict_types=1);
namespace MyVendor\Weekday\Resource\App;
use BEAR\Resource\ResourceObject;
use DateTimeImmutable;
use MyVendor\Weekday\Exception\InvalidDateTime;
class Weekday extends ResourceObject
{
public function onGet(int $year, int $month, int $day): static
{
$dateTime = DateTimeImmutable::createFromFormat('Y-m-d', "$year-$month-$day");
if (! $dateTime instanceof DateTimeImmutable) {
throw new InvalidDateTime("$year-$month-$day");
}
$weekday = $dateTime->format('D');
$this->body = ['weekday' => $weekday];
return $this;
}
}
EOF
)
# テストコード
mkdir -p tests/Resource/App
$(cat << 'EOF' > tests/Resource/App/WeekdayTest.php
<?php
declare(strict_types=1);
namespace MyVendor\Weekday\Resource\App;
use BEAR\Resource\ResourceInterface;
use MyVendor\Weekday\Injector;
use PHPUnit\Framework\TestCase;
class WeekdayTest extends TestCase
{
private ResourceInterface $resource;
protected function setUp(): void
{
$injector = Injector::getInstance('app');
$this->resource = $injector->getInstance(ResourceInterface::class);
}
public function testOnGet(): void
{
$ro = $this->resource->get('app://self/weekday', ['year' => '2001', 'month' => '1', 'day' => '1']);
$this->assertSame(200, $ro->code);
$this->assertSame('Mon', $ro->body['weekday']);
}
public function tesInvalidDateTime(): void
{
$this->expectException(InvalidDateTime::class);
$this->resource->get('app://self/weekday', ['year' => '-1', 'month' => '1', 'day' => '1']);
}
}
EOF
)
# Install aura router
composer require bear/aura-router-module:'^2.0'
# App module
$(cat << 'EOF' > src/Module/AppModule.php
<?php
declare(strict_types=1);
namespace MyVendor\Weekday\Module;
use BEAR\Dotenv\Dotenv;
use BEAR\Package\AbstractAppModule;
use BEAR\Package\PackageModule;
use BEAR\Package\Provide\Router\AuraRouterModule;
use function dirname;
class AppModule extends AbstractAppModule
{
protected function configure(): void
{
(new Dotenv())->load(dirname(__DIR__, 2));
$appDir = $this->appMeta->appDir;
$this->install(new AuraRouterModule($appDir . '/var/conf/aura.route.php'));
$this->install(new PackageModule());
}
}
EOF
)
# router file
mkdir -p var/conf
$(cat << 'EOF' > var/conf/aura.route.php
<?php
/**
* @see http://bearsunday.github.io/manuals/1.0/ja/router.html
* @var \Aura\Router\Map $map
*/
$map->route('/weekday', '/weekday/{year}/{month}/{day}');
EOF
)
# ここまではOK
php bin/app.php get /weekday/1981/09/08
# MyLoggerInterface
$(cat << 'EOF' > src/MyLoggerInterface.php
<?php
declare(strict_types=1);
namespace MyVendor\Weekday;
interface MyLoggerInterface
{
public function log(string $message): void;
}
EOF
)
# リソース
mkdir -p src/Resource/App/
$(cat << 'EOF' > src/Resource/App/Weekday.php
<?php
namespace MyVendor\Weekday\Resource\App;
use BEAR\Resource\ResourceObject;
use MyVendor\Weekday\MyLoggerInterface;
class Weekday extends ResourceObject
{
public function __construct(public MyLoggerInterface $logger)
{
}
public function onGet(int $year, int $month, int $day) : ResourceObject
{
$weekday = \DateTime::createFromFormat('Y-m-d', "$year-$month-$day")->format('D');
$this->body = [
'weekday' => $weekday
];
$this->logger->log("$year-$month-$day {$weekday}");
return $this;
}
}
EOF
)
# MyLogger実装
$(cat << 'EOF' > src/MyLogger.php
<?php
declare(strict_types=1);
namespace MyVendor\Weekday;
use BEAR\AppMeta\AbstractAppMeta;
use function error_log;
use const PHP_EOL;
class MyLogger implements MyLoggerInterface
{
private string $logFile;
public function __construct(AbstractAppMeta $meta)
{
$this->logFile = $meta->logDir . '/weekday.log';
}
public function log(string $message): void
{
error_log($message . PHP_EOL, 3, $this->logFile);
}
}
EOF
)
# App module
$(cat << 'EOF' > src/Module/AppModule.php
<?php
declare(strict_types=1);
namespace MyVendor\Weekday\Module;
use BEAR\Dotenv\Dotenv;
use BEAR\Package\AbstractAppModule;
use BEAR\Package\PackageModule;
use BEAR\Package\Provide\Router\AuraRouterModule;
use MyVendor\Weekday\MyLogger;
use MyVendor\Weekday\MyLoggerInterface;
use function dirname;
class AppModule extends AbstractAppModule
{
protected function configure(): void
{
(new Dotenv())->load(dirname(__DIR__, 2));
$appDir = $this->appMeta->appDir;
$this->install(new AuraRouterModule($appDir . '/var/conf/aura.route.php'));
$this->bind(MyLoggerInterface::class)->to(MyLogger::class);
$this->install(new PackageModule());
}
}
EOF
)
# test => error
php bin/app.php get /weekday/2011/05/23
# test => OK
# rm -fr var/tmp
# php bin/app.php get /weekday/2011/05/23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment