Symfony2 概念问题:通用捆绑包与特定捆绑包 [英] Symfony2 conceptual issue: general bundles vs. specific ones

查看:36
本文介绍了Symfony2 概念问题:通用捆绑包与特定捆绑包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Symfony 最佳实践回答了我的大部分问题.

the Symfony best practices answer most of my questions.

我有几个关于我的 Symfony2 应用的问题.

I have several questions concerning my Symfony2 app.

它将有一个前端和一个后端,它们将使用一些通用代码(例如日期显示器、分页器、一些经常使用的模板等).

It will have a frontend and a backend, and they will use some common code (such as a date displayer, paginator, some templates often used, etc).

因此,我创建了一个 FrontendBundle 和一个 BackendBundle,每个都包含例如它们各自的布局.第一个问题:为前端和后端创建包是一种好的做法,这些包是通用"包,甚至没有控制器?

So, I created one FrontendBundle and one BackendBundle, each containing for example their respective layout. First question: is that good practice to create bundles for frontend and backend, which are "general" bundles which won't even have a controller?

第二个问题:我在一本食谱上读到我不应该把我的布局放在包里,而是放在 app/Resources/views/目录中.我已经有一个 base.html.twig 文件,我想知道我是否也应该把我的布局也放在那里,就像一个 frontend_layout.html.twig 文件?

Second question: I read on a cookbook that I should not put my layouts in bundles, but in the app/Resources/views/ directory. I already have a base.html.twig file in it, and I wonder if I should put my layouts in there too, like a frontend_layout.html.twig file?

我创建了一个名为 RootBundle 的包,它将包含我的应用程序在前端和后端所需的一切.这是一个好习惯吗?或者我应该为每个提议的功能创建一个专用包,例如 PaginatorBundle、DateDisplayerBundle 等?我有一个杂项"包,其中包含我不知道放在哪里的所有内容,这听起来很奇怪.你是怎么做到的?

I created a bundle named RootBundle, which would contain everything my app needs in frontend AND backend. Is that a good practice or not? Or I should create a dedicated bundle for each functionality proposed, such as a PaginatorBundle, a DateDisplayerBundle, etc? It sounds weird that I have one "miscellaneous" bundle containing everything I don't know where to put. How do you do that?

推荐答案

新方法

自从我写下这个答案几个月后,我的方法发生了变化,所以我要与社区分享.这个答案仍然很受欢迎,可以引导新人采用我认为不再是最好的方法.所以...

The new approach

After several months since I wrote this answer, my approach has changed, so I'm sharing it with the community. This answer is still pretty popular and can lead newcomers to the approach I don't think is the best one anymore. So...

现在我只有一个应用特定包,我称之为AppBundle.旧方法存在几个问题,以下是其中一些问题:

Now I have only one app specific bundle and I call it AppBundle. There were several problems with the old approach and here are some of them:

  • 创建大量的bundle很乏味.你必须为每个新bundle创建一个bundle类和一堆标准文件夹,然后激活它并注册它的路由和DI等等.

  • Creating a lot of bundles is tedious. You have to create a bundle class and a bunch of standard folders for each new bundle and then activate it and register its routes and DI and whatnot.

不必要的核心决策过程.有时您无法决定特定事物属于哪个捆绑包,因为它被多个捆绑包使用.在你花了半天时间并最终做出了把它放在哪里的艰难决定之后,你会发现在几天或几周内你将无法立即分辨出该放在哪个包里——因为大多数时候决定不是基于纯粹的逻辑,你必须根据掷硬币或任何你用来带来更高权力寻求帮助的方式来选择.

Unnecessary hardcore decision making process. Sometimes you just can't decide which bundle a particular thing belongs to because it's used by more than one bundle. And after you spend a half a day and finally make your hard decision on where to put it, you'll find that in a couple of days or weeks you won't be able to tell right away which bundle to look that thing in — because most of the times the decision wasn't based on pure logic and you had to choose based on a coin toss or whatever means you use to bring higher powers for help.

过去我建议将 CommonBundle 用于常见的东西,但这样做你必须做很多不必要的重构,将一个东西移入和移出 CommonBundle 基于以后有多少包会使用那个东西.

I suggested using CommonBundle for common stuff in the past but doing that you'll have to do a lot of unnecessary refactorings moving a thing to and from CommonBundle based on how many or few bundles will use that thing later.

无论如何,特定于应用程序的捆绑包是相互依赖的.当人们第一次遇到捆绑包的想法时,他们脑海中闪过的一个主要想法是耶!我会给我一堆可重复使用的包!"这个想法很棒,我不反对;问题是特定于应用程序的包无论如何都不是可重用的——它们是相互依赖的.忘记在这种情况下的重用.

App specific bundles are interdependent anyway. When people meet the idea of bundles for the first time, one of the main thought that goes through their minds is something like "Yay! I'll have me a bunch of reusable bundles!" That idea is great and I have nothing against it; the problem is that app specific bundles are not that reusable anyway — there are interdependent. Forget about reuse in this case.

不知道把 Behat 功能和步骤定义放在哪里. 这个问题与之前的相关:您必须为每个捆绑重复相同的无脑动作,然后做出核心决定.

No idea where to put Behat features and step definitions. This problem is related to the previous ones: you have to repeat the same brainless motions for each bundle and then make hardcore decisions.

当我开始编写 Behat 功能时,我无法决定将很多功能和步骤定义放在哪里,因为它们一次属于多个包.将它们放入 CommonBundle 似乎更糟,因为这是我要在其中查找这些东西的最后一个包.所以,我最终为此创建了 FeatureBundle.

