Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/230.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 在非';一捆_Php_Symfony - Fatal编程技术网

Php 在非';一捆

Php 在非';一捆,php,symfony,Php,Symfony,我正在为Symfony应用程序构建一个捆绑包,该应用程序使用了我编写的几个不同组件。我将把这个包称为MyAppBundle 我的bundle使用的组件本身并不依赖于Symfony,但我希望能够为每个组件定义一组Symfony服务,这些服务将在每个单独包的services.yml文件中定义,但我不希望这些包成为完整的bundle 为什么??因为我不希望软件包依赖于Symfony框架,我不想将软件包结构化为Symfony捆绑包,我希望能够通过注册单个MyAppBundle来注册我的应用程序所需的所有

我正在为Symfony应用程序构建一个捆绑包,该应用程序使用了我编写的几个不同组件。我将把这个包称为MyAppBundle

我的bundle使用的组件本身并不依赖于Symfony,但我希望能够为每个组件定义一组Symfony服务,这些服务将在每个单独包的services.yml文件中定义,但我不希望这些包成为完整的bundle

为什么??因为我不希望软件包依赖于Symfony框架,我不想将软件包结构化为Symfony捆绑包,我希望能够通过注册单个MyAppBundle来注册我的应用程序所需的所有服务,同时,如果我愿意,我可以灵活地在一个无关的Symfony应用程序中使用这些组件提供的服务。如果我将这些包制作成完整的包,那么我必须在我的AppKernel中单独加载每个包,这是我不想要的

这应该很容易-根据文档,我只需要构建一个容器扩展:

因此,我为我的组件创建了一个容器扩展以加载其服务定义:

namespace MyComponent;

class MyComponentExtension extends \Symfony\Component\DependencyInjection\Extension\Extension
{

    public function load(array $configs, ContainerBuilder $container)
    {
        $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
        $loader->load('services.yml');
    }

}
我只是不确定如何从MyAppBundle加载此扩展?关于如何从另一个bundle加载扩展的信息似乎很少。也许这不是推荐的做事方式,但出于上述原因,我认为我的用例是合理的

到目前为止,我从MyAppBundle加载MyComponentExtension的最佳尝试是:

namespace MyAppBundle;

class MyAppBundle extends Bundle
{

    public function build(ContainerBuilder $container)
    {
        $extensions = array(
            new MyComponentExtension(),
            new MyOtherComponentExtension()
        );
        $aliases = array();
        foreach($extensions as $extension) {
            $container->registerExtension($extension);
            $aliases[] = $extension->getAlias();
        }
        $container->addCompilerPass(new MergeExtensionConfigurationPass($aliases));
    }

}

“addCompilerPass”是从我能找到的一些小信息中收集到的,我敢肯定它是错的。执行此操作时,我无法访问MyComponentExtension提供的服务。我非常确定我只需要确保定义被正确地编译到容器中,但我不确定如何做到这一点

有两种类型的耦合:硬耦合和软耦合。 那么你就有了脱钩

解耦

当您将组件从捆绑包中解耦时,您可以使每个部分依赖于一个公共接口()

或者您可以具有单向依赖关系。在这种情况下,捆绑包将依赖于组件。一个示例是依赖于Symfony组件的Symfony框架包

对于第一个示例,您将使用配置来定义要使用的类。 然后,在第二个示例中,您将为组件的类定义捆绑包中的服务。同样,这就是Symfony框架包的作用

软耦合

这是指一个库引用另一个库(或另一个库的抽象),但不需要它(除非您尝试使用它,之后它间接成为硬依赖)。例如,如果缺少提供附加功能的资源,则会忽略这些附加功能

例如,将依赖项注入放在组件中,提供对Symfony的支持,但不需要它

例如,请查看
Symfony\Bridge\doctor\DependencyInjection\AbstractDoctrineExtension

常见的策略是创建一个抽象扩展,然后在bundle中重写它。 如果需要进一步集成,则捆绑包可以覆盖组件的部分()

任意一种方式

理想的情况是组件可以自己使用(),并且只使用Symfony将它们作为服务引导

解耦

Bundle => depends on => Component
Component depends on nothing
软依赖

Bundle => depends on => Component  
Component -> supports -> Symfony
但是,您永远不应该创建一个双向依赖项。也就是说,每个部分静态地相互依赖

根据以下方式进行编辑:

你可以,尽管你为什么要这么做对我来说仍然是个谜

class MyAppBundle extends Bundle
{
    /**
     * Override extension getter.
     */
    public function getContainerExtension()
    {
        if(null === $this->extension) {
            $this->extension = new My\Component\Extension();
        }

        return $this->extension;
    }
}

你可能会让事情变得更难。MyAppExtension可以轻松地从组件库加载services.yml。不需要组件扩展

class MyAppBundleExtension extends Extension
{
    public function load(array $configs, ContainerBuilder $container)
    {
        $loader = new Loader\YamlFileLoader($container, 
            new FileLocator('path_to_component_library'));
        $loader->load('services.yml');
    }
获取组件库的路径是唯一的小挑战,但即使是硬编码,也不会太糟糕

说到这里,你真的应该考虑把桥牌捆绑到你的图书馆里去。它真正需要的只是一个Bundle类、扩展类和services.yml文件。您的库本身可以保持原样


桥是Symfony 2框架用来访问诸如Twig和Doctrine之类的库的东西。很肯定它们也会为你的图书馆工作。以:vendor/symfony/monolog bundle为例。下面是我最后选择的解决方案。我使用静态buildContainer方法在MyComponent中创建了一个loader类:

<?php

namespace MyComponent;

use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;

class MyComponentLoader
{

    /**
     * Loads component services into a container.
     *
     * @param ContainerBuilder $container
     */
    public static function buildContainer(ContainerBuilder $container)
    {
        $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/Resources/config'));
        $loader->load('services.yml');
    }

}

感谢您提供了信息丰富的答案。事实上,我希望MyComponentExtension只对Symfony具有软依赖性,但您的回答没有告诉我如何从MyAppBundle正确注册我的ComponentExtension!在您给出的AbstractDoctrineExtension示例中,您仍然需要一个DoctrineBundle,它必须从AppKernel类中单独加载-这是我希望避免的情况,因为MyAppBundle应该加载MyComponentExtension本身。是的,但是
Doctrine\Bundle\DoctrineBundle\DependencyInjection\DoctrineExtension
在bridge中扩展了
AbstractDoctrineExtension
。我理解,但是DoctrineExtension是DoctrineBundle的一部分,只能通过注册DoctrineBundle来加载。我的问题是-我可以在我的应用程序中注册一个扩展,而不将该扩展作为捆绑包的一部分吗?更新以显示如何做到这一点。我先前的回答是试图让你们回到忠诚的道路上:这与我最终选择的方法有些相似。通过在我的组件中使用静态加载程序方法,我避免了硬编码路径。不制作桥接捆绑包的原因是我只想在AppKernel中加载一个捆绑包,而不需要单独加载其他依赖捆绑包
<?php

namespace MyAppBundle\DependencyInjection;

use MyComponent\MyComponentLoader;
use MyOtherComponent\MyOtherComponentLoader;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;

class SmartCloneExtension extends Extension
{

    public function load(array $configs, ContainerBuilder $container)
    {
        MyComponentLoader::buildContainer($container);
        MyOtherComponentLoader::buildContainer($container);
    }

}