Bundle系统
bundle类似于其他软件中的插件,但却更好。关键区别在于:Symfony中的每一样东西都是bundle,包括框架核心功能,以及你编写的程序代码。bundle是Symfony体系中的一等公民。这就给了你一个弹性架构,既可以使用 第三方bundle 中的预建功能,也可以发布你自己的bundle。bundle可以让你在自己的程序中挑选“开启哪个功能”变得很容易,还能按你的方式来优化之。
在本文中你可以学到bundle基础知识,“最佳实践”中有大章节专注于bundle的组织和最佳实践。
一个bundle,就是一组结构化的文件,存于一个“用于实现某个独立功能”的目录中。你可以创建一个BlogBundle,一个ForumBundle,或者是一个管理用户的bundle(很多类似bundle已经作为开源项目存在)。每个目录都包含着关乎那个功能的所有东西,包括php文件,模板,css,js文件,tests,以及其他。每一个功能的子项都存在于bundle中,每一个功能都存在于bundle中。
要在你的程序中使用bundle,必须通过 AppKernel
类的 registerBundles()
方法来注册并使用它们:
// app/AppKernel.phppublic function registerBundles(){ $bundles = array( new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), new Symfony\Bundle\SecurityBundle\SecurityBundle(), new Symfony\Bundle\TwigBundle\TwigBundle(), new Symfony\Bundle\MonologBundle\MonologBundle(), new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(), new Symfony\Bundle\DoctrineBundle\DoctrineBundle(), new Symfony\Bundle\AsseticBundle\AsseticBundle(), new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(), new AppBundle\AppBundle(), ); if (in_array($this->getEnvironment(), array('dev', 'test'))) { $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle(); $bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle(); $bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle(); } return $bundles;
registerBundles()
方法可以让你完全控制在程序中使用哪个bundle(包括Symfony的核心bundle)。
bundle可以存在于任何地方,只要它能够被自动加载(通过 app/autoload.php
中所配置的自动加载器实现)
创建一个Bundle ¶
Symfony标准版内置了超好用的命令,用来帮你创建全功能bundle。当然,手动创建bundle也一样容易。
为了展示一个简单的bundle系统,我们创建一个全新的AcmeTestBundle并开启它。
Acme
部分只是个假名,实战中应被一些“vendor”名字替换掉,以代表你或者你所在的组织(比如ABCTestBundle代表某个名为 ABC
的公司)
从新建一个 src/Acme/TestBundle/
目录开始,再新建一个 AcmeTestBundle.php
文件:
// src/Acme/TestBundle/AcmeTestBundle.phpnamespace Acme\TestBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; class AcmeTestBundle extends Bundle { }
AcmeTestBundle遵守 bundle命名约定。你可以选择简化bundle名称为TestBundle,通过把类名改为TestBundle(同时修改文件名为 TestBundle.php
)
这个空类就是你在创建全新bundle时,唯一需要的东西。尽管一般情况下确实是空的,但这个类格外强大,专门用于定制该bundle的各种行为。
现在你已经创建了bundle,在AppKernel
类中开启它:
// app/AppKernel.phppublic function registerBundles(){ $bundles = array( // ... // register your bundle / 注册你的bundle new Acme\TestBundle\AcmeTestBundle(), ); // ... return $bundles;}
尽管目前啥也没做,AcmeTestBundle已经可以使用。
就这么简单,Symfony也提供了命令行界面,用于生成一个基本的bundle骨架:
$ php bin/console generate:bundle --namespace=Acme/TestBundle
bundle骨架包括控制器、模板和路由资源等,而且都可以自定义。在后面的Symfony命令行工具小节,你可以学到更多。
不管是创建新bundle还是使用第三方bundle,应确保bundle被 registerBundles()
开启。当使用 generate:bundle
命令时,Symfony替你注册完成了。
Bundle目录结构 ¶
bundle目录是简单而有弹性的。默认条件下,bundle系统遵循着一组命名约定,以保持所有Symfony bundle的代码一致性。看一眼AcmeDemoBundle,它包括了一个bundle最常见的某些元素:
Controller/
- 里面有该bundle的控制器(如 `RandomController.php`)。
DependencyInjection/
- 里面有特定的Dependency Injection Extension类,用来导入服务配置信息,注册compiler passes,以及更多内容(这个目录并非必需)。
Resources/config/
- 存放配置信息,包括路由配置(`routing.yml` 等)。
Resources/views/
- 存放模板。依控制器名字来组织子文件夹(如 `Hello/index.html.twig`)。
Resources/public/
- 存放web assets资源(图片,css等),将通过硬拷贝或symlink方式导入到项目的 `web/` 目录,通过console命令 `assets:install` 实现。
Tests/
- 存放本bundle的所有测试类。
一个bundle依其实现的功能而或小或大。它只包含你需要的文件,再无其他。
在你通读中文指南的过程中,你将学到如何持久化对象到数据库中,创建和验证表单,为程序增加翻译功能,编写测试,以及更多内容。所有这些,都是基于bundle而有自己的目录和功能。