![]() |
|
sfPropelAlternativeSchemaPlugin - 0.9.0Alternative propel schema syntax for customizable schemas |
|
This plugin extends the symfony model generator, based on Propel, to allow a schema to override another one. It also provides a new YAML syntax for defining database schemas, more explicit and more readable. This new syntax is completely backward compatible with symfony's current schema.yml syntax, so installing this plugin will not break your applications.
To install the plugin for a symfony project, the usual process is to use the symfony command line:
$ php symfony plugin-install http://plugins.symfony-project.com/sfPropelAlternativeSchemaPlugin
Alternatively, if you don't have PEAR installed, you can download the latest package attached to this plugin's wiki page and extract it under your project's plugins/ directory.
Clear the cache to enable the autoloading to find the new classes:
$ php symfony cc
That's it, you are ready to write schemas with the new syntax and override existing schemas.
As an alternative to the current schema.yml syntax (which still works), this plugin proposes a new way to define a database schema.
Consider the following schema, using the current syntax:
propel:
_attributes: { noXsd: false, defaultIdMethod: none, package: lib.model }
ab_group:
_attributes: { phpName: Group, package: foo.bar.lib.model }
id:
name: varchar(50)
cd_user:
_attributes: { phpName: User, isI18N: true, i18nTable: cd_user_i18n }
first_name: { type: varchar, size: 255, default: "Anonymous" }
last_name: varchar(50)
age: { type: integer, required: true, index: true }
ab_group_id:
created_at:
cd_user_i18n:
description: longvarchar
ef_article:
title: { type: longvarchar, required: true, index: unique }
stripped_title: { type: longvarchar, required: true, primaryKey: true, sequence: my_custom_sequence_name }
user_id:
my_group: { type: integer, foreignTable: ab_group, foreignReference: id, onDelete: setnull }
created_at: timestamp
updated_at:
ij_article:
_attributes: { phpName: Article }
title: varchar(50)
user_id: { type: integer }
_foreignKeys:
*
foreignTable: cd_user
onDelete: cascade
references:
* { local: user_id, foreign: id }
created_at:
_indexes:
my_index: [user_id](title,)
_uniques:
my_other_index: [created_at]
ab_group_i18n:
motto: longvarchar
With the new syntax, you can write it as follows:
connection: propel
noXsd: false
defaultIdMethod: none
package: lib.model
classes:
Group:
tableName: ab_group
package: foo.bar.lib.model
columns:
id:
name: varchar(50)
User:
tableName: cd_user
isI18N: true
i18nTable: cd_user_i18n
columns:
first_name: { type: varchar, size: 255, default: "Anonymous" }
last_name: varchar(50)
age: { type: integer, required: true, index: true }
ab_group_id:
created_at:
CdUserI18n:
columns:
description: longvarchar
EfArticle:
columns:
title: { type: longvarchar, required: true, index: unique }
stripped_title: { type: longvarchar, required: true, primaryKey: true, sequence: my_custom_sequence_name }
user_id:
my_group: { type: integer, foreignTable: ab_group, foreignReference: id, onDelete: setnull }
created_at: timestamp
updated_at:
Article:
tableName: ij_article
columns:
title: varchar(50)
user_id: { type: integer }
created_at:
foreignKeys:
*
foreignTable: cd_user
onDelete: cascade
references:
* { local: user_id, foreign: id }
indexes:
my_index: [user_id](title,)
uniques:
my_other_index: [created_at]
AbGroupI18n:
columns:
motto: longvarchar
The main difference is that you declare classes, not tables, using the table phpName as a key. If you don't define a tableName, the plugin will determine one automatically based on the phpName using sfInflector::underscore().
This syntax is also more explicit, since you must create entries for classes and columns. But it gets rid of the ugly _attributes hack of the current syntax.
The connection parameter is optional. If it is not set, it will take propel as a default value.
Last but not least, all the 'magic' of the current syntax is still there (auto definition of primary keys, foreign keys, i18n tables, etc.).
Once you have defined such a schema, rebuild the model as usual:
$ php symfony propel-build-model
Schemas using this new syntax can be customized by other schemas. This is great for plugin schemas, for instance, to allow users to override some of the plugin's schema settings (such as the connection, the table names, etc).
When dealing with a schema with the alternative syntax, the symfony builder will look for custom YAML files for this schema, following this rule:
Original schema name | Custom schema name
*----------------------------------------|------------------------
config/schema.yml | schema.custom.yml
config/foobar_schema.yml | foobar_schema.custom.yml
plugins/myPlugin/config/schema.yml | myPlugin_schema.custom.yml
plugins/myPlugin/config/foo_schema.yml | myPlugin_foo_schema.custom.yml
Custom schemas will be looked for in the application's and plugins' config/ directories, so a plugin can override another plugin's schema.
Custom schemas must respect the same alternative syntax. The plugin will simply merge the two schemas, as follows:
# Original schema
#################
classes:
User:
tableName: cd_user
columns:
first_name: { type: varchar, size: 255, default: "Anonymous" }
last_name: varchar(50)
age: { type: integer, required: true, index: true }
created_at:
Article:
tableName: ij_article
columns:
title: varchar(50)
user_id: { type: integer }
created_at:
foreignKeys:
*
foreignTable: cd_user
onDelete: cascade
references:
* { local: user_id, foreign: id }
# Custom schema
###############
connection: myConnection
classes:
Group:
tableName: ab_group
package: foo.bar.lib.model
columns:
id:
name: varchar(50)
User:
tableName: ef_user
isI18N: true
i18nTable: cd_user_i18n
columns:
ab_group_id:
Article:
columns:
updated_at:
# Resulting schema
##################
connection: myConnection
classes:
Group:
tableName: ab_group
package: foo.bar.lib.model
columns:
id:
name: varchar(50)
User:
tableName: cd_user
isI18N: true
i18nTable: cd_user_i18n
columns:
first_name: { type: varchar, size: 255, default: "Anonymous" }
last_name: varchar(50)
age: { type: integer, required: true, index: true }
ab_group_id:
created_at:
Article:
tableName: ij_article
columns:
title: varchar(50)
user_id: { type: integer }
created_at:
updated_at:
foreignKeys:
*
foreignTable: cd_user
onDelete: cascade
references:
* { local: user_id, foreign: id }