Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
rvanlaak committed Jan 17, 2022
0 parents commit a75203b
Show file tree
Hide file tree
Showing 22 changed files with 206 additions and 0 deletions.
10 changes: 10 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/vendor/
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
Symfony CLI Minimum Skeleton
============================

Thi CLI project skeleton tempts to require the least amount of code needed to write a command line interface project
based on Symfony Console.

The folder structure follow a simple Domain Driven Design application structure by suggesting splitting Application,
Domain, UserInterface, and Infrastructure responsibilities.

The minimum of features that is needed for developing CLI applications is included:

* [Auto-wiring](https://symfony.com/doc/current/service_container/autowiring.html) on all classes in `/src`
* Autoconfigure `Command` implementations directly to the CLI console application
* [PHPUnit](https://phpunit.de/)

## How to run tests?

Running PHPUnit test suites is possible by running `composer run tests`. The `/tests` folder gets auto-registered by
composer, and follows the DDD application structure, but no actual tests are provided with the skeleton.

## How to register a command to the CLI console?

Registering a command to the CLI application is the only autoconfiguration available in this skeleton, as can be found
in `config/services.php`.

* Create a class (preferably in `/src/UserInterface/Cli`) and let it extend `Symfony\Component\Console\Command\Command`
* Run `bin/console`, the command created became available

## Environment requirements

* PHP `>=8.0.2` with `ext-mbstring` extension enabled
* [Composer](https://getcomposer.org/)
10 changes: 10 additions & 0 deletions bin/console
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env php
<?php

use App\Application;

require dirname(__DIR__).'/vendor/autoload.php';
$container = require dirname(__DIR__).'/config/bootstrap.php';

$application = $container->get(Application::class);
exit($application->run());
27 changes: 27 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"require": {
"php": ">=8.0.2",
"ext-mbstring": "*",
"symfony/dependency-injection": "^6.0",
"symfony/console": "^6.0",
"symfony/config": "^6.0"
},
"require-dev": {
"roave/security-advisories": "dev-latest",
"phpunit/phpunit": "^9.5"
},
"scripts": {
"app:example": "bin/console app:example 'John Doe'",
"test": "vendor/bin/phpunit"
},
"autoload": {
"psr-4": {
"App\\": ["src"]
}
},
"autoload-dev": {
"psr-4": {
"App\\": ["tests"]
}
}
}
20 changes: 20 additions & 0 deletions config/bootstrap.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace App;

require_once \dirname(__DIR__).'/vendor/autoload.php';

use Symfony\Component\Config\FileLocator;
use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;

$container = new ContainerBuilder();
$container->addCompilerPass(new AddConsoleCommandPass());

$loader = new PhpFileLoader($container, new FileLocator(__DIR__));
$loader->load(__DIR__.'/services.php');

$container->compile();

return $container;
23 changes: 23 additions & 0 deletions config/services.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace App;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use function Symfony\Component\DependencyInjection\Loader\Configurator\tagged_iterator;

return static function (ContainerConfigurator $configurator) {
$services = $configurator->services();
$services
->defaults()
->autoconfigure()
->autowire()
;

$services->instanceof(Command::class)->tag('console.command');

$services->load(__NAMESPACE__.'\\', '../src/*');
$services->get(Application::class)
->args([tagged_iterator('console.command')])
->public();
};
32 changes: 32 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
backupGlobals="false"
cacheResult="true"
failOnWarning="true"
colors="true"
bootstrap="tests/bootstrap.php"
executionOrder="random"
>
<coverage processUncoveredFiles="true" cacheDirectory=".coverage-cache">
<include>
<directory suffix=".php">src</directory>
</include>
</coverage>

<php>
<ini name="error_reporting" value="-1"/>
<ini name="memory_limit" value="512M" />
<server name="APP_ENV" value="test" force="true"/>
<server name="SHELL_VERBOSITY" value="-1"/>
<server name="SYMFONY_PHPUNIT_VERSION" value="9.5"/>
</php>

<testsuites>
<testsuite name="unit">
<directory>tests/Unit</directory>
</testsuite>
<testsuite name="functional">
<directory>tests/Functional</directory>
</testsuite>
</testsuites>
</phpunit>
15 changes: 15 additions & 0 deletions src/Application.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace App;

use Symfony\Component\Console\Application as BaseApplication;

final class Application extends BaseApplication
{
public function __construct(\Traversable $commands)
{
$this->addCommands(iterator_to_array($commands));

parent::__construct(__NAMESPACE__, '1.0.0');
}
}
Empty file added src/Application/.gitkeep
Empty file.
Empty file added src/Domain/.gitkeep
Empty file.
Empty file added src/Infrastructure/.gitkeep
Empty file.
30 changes: 30 additions & 0 deletions src/UserInterface/Cli/Command/ExampleCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace App\UserInterface\Cli\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

final class ExampleCommand extends Command
{
public function __construct()
{
parent::__construct('app:example');
}

protected function configure()
{
$this->addArgument('name', InputArgument::REQUIRED, 'Name of the one running the example command.');
}

protected function execute(InputInterface $input, OutputInterface $output)
{
$name = $input->getArgument('name');

$output->writeln("<info>Hello worl, my name is $name.</info>");

return self::SUCCESS;
}
}
Empty file.
Empty file.
Empty file.
Empty file.
Empty file added tests/Unit/Application/.gitkeep
Empty file.
Empty file added tests/Unit/Domain/.gitkeep
Empty file.
Empty file.
Empty file.
6 changes: 6 additions & 0 deletions tests/bootstrap.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

$_SERVER['APP_ENV'] = 'test';
putenv('APP_ENV=test');

require dirname(__DIR__).'/config/bootstrap.php';

0 comments on commit a75203b

Please sign in to comment.