Návrh modulů a závislostí
- Phalanx
- Člen | 310
Ahoj, rád bych se zeptal, jak řešíte následující věc:
Mám hodně modulů:
ShopModule
- FrontModule
- AdminModule
- Shop.php
BlogModule
- FrontModule
- Blog.php
a další
A pak například chci vygenerovat sitemapu, ale nechci tam vkládat každý modul samostatně viz:
<?php
class Sitemap {
/** @var Shop @inject */
protected $shop;
/** @var Blog @inject */
protected $blog;
public function()
{
$urls = array();
$urls[] = $this->shop->getUrls();
$urls[] = $this->blog->getUrls();
return $urls;
}
}
?>
Lze na tento problém nějak použít dědičnost?
<?php
abstract class X {
abstract function getUrls();
}
class Shop extends X
{
public function getUrls() {
...
return $urls;
}
}
class Blog extends X
{
public function getUrls() {
...
return $urls;
}
}
class Sitemap {
public function()
{
$urls = array();
$urls[] = "všechny třídy co rozšiřují třídu X";
return $urls;
}
}
?>
Děkuju za Váš čas
- CZechBoY
- Člen | 3608
Takhle to spíš vypadá, že ta třída implementuje nějakej interface
(metoda getUrls).
Najít si jaký třídy implementujou interface (třeba z DIC) je jednoduchá
věc a nemusíš se starat ani o případné závislosti.
$serviceNames = $container->findByType(MujInterface::class);
$moduleUrlsFinders = [];
foreach ($serviceNames as $serviceName) {
$moduleUrlsFinders[] = $container->getService($serviceName);
}
// následuje tvůj kod
foreach ($moduleUrlsFinders as $moduleUrlFinder) {
$urls[] = $moduleUrlFinder->getUrls();
}
- Jan Endel
- Člen | 1016
Ahoj,
to co hledáš je spíše interface:
interface ISiteLinksProvider
{
public getSiteLinks(): array;
}
pak totiž můžeš vytvořit třídy:
class ShopModuleSiteLinksProvider implements ISiteLinksProvider
{
public getSiteLinks(): array
{
//...
}
}
class BlogModuleSiteLinksProvider implements ISiteLinksProvider
{
public getSiteLinks(): array
{
//...
}
}
pak mít třídu, co tyhle linky vrátí hromadně:
class Sitemap
{
/**
* @var array|ISiteLinksProvider[]
*/
private $providers = [];
public addProvider(ISiteLinksProvider $provider)
{
$this->providers[] = $provider;
}
public function getUrl()
{
//...
}
}
a pak asi nejelegantnější a nejjednoduší bude DI Container extension, co ti to naplní podle interface:
class ApplicationExtension extends Nette\DI\CompilerExtension
{
public function beforeCompile()
{
$builder = $this->getContainerBuilder();
$linksProviders = $builder->findByType(ISiteLinksProvider::class);
$sitemap = $builder->getDefinition($builder->getByType(Sitemap::class));
foreach ($linksProviders as $linkProvider) {
$sitemap->addSetup('addProvider', [$linkProvider]);
}
}
}