Symfony2学习笔记之插件格式分析

本文讲述了Symfony2的插件格式。分享给大家供大家参考,具体如下:

一个bundle类似于其它框架中的插件,但是比插件表现更好。它跟其它框架最主要的不同是在Symfony2中所有东西都是bundle,包括核心框架功能和你写的所有应用程序代码。Symfony2中,bundle可是一等公民。这给了你使用其它第三方开发的内容包或者分发你自己的bundle更多灵活性。你可以方便的选择哪些内容可以应用到你的程序中那些不用,来根据你的想法优化它们。

一个bundle就是一个目录,它具有很好的结构性,它能存放从类到controller和web资源等任何东西。

一个bundle仅仅是一个结构化的文件目录集合,它实现一个单一的内容。

你可以创建一个BlogBundle,一个ForumBundle或者一个实现用户管理的bundle(好像已经有很多此类开源的bundle了)。每个bundle目录包含跟实现内容有关的所有东西,包括PHP文件,模板,样式表,javascript文件,测试内容以及其它任何相关的东西。要实现的内容的各方面都保存在一个bundle中。

一个应用程序是由在AppKernel类中registerBundles()方法里定义的所有bundle组成。

// app/AppKernel.php
public 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 JMS\SecurityExtraBundle\JMSSecurityExtraBundle(),
  );
  if (in_array($this->getEnvironment(), array('dev', 'test'))) {
    $bundles[] = new Acme\DemoBundle\AcmeDemoBundle();
    $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
    $bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
    $bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
  }
  return $bundles;
}

在这里你可以通过该方法来统一控制和管理你的应用程序组成。

一个bundle可以存放在任何目录下,只需要能够通过配置app/autoload.php文件中的自动加载器即可被自动加载。

创建一个bundle

Symfony2标准版中已经为你准备好了一全功能的创建bundle的工具文件。你可以运行它来创建bundle的所有内容,当然你也可以

选择自己手工创建。现在我们创建一个AcmeTestBundle并让它能够在我们的应用程序中工作。注意,这里的Acme是一个虚假的提供商名字,你完全可以替换它为你自己组织或公司的名字。

首先,创建一个src/Acme/TestBundle/ 目录并添加新文件AcmeTestBundle.php

// src/Acme/TestBundle/AcmeTestBundle.php
namespace Acme\TestBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class AcmeTestBundle extends Bundle
{
}

接下来,让它在你的应用程序可用,则需要在AppKernel类中的registerBundles()方法中添加它。

// app/AppKernel.php
public function registerBundles()
{
  $bundles = array(
    // ...
    // register your bundles
    new Acme\TestBundle\AcmeTestBundle(),
  );
  // ...
  return $bundles;
}

虽然现在它不能做任何事情,但是它已经成为你应用程序的一部分了。

我们同样可以使用Symfony2为我们提供给命令行工具来创建:

$ php app/console generate:bundle --namespace=Acme/TestBundle

如果你使用上面的命令行工具,则创建的bundle会自动的注册到appKernel类中。

Bundle的目录结构

看一下我们Symfony2自带的Demo bundle的目录结构:

bundle的目录机构简单灵活,从上面的截图中可以看到:

Controller/ 包含bundle的所有controllers文件,比如HelloController.php 。
DependencyInjection/ 保存了特定的依赖注入扩展类,该类可能会导入服务配置,注册编译器传输或者更多其它。该目录并不是必需的。
Resources/config/ 存放着配置文件,包括路由配置(比如:routing.yml)。
Resources/views/ 所有的模板被按照对应controller的名字分成文件夹保存在这里。比如Hello/index.html.twig 。
Resources/public/ 所有可访问的web资源(图片,样式表等)和通过assets:install控制台命令拷贝或者异步链接到项目 web/ 目录的内容。
Tests/ 保存bundle所有的测试

下面是Symfony2 推荐的一些有关bundle的标准规则:

Bundle名称:

一个bundle同时也是一个PHP的命名空间。命名空间必须遵守PHP5.3命名空间和类名的内部技术标准。开头使用提供商名,接着是分类段(可以省略),最后是命名空间的简写名字,而且该名字必须以Bundle作为后缀。一个命名空间变为一个bundle只需要你在该命名空间内添加一个bundle类即可。

Bundle类的命名:

仅适用数字,字母和下划线
使用驼峰式命名
使用描述性简洁的名字(不超过两个单词)
使用供应商名称做前缀(可选的分类命名空间)

添加Bundle作为名称后缀

比如:

Namespace => Bundle 类名称

Acme\Bundle\BlogBundle => AcmeBlogBundle
Acme\Bundle\Social\BlogBundle =>AcmeSocialBlogBundle
Acme\BlogBundle => AcmeBlogBundle

定义bundle类时的getName()方法应该返回类名称。

每个bundle都有一个别名,它是小写字符简写版的bundle名,使用下划线分割。比如 acme_hello 的bundle原名是AcmeHelloBundle, acme_social_blog 则是Acme\Social\BlogBundle的实例。

别名在一个bundle中必须是唯一的。

Bundle的目录结构:HelloBundle的基础目录结构

XXX/...
  HelloBundle/
    HelloBundle.php
    Controller/
    Resources/
      meta/
        LICENSE
      config/
      doc/
        index.rst
      translations/
      views/
      public/
    Tests/

上面的XXX/... 映射到该bundle的命名空间。其中下面的文件是必备的:

HelloBundle.php;

Resources/meta/LICENSE: 全文的许可代码;
Resources/doc/index.rst: bundle说明的根目录文件。

使用类的子文件夹的深度应该保持到最小(2级是极限)。如果更多级可以定义为非静态,不过很少使用。bundle的目录是只读的。如果你需要修改临时文件,把它们保存到主应用程序的cache/ 或者 log/ 目录下。

需要强调的类和文件

类型 VS 目录

Commands                            VS         Command/
Controllers                             VS        Controller/
Service Container Extensions   VS        /DependencyInjection/
Event Listeners                      VS         EventListener/
Configuration                         VS         Resources/config
Web Resources                      VS         Resources/public
Translation files                      VS         Resources/translations/
Templates                              VS         Resources/views
Unit and Functional Test          VS         Tests/

类:

bundle的目录结构是被用来当作命名空间层级的。比如HelloController类保存在 Bundle/HelloBundle/Controller/HelloController.php文件中。

所以类的完全限定名是 Bundle\HelloBundle\Controller\HelloController 。 一些类被看作是装饰,应该越短越好,比如Commands,Helpers, Listeners 和Controllers等,一般都会被当作后缀。

跟事件分发器有关的类应该用后缀Listener标识。

异常类应该保存到一个Exception子命名空间中。

关于提供商

一个bundle不应该被嵌入第三方的PHP类库,它应该依靠Symfony2标准来自动加载它们。

一个bundle不应该被嵌入第三方的javascript,CSS或者其它语言写的任何类库。

关于测试

一个bundle应该有一个使用PHPUnit的测试单元并把它存储在Tests/ 目录下。

测试应该遵循以下原则:

测试套件必须能够被一个简单的phpunit 命令从一个简单的应用程序中执行。

功能测试应该只备用来测试回复输出和一些监控信息。

测试代码覆盖应该至少在95%以上的基本代码。

一个测试套件可以不包含AllTests.php脚本,但必须依靠外部的phpunit.xml.dist文件。

文档说明

所有的类必须带有PHPDoc。

Controllers

最好的情况下,controller应该在一个可以部署到其它地方的bundle中,那么它不能继承Controller基类。而是通过实现ContainerAwareInterface接口或者继承ContainerAware来取代继承Controller。

Routing

如果bundle提供路由,他们必须使用bundle的别名为前缀,比如一个AcmeBlogBundle实例,所有的路由名必须是acme_blog_ 开头。

