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而有自己的目录和功能。