recras/sf-doctrine-rest-generator-plugin

此包已被弃用,不再维护。未建议替代包。

sfDoctrineRestGeneratorPlugin 的分支


README

介绍

此插件允许根据 Doctrine 模型生成 REST 模块。它允许轻松创建 REST Web 服务,并提供一个可扩展的数据交换框架。以下是关键特性:

  • REST 模块生成 "类似 admin-generator"
  • 易于定制的 generator.yml 配置文件
  • 使用 symfony 验证器验证传递给服务的参数
  • JSON 序列化
  • 在检索以及创建请求中嵌入相关模型的可能性
  • 嵌入额外字段的可能
  • 限制结果数量的能力,带或不带分页
  • 支持约束联合(例如,http://api.example.org/city?city_id=12,13,14
  • 通过事件和过滤器可钩入
  • 抽象和可替换对象的序列化
  • 全面支持 HTTP(GET、POST、PUT、DELETE)
  • 为每个生成的模块进行功能测试

如何安装

用法

REST 模块生成

生成 REST 模块相当简单

   ./symfony doctrine:generate-rest-module  APPLICATION MODULE MODEL

这将创建一个名为 "MODULE" 的模块,位于 "APPLICATION" 应用程序中,该模块将配置为通过 REST 风格的服务公开 "MODEL" 模型。

生成的文件

假设我们有一个以下模型

    Post:
      actAs:                      [ Timestampable ]
      columns:
        post_category_id:         integer(4)
        created_by:               integer
        title:                    {type: string(128), notnull: true}
        summary:                  {type: string(255), notnull: true}
        body:                     clob
      relations:
        CreatedBy:                { class: sfGuardUser, onDelete: SET NULL, local: created_by, foreign: id, foreignAlias: CreatedPost }
        PostCategory:             { class: PostCategory, onDelete: SET NULL, local: post_category_id, foreign: id }

    PostCategory:
      columns:
        id:                        { type: integer(4), primary: true, autoincrement: true }
        name:                      { type: string, size: 100, notnull: true, unique: true }
        description:               clob
        is_enabled:                { type: boolean, default: true }

如果我们想通过 REST API 公开 "Post" 模型,我们只需输入以下命令

    ./symfony doctrine:generate-rest-module  api post Post

这将生成以下内容

  • 在 "api" 应用的 routing.yml 文件中创建一个新的路由

      post:
        class:   sfObjectRouteCollection
        options:
          model:   Post
          actions: [ create, delete, list, show, update ]
          module:  post
          column:  id
          format:  xml
    
  • 一个名为 "post" 的 RESTgen 模块,位于 apps/api/modules/post,包含四个子目录

    • actions:包含一个 "postActions" 类,该类扩展了一个动态生成的 "autopostActions" 类
    • config:包含生成模块的 generator.yml 和 view.yml 文件(有关如何配置生成模块的说明,请参阅 "服务配置" 章节),
    • lib:包含一个空的 "postGeneratorConfiguration" 类,该类扩展了一个动态生成的 "BasePostGeneratorConfiguration" 类
    • templates
  • 在第一次请求 REST 模块后,缓存目录将包含生成模块的代码,特别是 "autopostActions" 类的代码,您应该检查以了解插件的工作方式。

您可以在 http://api.example.com/post.json 上看到您的帖子作为 JSON 提要

如果情况不是这样,请检查 routing.yml 文件,确认路由名称前是否带有减号 "p"。如果您想更改 API 的公开 URI,只需更改路由名称,然后清除您项目的缓存。以下配置将 API 公开在 http://api.example.com/myPostAPI.json

     myPostAPI:
       class:   sfObjectRouteCollection
       options:
         model:   Post
         actions: [ create, delete, list, update ]
         module:  post
         column:  id
         format:  xml

主配置

在配置 webservice 的响应内容之前,最重要的配置步骤必须经过。它们解决了一些影响安全、稳定性的通用问题,并定义了 webservice 应该做什么

  • webservice 支持哪些类型的操作?仅仅是获取对象,还是也可以创建/更新/删除它?
  • 如何访问 webservice?主要的安全指南是什么?

允许的操作

REST web 服务支持五种不同的操作

这些操作中的每一个都可以在路由文件中允许或禁止,使用 actions 键:只启用您要使用的操作。

安全指南

您永远不应该忘记,公开具有写访问权限的 webservice 可能会危害您的数据。由于对您的 webservice 安全性的关注不够,您可能会丢失一些重要数据,或者在不应该的情况下更改数据。

首先,确保只允许严格必要的操作。如果客户端不需要使用 webservice 删除项目,请在 routing.yml 文件中禁用此操作。

其次,考虑一种方法来提高您的 webservice 的安全性

  • 尽可能使用 SSL,以确保上传的数据不会被第三方(中间人)截获和更改,
  • 使用 HTTP 身份验证,
  • 使用更强大/更灵活的认证系统(例如 OAuth),
  • 向您的客户端提供唯一的 API 密钥,并检查他们对 API 的使用情况。

详细服务配置

对于 symfony 的 admin-generator,REST 生成器会根据在 generator.yml 文件中完成的配置动态生成代码。

以下是 generator.yml 文件的默认内容

    generator:
      class: sfDoctrineRestGenerator
      param:
        model_class:   Post

        config:
          default:
    #        fields:                                # list here the fields.
    #          created_at:                  { date_format: 'Y-m-d\TH:i:s', tag_name: 'created' }      # for instance
    #        separator:                     ','     # separator used for multiple filters
          get:
    #        additional_params:             []      # list here additional params names, which are not object properties
    #        display:                       []      # list here the fields to render in the response
    #        embed_relations:               []      # list here relations to embed in the response
    #        embedded_relations_hide:
    #          Category:                    [id]    # you can hide fields inside a certain embedded relation
    #        global_additional_fields:      []      # list here additionnal calculated global fields
    #        hide:                          [id]    # list here the fields you don't want to expose
    #        max_items:                     0       # uncomment to fix an absolute limit to the number of items in the response
    #        object_additional_fields:      []      # list here additional calculated fields
    #        pagination_enabled:            false   # set to true to activate the pagination
    #        pagination_custom_page_size:   false   # set to true to allow the client to pass a page_size parameter
    #        pagination_page_size:          100     # the default number of items in a page
    #        sort_custom:                   false   # set to true to allow the client to pass a sort_by and a sort_order parameter
    #        sort_default:                  []      # set to [column, asc|desc] in order to sort on a column
    #        filters:                               # list here the filters
    #          id:
    #            compare:                   { less: , greaterEqual: moreThan } # generate filters idLess and idMoreThan
    #          created_at:                  { date_format: 'd-m-Y', multiple: true }  # for instance
          create:
    #        disable_validators:            [ created_at ] # list here validators that should not be generated

在上一个示例中注释的不同可能参数将在以下章节中详细说明。

model_class

model_class 参数定义了 REST 模块所绑定的 Doctrine 模型的名称。

默认值

default 选项包含多个通用配置指令

字段

“fields”选项包含每个模型字段的装饰选项数组,这些选项在序列化和反序列化过程中使用。它可能包括:

  • date_format:用于格式化字段的日期格式。这必须是可以由date()函数接受的格式。
  • tag_name:用于显示此字段的标签名称。例如,您可能希望将文章的标题关联到“post_title”键而不是“title”。
  • type:用于显示此字段的类型。支持所有PHP类型转换关键字,null值保留。

separator

在通过URL传递对象的键时使用的分隔符。生成的模块允许通过它们的ID要求多个资源:http://api.example.com/post/?id=12,17,19

get

get选项列出了针对“get”操作特定的几个选项。

additional_params

additional_params选项允许定义一个参数名称数组,Web服务将接受这些参数。

生成器中参数的验证相当严格,对于传递给服务的每个未识别的参数,生成器都会抛出异常。此选项允许对于某些参数类型不抛出此异常,即使这些参数实际上没有被生成器使用。

此参数的目的是允许将第三方参数传递到服务中。例如,您可能希望传递一个“token”或“api_key”参数,然后可以使用它来检查客户端是否有权使用该服务。

display

display选项包含要输出到XML或JSON源的字段列表。例如,对于之前定义的“Post”模型,您可以通过更改此参数仅显示标题和作者的ID。

        config:
          get:
            display:                       [ title, author_id ]

如果此选项留空,则将渲染模型的全部字段。

您可能还感兴趣的是hide选项,它允许隐藏模型的一些字段。

embed_relations

embed_relations选项包含要嵌入的Doctrine关系列表。它可以是1-n或n-n关系,其内容将嵌入到每个对象中。以下是针对“Post”模型的有效配置:

        config:
          get:
            embed_relations:                       [ PostCategory ]

此配置将产生如下源:

...
<Post>
  <Id>1</Id>
  <PostCategoryId>2</PostCategoryId>
  <CreatedBy>26</CreatedBy>
  <Title>Here the title of my post</Title>
  <Summary>Here the summary of my post</Summary>
  <Body>Here the body of my post</Body>
  <PostCategory>
    <Id>2</Id>
    <Name>Name of the category</Name>
    <Description>Description of the category</Description>
    <IsEnabled>1</IsEnabled>
  </PostCategory>
</Post>
...

需要考虑的几个事项

  • 您不能定义在相关对象中要渲染的字段,但可以使用embedded_relations_hide选项隐藏某些字段。
  • 响应包含PostCategoryId字段和PostCategory.Id字段。您可以通过使用displayhide选项来节省一些字节,以删除PostCategoryId字段。

embed_relations_custom

embed_relations_custom选项包含可能嵌入的Doctrine关系列表。只有当请求中存在embed参数时,这些关系才会被嵌入。其行为与embed_relations选项一致。以下是针对“Post”模型的有效配置:

        config:
          get:
            embed_relations_custom:                [ PostCategory ]

如果提供了embed请求参数,此配置将生成如下格式的feed:

...
<Post>
  <Id>1</Id>
  <PostCategoryId>2</PostCategoryId>
  <CreatedBy>26</CreatedBy>
  <Title>Here the title of my post</Title>
  <Summary>Here the summary of my post</Summary>
  <Body>Here the body of my post</Body>
  <PostCategory>
    <Id>2</Id>
    <Name>Name of the category</Name>
    <Description>Description of the category</Description>
    <IsEnabled>1</IsEnabled>
  </PostCategory>
</Post>
...

embedded_relations_display

您可能只想显示结果中的特定字段。这些字段可以通过embedded_relations_display配置选项进行配置

        config:
          get:
            embedded_relations_display:
              PostCategory:
                - name
                - description

注意:此配置选项仅在设置display选项时有效。如果没有为某个嵌入设置embedded_relations_display选项,则将选择所有字段。

embedded_relations_hide

您可能想隐藏嵌入关系中的某些字段。例如,您可能想从PostCategory模型中隐藏id字段。这可以使用embedded_relations_hide配置选项完成

        config:
          get:
            embedded_relations_hide:
              PostCategory:                     [id]

global_additional_fields

在某些情况下,您可能想将一些附加字段嵌入到XML或JSON响应中。例如,您可能想包括帖子总数、平均价格等。

global_additional_fields在这种情况下很有帮助。它包含您想要添加的字段数组,并且为每个字段,生成器将创建一个用于嵌入该字段的方法。以下是一个可能的配置:

        config:
          get:
            global_additional_fields:                       [ TotalPosts ]

这将创建一个空方法,必须在生成的模块中手动覆盖,以包含您选择的附加字段。

public function embedGlobalAdditionalTotalPosts($params)
{
  $totalObjects = count($this->objects);
  $this->objects['NbObjects'] = $totalObjects;
}

hide

hide选项包含要在XML或JSON feed中隐藏的字段列表。例如,对于之前定义的"Post"模型,您可以选择通过更改此参数来隐藏其id

        config:
          get:
            hide:           [id]

此选项比"display"选项具有更高的优先级,这意味着如果同时使用这两个选项,则仅渲染未列入"hide"选项的字段。

max_items

此指令允许将绝对限制设置在响应中的项目数量上。此参数比pagination_page_size指令具有更高的优先级,以及可能由用户定义的page_size参数。

默认情况下没有限制。将此键设置为0将禁用限制。

object_additional_fields

object_additional_fields包含要在响应的每个项目中嵌入的附加字段列表。例如,如果您想添加一个字段NbWords,该字段会给出帖子正文的单词数,请使用以下配置:

        config:
          get:
            object_additional_fields:                       [ NbWords ]

这将创建一个空方法,必须在生成的模块中手动覆盖,以包含您选择的附加字段。

public function embedAdditionalNbWords($item, $params)
{
  $array = $this->objects[$item];
  $array['NbWords'] = str_word_count($array['body']);
  $this->objects[$item] = $array;
}

此选项对于仅嵌入少量字段的关系很有用(参见embed_relations选项)

  • 嵌入关系
  • 使用object_additional_fields选项取消设置不需要的字段。

embedAdditionalXXX()方法应始终采用以下形式(生成器会以注释的形式生成此代码):

public function embedAdditionalXXXX($item, $params)
{
  $array = $this->objects[$item];

  // here go some manipulation of $array

  $this->objects[$item] = $array;
}

也可以指定调用以添加字段的函数

config:
  get:
    object_additional_fields:
      is_deleted: additionalFieldIsDeleted

指定的函数应具有以下签名

function additionalFieldIsDeleted(array $object, array $parameters): mixed
{
  // $object contains the object as it currently is formatted
  // $parameters contains the request parameters from this API call
  // return the value you'd like field "is_deleted" to have
}

指定的函数将以这种方式被调用

// in formatObjects:
$this->objects[$key]['is_deleted'] = $this->additionalFieldIsDeleted($this->objects[$key], $parameters);

pagination_enabled

此选项定义是否启用分页。默认为false。如果启用,服务将允许在请求中传递"page"参数。请求可以是以下形式:http://api.example.org/post/?page=3

分页自定义页面大小

将此选项设置为true,允许客户端传递一个page_size参数。否则,分页将具有固定的大小。如果pagination_enabled选项设置为false,此选项将没有效果。

分页页面大小

此选项定义分页的默认页面大小。如果pagination_enabled选项设置为false,此选项将没有效果。

自定义排序

将此选项设置为true,允许客户端在查询字符串中传递sort_bysort_order参数。否则,客户端将无法对结果进行排序。

默认排序

sort_default选项定义默认的排序顺序。此选项的格式为[column, asc|desc]。例如

        config:
          get:
            sort_default:                       [ created_at, desc ]

过滤器

此选项允许通过设置一些选项来覆盖默认的过滤行为。默认情况下,插件允许根据模型字段过滤结果。对于每个字段,可以在查询字符串中传递一个值,该值将用于选择匹配的项目。

例如,您可能只想通过请求中的category_id参数获取特定类别的帖子。如果您想允许客户端请求多个类别的帖子,您必须明确允许它,因为这可能会创建更复杂(即资源消耗大且速度慢)的请求。为此,必须将此字段名的键multiple设置为true

        config:
          get:
            filters:
              category_id:                  { multiple: true }

这将允许一次性调用包含多个category_ids的webservice,请求形式为http://api.example.org/post/?category_id=1,4,5

对于日期字段,您可能想告诉插件接受的日期格式。例如

        config:
          get:
            filters:
              created_at:                  { date_format: 'd-m-Y' }

要比较某个字段与给定的值,可以向某个字段添加一个compare指令以添加过滤器。这些过滤器具有fieldNameOperator名称,以下操作符受支持

  • less
  • lessEqual
  • greater
  • greaterEqual

比较过滤器可选地带有别名名称,该名称覆盖了参数中的默认操作符名称。

例如,要向created_at字段添加比较过滤器

        config:
          get:
            filters:
              created_at:
                compare:
                  less: before # generates the created_atBefore filter
                  lessEqual: before # generates the created_atLessEqual filter
                  greater: after # generates the created_atAfter filter
                  # greaterEqual will not be generated

创建

create选项列出针对"创建"操作特定的几个选项

禁用验证器

disable_validators选项包含不应生成创建验证器的字段名称列表。例如

        config:
          create:
            disable_validators:            [ created_at, updated_at ]

其他配置变量

某些其他配置变量在默认配置文件中不存在

  • actions_base_class参数允许更改由模块的动作类扩展的基本动作类名称。这允许您使用自己的动作类,该类可能包含您希望在不同REST模块中使用的多个方法。

事件

截至版本0.9.1,该插件在几个地方使用事件,以提高重载和扩展默认行为。

以下是支持的事件名称列表

  • sfDoctrineRestGenerator.filter_error_output:此事件用于过滤错误消息并允许其自定义
  • sfDoctrineRestGenerator.filter_results:此事件用于过滤查询结果数组(添加、删除或更改其某些键)。请注意,您可以通过在generator.yml中使用object_additional_fields参数来实现相同的功能
  • sfDoctrineRestGenerator.filter_result:此事件用于过滤单个查询结果(添加、删除或更改其某些键)。请注意,您可以通过在generator.yml中使用object_additional_fields参数来实现相同的功能
  • sfDoctrineRestGenerator.get.pre:此事件在请求的开始处触发(在executeIndex()的开始处)

愿望清单

如果您使用此插件并想帮助我改进它,可以考虑以下主题之一

  • 嵌套embed_relations参数的可能性(而不仅仅是限制在单个级别)
  • 禁用事件通知/过滤(性能)的可能性
  • 更多的序列化器(例如BSON或RDF)。目前,该插件仅允许将结果集序列化为XML、YAML或JSON数据流(请参阅“序列化”章节)。需要尽可能紧凑的数据流的移动客户端将受益于BSON序列化。
  • 生成客户端库(sfDoctrineRestClientGenerator ?)的可能性
  • 生成单元测试的可能性
  • 生成API文档的可能性
  • 记录身份验证解决方案
  • 所有可能的反馈!

向插件贡献力量,寻求帮助

请在symfony用户邮件列表上寻求如何使用该插件的帮助。您也可以直接给我发邮件:xavier@lacot.org

许可和致谢

此插件由Xavier Lacot开发,并受MIT许可协议的许可。

变更日志

trunk

  • 默认启用show路由

版本0.9.4 - 2010-11-25

  • 允许在同一个请求中创建或更新相关对象:以递归方式解析有效负载,递归验证有效负载数组,递归生成验证器数组。感谢dfeyer在此方面的贡献
  • 添加了基本“显示”操作(感谢dfeyer)
  • 提高了XML序列化器的性能
  • 添加了序列化单个对象的能力(感谢dfeyer)
  • 添加了cleanupParameters()方法以避免代码重复(感谢dfeyer)
  • 添加了setFieldVisibility()方法,以便在索引和显示操作之间共享代码(感谢dfeyer)
  • 添加了configureFields()方法,以便在索引和显示操作之间共享代码(感谢dfeyer)
  • 修复了executeUpdate(),以便内容不是请求的参数,而是PUT请求的内容(感谢dfeyer)
  • 修复了setFieldVisibility()方法,以便如果对象附加字段未在“get.display”选项中列出,则不会删除它们
  • 使XML序列化器返回PHP数组(感谢dfeyer)
  • 添加了 formats_strict 选项
  • 改进了反序列化抽象
  • 添加了 YAML 序列化器
  • 改进了这些主题的文档

版本 0.9.3 - 2010-08-13

  • 添加了 hideembedded_relations_hide 选项(感谢 Pascal Borreli)
  • 使字段过滤更快

版本 0.9.2 - 2010-07-01

  • 添加了事件(感谢 Matthew Penrice)
  • 添加了默认格式参数(感谢 Matthew Penrice)
  • 添加了 PUT 支持
  • 将默认序列化器切换为 json(更快且更简洁)
  • 改进了文档

版本 0.9.1 - 2010-05-14

  • 修复了上一版本中的拼写错误

版本 0.9 - 2010-05-14

  • 添加了 JSON 序列化器。

版本 0.8 - 2010-05-09

  • 首次公开发布。功能包括带有验证的 REST 模块生成和 XML 序列化器。