When I started writing Behat features, I just couldn't decide where to put a lot of features and step definitions because they belonged to several bundles at a time. Putting them into CommonBundle seemed to be even worse, because that's the last bundle I would look for that stuff in. So, I ended up creating FeatureBundle for that.

切换到单个捆绑包解决了所有这些问题.

Switching to a single bundle solved all these problems.

我还看到有些人有一个单独的包,比如所有实体.我也不喜欢这种方法,实际上 建议将实体和其他非 Symfony2 特定的东西放在包中.

I've also seen some people having a separate bundle for, say, all the entities. I don't like this approach neither and actually suggest keeping entities and other non Symfony2 specific stuff out of the bundles.

再次注意,这种新方法适用于特定于应用程序的捆绑包.官方文档和其他地方对如何构建旨在与他人共享并在众多项目中重用的包提供了很好的建议.我也写过这种类型的包.但我在 Symfony2 项目上工作数月后发现,用于重用的包和特定于应用程序的包之间存在差异——一种方法并不适合所有.

Note again that this new approach applies to app specific bundles. Official docs and other places are full of great advice on how to structure bundles intended to be shared with others and reused across numerous projects. I write bundles of this type as well. But what I've found out after months of working on Symfony2 projects is that there is a difference between the bundles intended for reuse and the app specific ones — one approach doesn't fit all.

当然,当您在特定于应用的捆绑包中看到可重用的东西时,只需将其提取出来,放在单独的存储库中并作为供应商安装.

And, of course, when you see something reusable emerging in your app specific bundle, just extract it, put it in a separate repo and install as a vendor.

此外,我发现自己更积极地使用子命名空间作为逻辑分区包的一种方式 - 而不是为此创建一堆包并经历所有这些麻烦.

Also I've found myself using subnamespaces much more actively as a way to partition the bundle logically — instead of creating a bunch of bundles for that and going through all those troubles.

没有硬性规定或灵丹妙药,但我会分享我做事的方法——也许它会给你一两个见解.

There are no hard and fast rules or silver bullets, but I'll share my approach of doing things — maybe it will give you an insight or two.

首先,我没有像 FrontendBundleBackendBundle 这样的两个包罗万象的包.相反,我的包同时具有前端和后端控制器、视图等.因此,如果我从 UserBundle 中删除除控制器和视图之外的所有内容,其结构将如下所示:

First of all, I don't have two all-encompassing bundles like FrontendBundle and BackendBundle. Instead, my bundles have both frontend and backend controllers, views, etc. So, if I strip everything from my UserBundle except for controllers and views, its structure would look like this:

UserBundle
├── Controller
│   ├── Admin
│   │   └── UserController.php
│   └── UserController.php
├── Resources
│   └── views
│       ├── Admin
│       │   └── User
│       │       ├── add.html.twig
│       │       ├── delete.html.twig
│       │       ├── edit.html.twig
│       │       ├── form.html.twig
│       │       └── index.html.twig
│       └── User
│           ├── edit.html.twig
│           ├── sign-in.html.twig
│           ├── sign-up.html.twig
│           └── view.html.twig
└── UserBundle.php

其次,我有 CommonBundle 用于多个包共享的内容:

Second, I have CommonBundle which I use for stuff shared by several bundles:

CommonBundle
├── Resources
│   ├── public
│   │   ├── css
│   │   │   ├── admin.css
│   │   │   ├── common.css
│   │   │   └── public.css
│   │   └── img
│   │       ├── add.png
│   │       ├── delete.png
│   │       ├── edit.png
│   │       ├── error.png
│   │       ├── return.png
│   │       ├── success.png
│   │       └── upload.png
│   └── views
│       ├── Admin
│       │   └── layout.html.twig
│       └── layout.html.twig
└── CommonBundle.php

我的 app/Resources/views/base.html.twig 几乎与 Symfony 标准发行版相同:

My app/Resources/views/base.html.twig is almost the same as it comes with Symfony Standard distribution:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>{{ block('title') | striptags | raw }}</title>
        {% block stylesheets %}{% endblock %}
    </head>
    <body>
        {% block body %}{% endblock %}
        {% block javascripts %}{% endblock %}
    </body>
</html>

CommonBundle/Resources/views/layout.htmlCommonBundle/Resources/views/Admin/layout.html 都扩展了 app/Resources/views/base.html.twig.其他包的模板扩展了这两种布局之一,具体取决于它们是用于前端还是后端.基本上,这就是我如何使用 三级继承方法.

Both CommonBundle/Resources/views/layout.html and CommonBundle/Resources/views/Admin/layout.html extend app/Resources/views/base.html.twig. Other bundles' templates extend one of these two layouts, depending on whether they are for frontend or backend. Basically, this is how I'm using the Three-level Inheritance approach.

所以,我会将您的日期显示器放入 CommonBundle.根据其复杂性,它可能只是一个模板、Twig 扩展名.

So, I'd put your date displayer into CommonBundle. Depending on its complexity it could be just a template, a macro or a Twig extension.

分页是一个常见问题,因此我建议您使用 现有 bundles 而不是重新发明轮子——当然,如果它们满足您的需求.

Pagination is a common problem, so I suggest you to use one of the existing bundles instead of reinventing the wheel — if they suite your needs, of course.

是的,没有控制器或视图等的包是完全可以的.

And yes, it's perfectly okay to have bundles without controllers or views, etc.

这篇关于Symfony2 概念问题:通用捆绑包与特定捆绑包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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