25/08/2018 - SYMFONY
I already have written some examples similar to this but I just wanted add one more. The difference here is that, the configuration file is optional, config root key name has been overriden, namespace is different so on. This example is a Symfony command that accepts some config parameters and just prints them on terminal. That's all!
This is what we will end up with.
.
├── .gitignore
├── composer.json
└── src
├── Command
│ └── DictateStructureCommand.php
├── DependencyInjection
│ ├── Configuration.php
│ ├── ExtensionTrait.php
│ └── StructureDictatorExtension.php
├── Resources
│ └── config
│ └── services.yaml
└── StructureDictatorBundle.php
vendor
composer.lock
{
"name": "inanzzz/structure-dictator",
"type": "symfony-bundle",
"description": "Ensures that the developers follow a certain application development structure",
"license": "MIT",
"require": {
"php": "^7.1",
"symfony/console": "*",
"symfony/dependency-injection": "*",
"symfony/config": "*",
"symfony/http-kernel": "*"
},
"autoload": {
"psr-4": {
"Inanzzz\\StructureDictator\\": "src/"
}
}
}
declare(strict_types=1);
namespace Inanzzz\StructureDictator\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class DictateStructureCommand extends Command
{
private $controller;
private $repository;
private $factory;
public function __construct(
string $controller,
string $repository,
string $factory
) {
parent::__construct();
$this->controller = $controller;
$this->repository = $repository;
$this->factory = $factory;
}
protected function configure()
{
$this
->setName('inanzzz:dictate-structure')
->setDescription('Verifies application development structure');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->write('Dictated'.PHP_EOL);
$output->write($this->controller.PHP_EOL);
$output->write($this->repository.PHP_EOL);
$output->write($this->factory.PHP_EOL);
}
}
declare(strict_types=1);
namespace Inanzzz\StructureDictator\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
class Configuration implements ConfigurationInterface
{
use ExtensionTrait;
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root($this->configRoot);
$rootNode
->children()
->arrayNode($this->configChild)
->addDefaultsIfNotSet()
->children()
->scalarNode($this->configChildController)
->cannotBeEmpty()
->defaultValue('src\Controller')
->end()
->scalarNode($this->configChildRepository)
->cannotBeEmpty()
->defaultValue('src\Repository')
->end()
->scalarNode($this->configChildFactory)
->cannotBeEmpty()
->defaultValue('src\Factory')
->end()
->end()
->end()
->end();
return $treeBuilder;
}
}
declare(strict_types=1);
namespace Inanzzz\StructureDictator\DependencyInjection;
trait ExtensionTrait
{
private $configRoot = 'inanzzz';
private $configChild = 'structure_dictator';
private $configChildController = 'controller';
private $configChildRepository = 'repository';
private $configChildFactory = 'factory';
}
declare(strict_types=1);
namespace Inanzzz\StructureDictator\DependencyInjection;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
class StructureDictatorExtension extends Extension
{
use ExtensionTrait;
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$container->setParameter(
$this->configRoot.'.'.$this->configChild.'.'.$this->configChildController,
$config[$this->configChild][$this->configChildController]
);
$container->setParameter(
$this->configRoot.'.'.$this->configChild.'.'.$this->configChildFactory,
$config[$this->configChild][$this->configChildFactory]
);
$container->setParameter(
$this->configRoot.'.'.$this->configChild.'.'.$this->configChildRepository,
$config[$this->configChild][$this->configChildRepository]
);
$loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yaml');
}
public function getAlias()
{
return $this->configRoot;
}
}
services:
inanzzz.structure_dictator.command.dictate_scructure:
class: Inanzzz\StructureDictator\Command\DictateStructureCommand
tags:
- { name: console.command }
arguments:
$controller: '%inanzzz.structure_dictator.controller%'
$repository: '%inanzzz.structure_dictator.repository%'
$factory: '%inanzzz.structure_dictator.factory%'
declare(strict_types=1);
namespace Inanzzz\StructureDictator;
use Inanzzz\StructureDictator\DependencyInjection\StructureDictatorExtension;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class StructureDictatorBundle extends Bundle
{
public function getContainerExtension()
{
if (null === $this->extension) {
$this->extension = new StructureDictatorExtension();
}
return $this->extension;
}
}
Add block below to main application's composer.json
file. This is compulsory only if you haven't registered your package with packagist site.
{
"repositories": [
{
"type": "git",
"url": "git@github.com:inanzzz/structure-dictator.git"
}
]
}
composer require "inanzzz/structure-dictator:dev-master"
bin/console list | grep inanzzz
inanzzz
inanzzz:dictate-structure Verifies application development structure
bin/console inanzzz:dictate-structure
Dictated
src\Controller
src\Repository
src\Factory
You can override values below by creating a configuration file under config/packages
directory as seen below.
# config/packages/inanzzz.yaml
inanzzz:
structure_dictator:
controller: 'src\App\Controller'
repository: 'src\App\Repository'
factory: 'src\App\Factory'
Let's test our command again.
bin/console inanzzz:dictate-structure
Dictated
src\App\Controller
src\App\Repository
src\App\Factory
Your config file can be configured in many ways as seen below. If any key is missing the default value will be used by the package.
# Empty file
inanzzz:
inanzzz:
structure_dictator: ~
inanzzz:
structure_dictator:
controller: 'src\App\Controller'
inanzzz:
structure_dictator:
controller: 'src\App\Controller'
repository: 'src\App\Repository'
inanzzz:
structure_dictator:
controller: 'src\App\Controller'
repository: 'src\App\Repository'
factory: 'src\App\Factory'