SonataEasyExtendsBundle功能包:让您的Symfony2功能包可被扩展

简介:


Note

this post is not part of the Symfony2 documentation; it is just a state about how things work now (end of 2010) between Doctrine2 and Symfony2. It is not a complaint about the architecture, it just exposes how I solve a recurrent problem I have.

注意:本文档并非Symfony2的官方文档,它只是表现Symfony2和Doctrine2之间如何工作的状态(2010年底)。它并非是关于结构方面的抱怨,它只是表明了我是如何解决这一常见问题的。

3.1. LET’S HAVE A QUICK SYMFONY2 AND DOCTRINE TOUR

3.1.SYMFONY2和DOCTRINE的简要说明


A quick Doctrine tour:

Doctrine的简要说明:

  • Doctrine2 entities are plain PHP objects; there is no database layer information. An Comment::post_id property is part of the database layer and not part of the domain layer. So a comment entity will have a postproperty and not a post_id property.

  • Doctrine2实体是一个简单PHP对象;它没有数据库层信息。Comment::post_id属性是属于数据库层而非域层,因此Comment实体有一个post属性而非post_id属性。

  • Doctrine2 entities are mapped through mapping information: yaml, xml, annotation or php code. There is one mapping per class. So if Blog extends SuperBlog, which extends SuperEntity, you will have 3 classes and so 3 information mappings and you will be able to use 3 different tables to save these entities.

  • Doctrine2实体通过yaml、xml、annotation或PHP代码等映射信息来进行映射,它是基于每个类来做映射的。因此如果Blog从SuperBlog(SuperBlog又是从SuperEntity扩展出来的)扩展出来的话,您将有三个类和三个映射信息,并且您将使用3个不同的数据表来保存这些实体。

  • A mapped entity is final (from doctrine2 point of view), it cannot be extended unless you create a new mapping definition for the new child class.

  • 如果一个被映射的实体是最终实体(从Doctine2的角度来看)的话,那么它不能被扩展,除非您为新的子类定义一个新的映射。

  • Each entity is linked to a ClassMetadata information which contains all the mapping information and the final class name.

  • 每个实体都被链到一个ClassMetadata信息,该信息包括所有的映射信息和最终类名。

  • An entity can extend a SuperClass. A SuperClass is just a mapping definition, a SuperClass cannot be persisted.

  • 实体可以从SuperClass扩展,SuperClass只是个映射定义,它是不能被持久化的。

A quick Symfony2 bundle tour:

Symfony2功能包的简要说明:

  • There are two types of bundles: Application Bundle (AB) and Vendor Bundle (VB), the latter should not be modified inside a project.

  • 功能包有两类:应用程序功能包(AB)和供应商提供的功能包(VB),后者不能在项目中修改。

  • The AB directory is where developers implement the project requirements.

  • AB的目录位置可以由开发者在根据项目要求来实现

  • An AB can overwrite almost everything from a VB, example: you can redefine a VB template at the AB level.

  • AB几乎可以覆写VB中的任何东西,如您可以在AB层次重定义VB的模板

名称空间的简要说明:

  • “命名空间是一个提供上下文的抽象容器

  • An entity is defined by a namespace

  • 实体通过命名空间定义

  • A bundle is defined by a namespace

  • 功能包通过命名空间定义

  • A VB and AB are defined with two different namespaces

  • VB和AB通过两个不同的命名空间定义

3.2. LET’S START TO MIX THESE POINTS TOGETHER

3.2.让我们开始将这些观点混和起来

  • If an AB bundle A wants to use an entity from a VB bundle B, the fully qualify namespace must be used.

  • 如果AB功能包A想使用来自VB功能包B的实体,那么必须使用一个完整的命名空间

  • If a developer wants to add a new property into a VB entity, the developer needs to create a new child entity with a custom mapping.

  • 如果开发者想添加一个新属性到一个VB实体,那么他需要通过一个自定义的映射去创建一个新的子实体

At this point you have 2 entities with 2 different namespace. The VB bundle’s code refers to its own namespace to instantiate the model, BUT ... how ... you just create a new entity. Your VB will be unable to use this new model ... too bad.

此时,您有两个不同命名空间的两个实体。VB功能包代码指向它自己的命名空间用来对模型进行实例化,但...您刚才创建了一个新的实体。您的VB将不能使用这个新模型...太糟了

3.3. CAN THIS PROBLEM BE SOLVED WITH THE ALTERNATE SYNTAX?

3.3.这个问题可以用替代语法解决吗?

There is actually a start of a solution, the DoctrineBundle allows us to use an alternate syntax, ie (BlogBundle:Blog instead of Bundle\BlogBundle\Entity\Blog). As you can guess this syntax only works for string, inside a query for instance.

有个解决方案:DoctrineBundle允许我们使用一个替代语法,如使用BlogBundle:Blog来替代Bundle\BlogBundle\Entity\Blog,因此您可以猜到该语法仅适用于字符串,以便放置在实例的查询中。

So if you want to instantiate a new model, you need first to get the ClassMetadata instance, retrieve the class name and create the model. It’s not really nice and creates a dependency to the class metadata.

因此如果您想实例化一个新模型,您首先需要获得ClassMetadata实例,检索类名并创建模型,然后创建类元数据依赖,这并不是太好。

Last issue, the entity’s mapping association required fully qualifies namespace: no alternate syntax. (I suppose, this last point can be fixed).

最后,实体映射关联要求完整的命名空间:没有替代语法(我假定最后一点没有变化)

At this point, we are stuck with no solution to fully extend a bundle. (Don’t take this for granted; this might change in a near future, as Symfony2 is not complete yet)

基于上述考虑,我们认为目前没有一个完全扩展功能包的解决方案。(不要想当然,在将来这些也许会被改变,因为Symfony2并未完成)