Templates

如果bundle提供模板,它必须使用Twig。 bundle不必低通一个主布局文件,如果你的bundle是一个完整的应用程序除外。

翻译文件

如果bundle提供信息翻译,它必须是被定义成XLIFF格式,区域名必须被命名在bundle名字之后,如bundle.hello

配置

为了提供更大的灵活性,一个bundle可以使用Symfony2的内建机制提供配置设置。对于简单的设置,依赖于默认的Symfony2的parameters配置入口。 Symfony2参数都是简单的 key/value 对。值可以是任意的合法的PHP值。 每个参数名应该以讹bundle的别名开始,这只是一个最佳的建议。参数名其余部分用点号(.)分割,比如 acme_hello.email.from

让最终用户可以在配置文件中直接提供值信息。

YAML格式:

# app/config/config.yml
parameters:
    acme_hello.email.from: fabien@example.com

XML格式:

<!-- app/config/config.xml -->
<parameters>
   <parameter key="acme_hello.email.from">fabien@example.com</parameter>
</parameters>

PHP代码格式:

// app/config/config.php
$container->setParameter('acme_hello.email.from', 'fabien@example.com');

INI格式:

[parameters]
acme_hello.email.from = fabien@example.com

这样就可以在代码中从容器获取这些配置信息了:

$container->getParameter('acme_hello.email.from');

如果你定义服务,我们也推荐你使用bundle的别名作为前缀。

总结思考:

以上是关于Symfony2中最主要的插件格式bundle的大体情况,在整个Symfony2为基础开发的应用程序中,几乎全部都是有bundle组成。Symfony2本身的核心组件都是FrameworkBundle。在Symfony2交流社区中,已经有了大量的开发者贡献了他们的bundle,我们可以直接拿来集成到我们自己的应用程序中使用。上面所说的大部分规则,都是应用于你开发贡献bundle时应该遵循的统一规则,以方便其它用户使用。

带有第三方贡献的bundle的Symfony2开发包:

如果你不打算把你的bundle贡献出来,那么完全可以不用按照这里说的大部分规则进行开发。

希望本文所述对大家基于Symfony框架的PHP程序设计有所帮助。

(0)

