关于Bundle的那些事

什么是Bundle

  • Bundle在你的项目里是一等公民
  • 事实上SF2自己就是一个Bundle
  • 最小程度的粘合剂 用于集成类库/命令行工具到SF2

Bundle能干啥哟

  • 提供控制器 example: Controller
  • 提供命令行 example: app/console command tool
  • 提供ORM实体(Entities)或者文档(Documents)
  • 提供服务(Services)
  • 提供Assets文件(js css img)

第三方Bundles的索引: knpbundles.com (其实我更喜欢packagist.org)

自动索引相似Bundle的代码

遵循下面的这些规则 会给bundle生成必定的分数

  • 每新增一个github的followers都有加分 (+1分)
  • README.md超过300个字也能加分 (+5分)
  • 若是使用CI持续集成也能加分 (+5分)
  • 若是travisCI上build的status都是ok的加分 (+5分)
  • 提供composer包的加分 (+5分)
  • 在KnpBundles每有一我的推荐你的bundle加分 (+5分)
  • 每一个月都最少要在github上提交一次

Knpbundles索引大全长啥样

请输入图片描述

(其实packagist.org更好用:)请输入图片描述)php

小哥 若是你有天心血来潮要写本身的bundle 请先上knp跟packagist看看是否是已经有了相似的bundle 有的话 请fork它 帮助它改善的更稳定更强大 这样能节约你的时间css

Bundle开发最好的实践 : Bundle的目录结构

AcmeMyBundle.php
Command
    MyCommand.php
Controller
    MyController.php
Doctrine
    ORM
        Foo.php
        FooRepository.php
Model
    Foo.php
Resources
    config
    doc
    meta
    public
    views
...

参考CMF : Bundle Standards git

Bundle开发最好的实践 : DIC 设置

  • 全部的service前缀都用Bundle的别名 (eg : AcmeMyExtension::getAlias() )
  • 任何参数都显式处理
  • 使用compiler传递对其它Bundle服务的做用
DependencyInjection 
    Compiler
        MyCompilerPass.php
    Configuration.php
    AcmeMyExtension.php
use Symfony\C..\D..I..\ContainerBuilder as CB;
use Symfony\C..\Config\FileLocator;
use Symfony\C..\HttpKernel\D..I..\Extension;
use Symfony\..\D..I..\Loader\XmlFileLoader;

class AcmeMyExtension extends Extension
{
    public function load(array $configs, CB $dic)
    {
        $configuration = new Configuration();
        $config = $this->processConfiguration(
            $configuration, $configs
        );

        $dir = __DIR__ . '/../Resources/config';
        $locator = new FileLocator($dir);
        $loader = new XmlFileLoader($dic, $locator);
        $loader->load('services.xml');

        foreach ($config as $key => $val) {
            $dic->setParameter('acme_my.'.$key, $val);
        }
    }
}

Bundle开发最好的实践 : 设置一个class

  • 合并同时验证Bundle的设置参数
  • Sf2.1+ : app/console config:dump-reference
use Symfony\C..\Config\Definition as Def;

class Configuration implements Def\ConfigurationInterface
{
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new Def\Builder\TreeBuilder();

        $treeBuilder->root('acme_my')
        ->children()
            ->scalarNode('host')
                ->isRequired()->cannotBeEmpty()->end()
            ->scalarNode('port')
                ->defaultValue(2000)->end()
            ->scalarNode('timeout')
                ->defaultValue(30000)->end()
        ->end()
        ;

        return $treeBuilder;
    }
}

Bundle开发最好的实践 : Composer包设置

  • 用packagist建立你的composer索引
  • Bundle要在packagist上注册过
  • 肯定开启了packagist提交钩子
{
    "name": "acme/my-bundle",
    "type": "symfony-bundle",
    "description": "This Bundle is an example",
    "license": "MIT",
    "authors": [
        {
            "name": "Duffy Duck",
            "email": "diffy@acme.com"
        }
    ],
    "require": {
        "php":                      ">=5.3.3",
        "symfony/framework-bundle": "~2.2",
    },
    "autoload": {
        "psr-0": { "Acme\\MyBundle": "" }
    },
    "target-dir": "Acme/MyBundle"
}

Bundle开发最好的实践 : 测试

  • JMSCommandBundle能够生成函数式测试的kernel代码
  • 测试

    Controller
    MyControllerTest.php
    Functional
    HomepageTest.php
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class HomepageTest extends WebTestCase
{
    public function testContents()
    {
        $client = $this->createClient();
        $crawler = $client->request('GET', '/');
        $s = $client->getResponse()->getStatusCode();
        $this->assertEquals(200, $s);

        $crawler->filter('h1:contains(Homepage)');
        $this->assertCount(1, $count);
        $crawler->filter('ul.menu_main li')
        $this->assertCount(13, $count);
    }
}

Bundle开发最好的实践 : 持续集成 travisCI

  • 项目根目录下建立.travis.yml文件
  • 开启github钩子来自动测试
  • 多个版本的PHP,类库,数据库的测试
  • fork这个项目以后能够很简单的测试
language: php

php:
    - 5.3
    - 5.4
    - 5.5

env:
  - SYMFONY_VERSION=2.2.*
  - SYMFONY_VERSION=2.3.*
  - SYMFONY_VERSION=dev-master

before_script:
  - composer require symfony/symfony:${SYMFONY_VERSION} --prefer-source
  - vendor/symfony-cmf/testing/bin/travis/phpcr_odm_doctrine_dbal.sh

script: phpunit --coverage-text