3.4. A PRAGMATIC WAY TO SOLVE THIS ISSUE

3.4.实用的解决方法

The easiest way to solve this problem is to use global namespace inside your VB, the global namespace is the only namespace allowed Application\YourBundle\Entity.

最容易解决这一问题的方法在您的VB中使用全局命名空间,全局的命名空间只允许Application\您的功能包\Entity

So inside your mapping definition or inside your VB code, you will use one final namespace: problem solved. How to achieve this

因此在您的映射定义或VB代码中,您将使用一个最终命名空间:问题解决。如何来实现呢?

  • Declare only SuperClass inside a VB, don’t use final entity

  • 在VB中只声明SuperClass,并不使用最终实体

  • Call your entity BaseXXXX and make it abstract, change the properties from private to protected.

  • 调用您的BaseXXXX并将其抽象,并将其属性由私有(private)改为保护(protected)。

  • The same goes for a repository

  • 同样对repository中也作相同操作

  • Always use Application\YourBundle\Entity\XXXX inside your code

  • 总在在您的代码中使用Application\您的功能包\Entity\XXXX

Of course, you need to create for each VB bundle

当然,您需要为每个VB功能包创建:

  • a valid structure inside the Application directory

  • Application目录下的合法结构

  • a valid entity mapping definition

  • 合法的实体映射定义

  • a model inside the entity folder

  • 实体目录中的模型

The last part is quite inefficient without an efficient tool to generate for you this structure: EasyExtendsBundle to the rescue.

最后这部分如果没有一个有效的工具来帮您生成这一结构将会十分繁琐:EasyExtendsBundle将能帮到您。

3.5. HOW TO MAKE YOUR BUNDLE EASY EXTENDABLE

3.5.如何让您的功能包容易被扩展

Mainly all you need is to follow instructions in previous paragraph.

综上所述,您主要需要:

  • Declare you entity/repository as described above

  • 根据上节的说明重新声明您的entity/repository

  • Use your entity/repository as described above.

  • 根据上节的说明使用您的entity/repository

  • Before generation you also need “skeleton” file that will describe AB entity. Skeleton file can either xml or yml. For fully working example see SonataMediaBundle.

  • 在生成之前,您还需要“skeleton”文件来描述AB实体,该文件可以是xml或yml格式,完整示例请参见SonataMediaBundle

At last you can run php app/console sonata:easy-extends:generate YourVBBundleName. Note that the –dest option allows you to choose the target directory, such as src. Default destination is app/

最后您可以运行 php app/console sonata:easy-extends:generate 您的VB功能包名。注意--dest选项允许您选择目的目录,如src等,该目录缺省为app/




本文转自 firehare 51CTO博客,原文链接:http://blog.51cto.com/firehare/1397586,如需转载请自行联系原作者
相关文章
|
7月前
|
缓存 前端开发 JavaScript
Webpack作为模块打包器,为前端项目提供了高度灵活和可配置的构建流程
【6月更文挑战第12天】本文探讨了优化TypeScript与Webpack构建性能的策略。理解Webpack的解析、构建和生成阶段是关键。优化包括:调整tsconfig.json(如关闭不必要的类型检查)和webpack.config.js选项,启用Webpack缓存,实现增量构建,代码拆分和懒加载。这些方法能提升构建速度,提高开发效率。
67 3
|
7月前
|
存储 数据库 数据安全/隐私保护
Duplicator插件的主要功能是什么?
【6月更文挑战第4天】Duplicator插件的主要功能是什么?
85 1
|
8月前
|
编译器 API PHP
深入PHP扩展开发:打造高效自定义模块
【4月更文挑战第30天】 在追求性能优化和特定功能实现的道路上,PHP提供了一种强大机制——扩展。本文将引导读者通过编写一个简单的PHP扩展来探索扩展开发的世界。我们将涉及从环境搭建到代码实现,再到扩展的编译与加载的完整流程,确保读者能够理解并实践如何创建高效的自定义PHP模块。
|
8月前
|
中间件 API 文件存储
Django的扩展包与中间件:增强应用功能的利器
【4月更文挑战第15天】本文介绍了Django的扩展包和中间件,两者用于增强Django应用功能。扩展包是可重用的应用,提供额外功能,如用户认证和API开发。选择合适的扩展包,通过安装、配置,可轻松集成到项目中。中间件则在请求和响应之间执行操作,如身份验证和权限控制。创建中间件类并添加到settings.py中,实现特定功能。扩展包和中间件常结合使用,以实现更复杂的应用需求,提高开发效率和应用性能。
|
8月前
|
数据处理 数据库 开发者
Django中的自定义管理命令:扩展管理功能的途径
【4月更文挑战第15天】Django教程:介绍如何创建和使用自定义管理命令以扩展框架功能。在应用的`management/commands`目录下创建Python文件,继承`BaseCommand`,实现`handle`方法。示例代码展示了如何定义参数和执行逻辑。自定义命令适用于批量数据处理、定期任务、项目初始化和自定义迁移操作。注意文件位置、命令安全性和稳定性。自定义管理命令能提升开发和维护效率。
|
开发框架 JavaScript 小程序
扩展应用功能的无限可能——UniApp生态系统中的组件库与插件探索
扩展应用功能的无限可能——UniApp生态系统中的组件库与插件探索
|
存储 网络架构 Python
python|web应用框架|增加动态路由
python|web应用框架|增加动态路由
171 0
python|web应用框架|增加动态路由
|
数据库
插件配置设计
插件配置设计
115 0
|
前端开发 小程序 项目管理
前端:组件、插件、模块、子应用、库、框架等区别
前端:组件、插件、模块、子应用、库、框架等区别
1133 0