相关推荐

  • Symfony2创建页面实例详解

    本文实例讲述了Symfony2创建页面的方法.分享给大家供大家参考,具体如下: 在Symfony2中创建页面只需要两步: 1.创建路由:路由定义你页面的URI(如/about)并指定要执行的控制器(PHP函数).当传入的请求URL匹配该路由时,Symfony2将执行指定的控制器: 2.创建控制器:控制器是一个PHP函数,它接受传入的请求并将其转换成Symfony2的Response对象. 我们喜欢这样简单的实现,因为它符合Web的工作方式.每一个Web交互都是由HTTP请求开始,应用程序的任务就

  • Symfony2函数用法实例分析

    本文实例讲述了Symfony2函数用法.分享给大家供大家参考,具体如下: 1.调用其他对象的方法. 例: $grobal_func=$this->container->get('global_func'); //'global_func'函数所在的文件名 $lot_data=$global_func->getDataFromFile($parm1); //getDataFromFile函数名 2.数据库的预备查询 $conn = $this->em->getConnectio

  • Symfony2安装第三方Bundles实例详解

    本文实例讲述了Symfony2安装第三方Bundles的方法.分享给大家供大家参考,具体如下: 大多数的Bundles都提了安装的介绍,下面来介绍基本的安装步骤: 一.添加composer依赖关系 在symfony里,用composer来管理依赖关系 1.找到Bundle的包的名称 在包的README里一般都告诉了我们它的名称,如果没有,可以在https://packagist.org网站里搜索到 2.通过composer来安装Bundle 知道了bundle的包名之后,我们可以通过compos

  • Symfony2学习笔记之模板用法详解

    本文实例讲述了Symfony2学习笔记之模板用法.分享给大家供大家参考,具体如下: 我们知道,controller负责处理每一个进入Symfony2应用程序的请求.实际上,controller把大部分的繁重工作都委托给了其它地方,以使代码能够被测试和重用.当一个controller需要生成HTML,CSS或者其他内容时,它把这些工作给了一个模板化引擎. 模板: 一个模板仅仅是一个文本文件,它能生成任意的文本格式(HTML,XML,CSV,LaTex...).最著名的模板类型就是PHP模板了,可以

  • Symfony2学习笔记之控制器用法详解

    本文实例讲述了Symfony2控制器用法.分享给大家供大家参考,具体如下: 一个controller是你创建的一个PHP函数,它接收HTTP请求(request)并创建和返回一个HTTP回复(Response).回复对象(Response)可以是一个HTML页面,一个XML文档,一个序列化的JSON数组,一个图片,一个重定向,一个404错误或者任何你想要的内容.controller中可以包含任何渲染你页面内容的所需要的逻辑. 下面是一个controller最简单的例子,仅仅打印一个Hello w

  • symfony2.4的twig中date用法分析

    本文实例讲述了symfony2.4的twig中date用法.分享给大家供大家参考,具体如下: 获得当前时间: {{ "now"|date("Y-m-d") }} //2014-03-06 获得三天后的时间 {{ "+3 day"|date('Y-m-d') }} //2014-03-09 //或者 date('+3days') //2014-03-09 对twig中的变量进行处理: {{ var|date("Y-m-d") }

  • Symfony2之session与cookie用法小结

    本文实例讲述了Symfony2之session与cookie用法.分享给大家供大家参考,具体如下: session操作: 1. Set Session: public function testSetSession() { $session = $this->getRequest()->getSession(); $session->set($sessionName, $sessionValue ); } 2. Get Session: public function testGetSe

  • Symfony2框架学习笔记之表单用法详解

    本文实例讲述了Symfony2框架表单用法.分享给大家供大家参考,具体如下: 对于一个Web开发者来说,处理HTML表单是一个最为普通又具挑战的任务.Symfony2集成了一个Form组件,让处理表单变的容易起来.在这一节里,我们将 从基础开始创建一个复杂的表单,学习表单类库中最重要的内容. Symfony2 的Form组件是一个独立的类库,你可以在Symfony2项目之外使用它. 创建一个简单的表单: 假设你要创建一个应用程序的todo列表,需要显示一些任务.因为你的用户需要编辑和创建任务,所

  • Symfony2实现从数据库获取数据的方法小结

    本文实例讲述了Symfony2实现从数据库获取数据的方法.分享给大家供大家参考,具体如下: 假设有一张表:test, 字段:name,color; 有2条记录: Tom blue Lily red 示例1: $conn = $this->getDoctrine()->getConnection(); $data = $conn->fetchcolumn("SELECT name, color FROM test"); echo '<pre>'; print

  • Symfony2学习笔记之系统路由详解

    本文详细讲述了Symfony2的系统路由.分享给大家供大家参考,具体如下: 漂亮的URL绝对是一个严肃的web应用程序必须做到的,这种方式使index.php?article_id=57这类的丑陋URL被隐藏,由更受欢迎的像 /read/intro-to-symfony 来替代. 拥有灵活性更为重要,如果你要改变一个页面的URL,比如从/blog 到 /new 怎么办? 有多少链接需要你找出来并更新呢? 如果你使用Symfony的router,这种改变将变得很简单. Symfony2 route

  • Symfony2联合查询实现方法

    本文实例讲述了Symfony2联合查询实现方法.分享给大家供大家参考,具体如下: 1.yml文件 Acme\MspadminBundle\Entity\MspArticle: type: entity table: msp_article manyToOne: Channel: targetEntity: MspChannel inversedBy: Articles joinColumn: name: channel_id referencedColumnName: channel_id Us

随机推荐