Last active
November 16, 2024 09:38
-
-
Save FaKleiser/a8b2c98586f2b939890fc448eda70f91 to your computer and use it in GitHub Desktop.
CompactBundle for DDD applications with Symfony. See this blog post for more information: http://www.fabian-kleiser.de/blog/domain-driven-design-with-symfony-a-folder-structure
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Fk\Core\Infrastructure\Bundle; | |
use Symfony\Component\HttpKernel\Bundle\Bundle; | |
/** | |
* The compact bundle combines a bundle definition with an {@link ExtensionInterface} to provide sound defaults for | |
* implementing custom bundles. | |
*/ | |
abstract class CompactBundle extends Bundle | |
{ | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getContainerExtension() | |
{ | |
return new CompactBundleExtension($this); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Fk\Core\Infrastructure\Bundle; | |
use Symfony\Component\Config\FileLocator; | |
use Symfony\Component\DependencyInjection\Container; | |
use Symfony\Component\DependencyInjection\ContainerBuilder; | |
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; | |
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; | |
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; | |
/** | |
* Provides an {@link ExtensionInterface} and {@link PrependExtensionInterface} implementation for {@link | |
* CompactBundle}s. Defines conventions to be used among bundles. | |
*/ | |
class CompactBundleExtension implements ExtensionInterface, PrependExtensionInterface | |
{ | |
/** @var CompactBundle the associated bundle */ | |
private $bundle; | |
public function __construct(CompactBundle $bundle) | |
{ | |
$this->bundle = $bundle; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function load(array $config, ContainerBuilder $container) | |
{ | |
$configDir = new FileLocator($this->bundle->getPath() . '/Resources/config'); | |
$loader = new YamlFileLoader($container, $configDir); | |
$loader->load("services.yml"); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getAlias() | |
{ | |
return Container::underscore($this->bundle->getName()); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getXsdValidationBasePath() | |
{ | |
return false; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getNamespace() | |
{ | |
return 'http://example.org/schema/dic/' . $this->getAlias(); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function prepend(ContainerBuilder $container) | |
{ | |
$this->prependDoctrineMappingConfiguration($container); | |
$this->prependJmsSerializerConfiguration($container); | |
} | |
/** | |
* Configures doctrine to add mapping files if doctrine config files are stored within this compact bundle in: | |
* <Bundle>/Resources/config/doctrine | |
* | |
* @param ContainerBuilder $container | |
*/ | |
private function prependDoctrineMappingConfiguration(ContainerBuilder $container) | |
{ | |
$doctrineConfigs = sprintf('%s/Resources/config/doctrine', $this->bundle->getPath()); | |
if (is_dir($doctrineConfigs)) { | |
$ns = $this->bundle->getNamespace(); | |
$container->prependExtensionConfig('doctrine', [ | |
'orm' => [ | |
'mappings' => [ | |
$this->bundle->getName() => [ | |
'type' => 'yml', | |
'dir' => 'Resources/config/doctrine', | |
'prefix' => substr($ns, 0, strrpos($ns, '\\')) . '\\Domain', | |
], | |
] | |
] | |
]); | |
} | |
} | |
/** | |
* Configures JMS serializer to add mapping files if serializer config files are stored within this compact bundle in | |
* <Bundle>/Resources/config/serializer | |
* | |
* @param ContainerBuilder $container | |
*/ | |
private function prependJmsSerializerConfiguration(ContainerBuilder $container) | |
{ | |
$serializerConfigs = sprintf('%s/Resources/config/serializer', $this->bundle->getPath()); | |
if (is_dir($serializerConfigs)) { | |
$ns = $this->bundle->getNamespace(); | |
$container->prependExtensionConfig('jms_serializer', [ | |
'metadata' => [ | |
'directories' => [ | |
$this->bundle->getName() => [ | |
'namespace_prefix' => substr($ns, 0, strrpos($ns, '\\')), | |
'path' => sprintf('@%s/Resources/config/serializer', $this->bundle->getName()), | |
], | |
] | |
] | |
]); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Fk\Core\Infrastructure\Bundle; | |
use Psr\Log\LoggerInterface; | |
use Symfony\Component\Config\Loader\Loader; | |
use Symfony\Component\HttpKernel\KernelInterface; | |
use Symfony\Component\Routing\RouteCollection; | |
/** | |
* Automatically loads routing configuration in compact bundles to favor convention over configuration. | |
* | |
* Currently loads: | |
* | |
* - <Bundle>/Resources/config/routing.yml | |
*/ | |
class CompactBundleRouteLoader extends Loader | |
{ | |
/** @var KernelInterface required to access bundles */ | |
private $kernel; | |
/** @var LoggerInterface */ | |
private $log; | |
/** @var bool stores whether the routes have already been loaded */ | |
private $loaded = false; | |
/** | |
* Provide access to kernel in order to load bundle routes. | |
*/ | |
public function __construct(KernelInterface $kernel, LoggerInterface $log) | |
{ | |
$this->kernel = $kernel; | |
$this->log = $log; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function load($resource, $type = null) | |
{ | |
if (true === $this->loaded) { | |
throw new \RuntimeException('Do not add the "convention" loader twice'); | |
} | |
$collection = new RouteCollection(); | |
foreach ($this->kernel->getBundles() as $bundle) { | |
if (!$bundle instanceof CompactBundle) { | |
continue; | |
} | |
$routing = sprintf("%s/Resources/config/routing.yml", $bundle->getPath()); | |
if (!file_exists($routing)) { | |
$this->log->debug('Compact bundle "{bundle}" has no routes defined.', [ | |
'bundle' => $bundle->getName() | |
]); | |
continue; | |
} | |
$collection->addCollection($this->import($routing, 'yaml')); | |
$this->log->debug('Loaded routes for compact bundle "{bundle}".', [ | |
'bundle' => $bundle->getName() | |
]); | |
} | |
return $collection; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function supports($resource, $type = null) | |
{ | |
return 'convention' === $type; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment