如果真的一切都在Symfony的2.x的捆绑? [英] Should everything really be a bundle in Symfony 2.x?

查看:96
本文介绍了如果真的一切都在Symfony的2.x的捆绑?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我所知道的像<一个问题href=\"http://stackoverflow.com/questions/7958346/an-exact-description-of-a-symfony-bundle-in-a-complex-web-application\">this,人们倾向于讨论捆绑的一般的Symfony 2的概念。

I'm aware of questions like this, where people tend to discuss the general Symfony 2 concept of bundle.

问题是,在一个特定的应用程序一样,比如,类似Twitter的应用程序,应该一切真的是一个普通的包里面,像的official文档说什么?

The thing is, in a specific application, like, for instance, a twitter-like application, should everything really be inside a generic bundle, like the official docs say?

我问这个的原因是因为当我们开发应用程序,在一般情况下,我们不希望以高度的情侣我们的code到一些全栈胶框架。

The reason I'm asking this is because when we develop applications, in general, we don't want to highly couple our code to some full-stack glue framework.

如果我开发一个基于Symfony的2应用,在某些时候,我决定的Symfony 2是不是真的是最好的选择的继续发展将会的,那将是一个问题吗?

If I develop a Symfony 2 based application and, at some point, I decide Symfony 2 is not really the best choice to keep the development going, will that be a problem for me?

所以,一般的问题是:为什么一切都被捆​​绑的好事吗?

So the general question is: why is everything being a bundle a good thing?

编辑#1

快一年了,因为现在我问这个问题,我写了<一个href=\"http://dribeiro.ghost.io/2013/02/28/yes-you-can-have-low-coupling-in-a-symfony-standard-edition-application/\">article分享关于这一主题我的知识。

Almost a year now since I asked this question I wrote an article to share my knowledge on this topic.

推荐答案

我已经写了关于这一主题进行更彻底的和更新的博客文章:的http://elnur.pro/symfony-without-bundles/

I've written a more thorough and updated blog post on this topic: http://elnur.pro/symfony-without-bundles/

不,不是一切都在一个包。你可以有这样的结构:

No, not everything has to be in a bundle. You could have a structure like this:


  • 的src /供应商/型号 - 适用机型,

  • 的src /供应商/控制器 - 为控制器,

  • 的src /供应商/服务 - 对服务,

  • 的src /供应商/捆绑 - 分发包,如的src /供应商/包/的appbundle


  • src/Vendor/Model — for models,
  • src/Vendor/Controller — for controllers,
  • src/Vendor/Service — for services,
  • src/Vendor/Bundle — for bundles, like src/Vendor/Bundle/AppBundle,
  • etc.

这样的话,你会放在的appbundle 只有东西,真的是Symfony2的具体。如果您决定后切换到另一个框架,你会摆脱捆绑命名空间,并与所选框架的东西取代它。

This way, you would put in the AppBundle only that stuff that is really Symfony2 specific. If you decide to switch to another framework later, you would get rid of the Bundle namespace and replace it with the chosen framework stuff.

请注意,什么我建议这里是应用具体code。可重复使用的包,我还是建议使用的最佳实践的。

Please note that what I'm suggesting here is for app specific code. For reusable bundles, I still suggest using the best practices.

要保持的src /供应商/型号实体捆绑任何外面,我已经改变了学说部分在 config.yml

To keep entities in src/Vendor/Model outside of any bundle, I've changed the doctrine section in config.yml from

doctrine:
    # ...
    orm:
        # ...
        auto_mapping: true

doctrine:
    # ...
    orm:
        # ...
        mappings:
            model:
                type: annotation
                dir: %kernel.root_dir%/../src/Vendor/Model
                prefix: Vendor\Model
                alias: Model
                is_bundle: false

实体的名字 - 从学说存储库访问 - 以模式开始在这种情况下,例如,型号:用户

Entities's names — to access from Doctrine repositories — begin with Model in this case, for example, Model:User.

您可以使用子名称将相关实体在一起,例如,的src /供应商/用户/ Group.php 。在这种情况下,实体的名称是型号:用户\\组

You can use subnamespaces to group related entities together, for example, src/Vendor/User/Group.php. In this case, the entity's name is Model:User\Group.

首先,你需要告诉 JMSDiExtraBundle 扫描的src 文件夹通过将其加入服务 config.yml

First, you need to tell JMSDiExtraBundle to scan the src folder for services by adding this to config.yml:

jms_di_extra:
    locations:
        directories: %kernel.root_dir%/../src

然后定义控制器,服务,并把它们在控制器命名空间:

Then you define controllers as services and put them under the Controller namespace:

<?php
namespace Vendor\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use JMS\DiExtraBundle\Annotation\Service;
use JMS\DiExtraBundle\Annotation\InjectParams;
use JMS\SecurityExtraBundle\Annotation\Secure;
use Elnur\AbstractControllerBundle\AbstractController;
use Vendor\Service\UserService;
use Vendor\Model\User;

/**
 * @Service("user_controller", parent="elnur.controller.abstract")
 * @Route(service="user_controller")
 */
class UserController extends AbstractController
{
    /**
     * @var UserService
     */
    private $userService;

    /**
     * @InjectParams
     *
     * @param UserService $userService
     */
    public function __construct(UserService $userService)
    {
        $this->userService = $userService;
    }

    /**
     * @Route("/user/add", name="user.add")
     * @Template
     * @Secure("ROLE_ADMIN")
     *
     * @param Request $request
     * @return array
     */
    public function addAction(Request $request)
    {
        $user = new User;
        $form = $this->formFactory->create('user', $user);

        if ($request->getMethod() == 'POST') {
            $form->bind($request);

            if ($form->isValid()) {
                $this->userService->save($user);
                $request->getSession()->getFlashBag()->add('success', 'user.add.success');

                return new RedirectResponse($this->router->generate('user.list'));
            }
        }

        return ['form' => $form->createView()];
    }

    /**
     * @Route("/user/profile", name="user.profile")
     * @Template
     * @Secure("ROLE_USER")
     *
     * @param Request $request
     * @return array
     */
    public function profileAction(Request $request)
    {
        $user = $this->getCurrentUser();
        $form = $this->formFactory->create('user_profile', $user);

        if ($request->getMethod() == 'POST') {
            $form->bind($request);

            if ($form->isValid()) {
                $this->userService->save($user);
                $request->getSession()->getFlashBag()->add('success', 'user.profile.edit.success');

                return new RedirectResponse($this->router->generate('user.view', [
                    'username' => $user->getUsername()
                ]));
            }
        }

        return [
            'form' => $form->createView(),
            'user' => $user
        ];
    }
}

请注意,我用我的 ElnurAbstractControllerBundle 来简化定义控制器,服务。

Note that I'm using my ElnurAbstractControllerBundle to simplify defining controllers as services.

最后一件事左边是告诉Symfony的寻找模板,而无需捆绑。我这样做,通过覆盖模板猜测者服务,但由于方法是Symfony的2.0和2.1之间是不同的,我对他们俩的提供的版本。

The last thing left is to tell Symfony to look for templates without bundles. I do this by overriding the template guesser service, but since the approach is different between Symfony 2.0 and 2.1, I'm providing versions for both of them.

我创建了一个捆绑,做了你。

I've created a bundle that does that for you.

首先,定义类:

<?php
namespace Vendor\Listener;

use InvalidArgumentException;
use Symfony\Bundle\FrameworkBundle\Templating\TemplateReference;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Sensio\Bundle\FrameworkExtraBundle\EventListener\TemplateListener as FrameworkExtraTemplateListener;
use JMS\DiExtraBundle\Annotation\Service;

class TemplateListener extends FrameworkExtraTemplateListener
{
    /**
     * @param array   $controller
     * @param Request $request
     * @param string  $engine
     * @throws InvalidArgumentException
     * @return TemplateReference
     */
    public function guessTemplateName($controller, Request $request, $engine = 'twig')
    {
        if (!preg_match('/Controller\\\(.+)Controller$/', get_class($controller[0]), $matchController)) {
            throw new InvalidArgumentException(sprintf('The "%s" class does not look like a controller class (it must be in a "Controller" sub-namespace and the class name must end with "Controller")', get_class($controller[0])));

        }

        if (!preg_match('/^(.+)Action$/', $controller[1], $matchAction)) {
            throw new InvalidArgumentException(sprintf('The "%s" method does not look like an action method (it does not end with Action)', $controller[1]));
        }

        $bundle = $this->getBundleForClass(get_class($controller[0]));

        return new TemplateReference(
            $bundle ? $bundle->getName() : null,
            $matchController[1],
            $matchAction[1],
            $request->getRequestFormat(),
            $engine
        );
    }

    /**
     * @param string $class
     * @return Bundle
     */
    protected function getBundleForClass($class)
    {
        try {
            return parent::getBundleForClass($class);
        } catch (InvalidArgumentException $e) {
            return null;
        }
    }
}

然后告诉Symfony的加入这使用它 config.yml

parameters:
    jms_di_extra.template_listener.class: Vendor\Listener\TemplateListener

使用模板,而无需捆绑

现在,您可以使用模板进行捆绑。让他们在应用程序/资源/视图文件夹下。例如,对于从例如控制器的那些两个动作模板以上位于

Using templates without bundles

Now, you can use templates out of bundles. Keep them under the app/Resources/views folder. For example, templates for those two actions from the example controller above are located in:


  • 应用程序/资源/视图/用户/ add.html.twig

  • 应用程序/资源/视图/用户/ profile.html.twig

  • app/Resources/views/User/add.html.twig
  • app/Resources/views/User/profile.html.twig

当提到一个模板,只是省略了包的一部分:

When referring to a template, just omit the bundle part:

{% include ':Controller:view.html.twig' %}

这篇关于如果真的一切都在Symfony的2.x的捆绑?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