Development

/plugins/sfPropel15Plugin/trunk/doc/schema.txt

You must first sign up to be able to contribute.

root/plugins/sfPropel15Plugin/trunk/doc/schema.txt

Revision 29352, 18.5 kB (checked in by francois, 4 years ago)

[sfPropel15Plugin] Documented the isCrossRef table attributes for the YAML schema

  • Property svn:executable set to *
Line 
1 YAML Schema Reference
2 =====================
3
4 Attributes
5 ----------
6
7 Connections and tables can have specific attributes, set under an `_attributes` key:
8
9     [yml]
10     propel:
11       # connection attributes
12       _attributes:   { noXsd: false, defaultIdMethod: none, package: lib.model }
13      
14       blog_article:
15         # table attributes
16         _attributes: { phpName: Article }
17
18 You may want your schema to be validated before code generation takes place. To do that, deactivate the `noXSD` attribute for the connection. The connection also supports the `defaultIdMethod` attribute. If none is provided, then the database's native method of generating IDs will be used--for example, `autoincrement` for MySQL, or `sequences` for PostgreSQL. The other possible value is `none`.
19
20 The `package` attribute is like a namespace; it determines the path where the generated classes are stored. It defaults to `lib/model/`, but you can change it to organize your model in subpackages. For instance, if you don't want to mix the core business classes and the classes defining a database-stored statistics engine in the same directory, then define two schemas with `lib.model.business` and `lib.model.stats` packages.
21
22 The `phpName` table attribute is used to set the name of the generated class mapping the table.
23
24 Tables that contain localized content (that is, several versions of the content, in a related table, for internationalization) also take two additional attributes (see symfony's i18n documentation for details), as shown in the next listing:
25
26     [yml]
27     propel:
28       blog_article:
29         _attributes: { isI18N: true, i18nTable: db_group_i18n }
30
31 Dealing with multiple Schemas
32 -----------------------------
33
34 You can have more than one schema per application. Symfony will take into account every file ending with `schema.yml` or `schema.xml` in the `config/` folder. If your application has many tables, or if some tables don't share the same connection, you will find this approach very useful.
35
36 Consider these two schemas:
37
38      [yml]
39      // In config/business-schema.yml
40      propel:
41        blog_article:
42          _attributes: { phpName: Article }
43          id:
44          title: varchar(50)
45
46      // In config/stats-schema.yml
47      propel:
48        stats_hit:
49          _attributes: { phpName: Hit }
50          id:
51          resource: varchar(100)
52          created_at:
53
54 Both schemas share the same connection (`propel`), and the `Article` and `Hit` classes will be generated under the same `lib/model/` directory. Everything happens as if you had written only one schema.
55
56 You can also have different schemas use different connections (for instance, `propel` and `propel_bis`, to be defined in `databases.yml`) and organize the generated classes in subdirectories:
57
58      [yml]
59      // In config/business-schema.yml
60      propel:
61        blog_article:
62          _attributes: { phpName: Article, package: lib.model.business }
63          id:
64          title: varchar(50)
65
66      // In config/stats-schema.yml
67      propel_bis:
68        stats_hit:
69          _attributes: { phpName: Hit, package: lib.model.stat }
70          id:
71          resource: varchar(100)
72          created_at:
73
74 Many applications use more than one schema. In particular, some plug-ins have their own schema and package to avoid messing with your own classes.
75
76 Column Details
77 --------------
78
79 A table contains columns. The column details can contain three types of definition:
80
81 - a simple type definition
82 - a complete definition
83 - an empty definition, to let Propel guess the correct settings
84
85 You can mix columns with all three types of definitions in a single table.
86
87 ### Simple Type
88
89 If you define only one attribute, it is the column type. Symfony understands the usual column types: `boolean`, `integer`, `float`, `date`, `varchar(size)`, `longvarchar` (converted, for instance, to `text` in MySQL), and so on. For text content over 256 characters, you need to use the `longvarchar` type, which has no size (but cannot exceed 65KB in MySQL).
90
91      [yml]
92      // In config/schema.yml
93      propel:
94        user:
95          login:     varchar(50)
96          password:  varchar(50)
97          age:       integer
98          dob:       bu_date
99
100 ### Complete Column Definition
101
102 If you need to define more column attributes than just the type (like default value, required, and so on), you should write the column attributes as a set of `key: value` pairs. For instance:
103
104     [yml]
105     propel:
106       blog_article:
107         id:       { type: integer, required: true, primaryKey: true, autoIncrement: true }
108         name:     { type: varchar(50), default: foobar, index: true }
109         group_id: { type: integer, foreignTable: db_group, foreignReference: id, onDelete: cascade }
110
111 The common column parameters are as follows:
112
113   * `type`: Column type. The choices are `boolean`, `tinyint`, `smallint`, `integer`, `bigint`, `double`, `float`, `real`, `decimal`, `char`, `varchar(size)`, `longvarchar`, `date`, `time`, `timestamp`, `bu_date`, `bu_timestamp`, `blob`, and `clob`.
114   * `default`: Default value.
115   * `required`: Boolean. Set it to `true` if you want the column to be required.
116   * `size`: The size or length of the field for types that support it
117   * `scale`: Number of decimal places for use with decimal data type (size must also be specified)
118   * `index`: Boolean. Set it to `true` if you want a simple index or to `unique` if you want a unique index to be created on the column.
119   * `isCulture`: Boolean. Set it to `true` for culture columns in localized content tables (see i18n section).
120  
121 Primary key columns accept additional parameters:
122
123   * `primaryKey`: Boolean. Set it to `true` for primary keys.
124   * `autoIncrement`: Boolean. Set it to `true` for columns of type `integer` that need to take an auto-incremented value.
125   * `sequence`: Sequence name for databases using sequences for `autoIncrement` columns (for example, PostgreSQL and Oracle).
126
127 Foreign key columns accept additional parameters:
128
129   * `foreignTable`: A table name, used to create a foreign key to another table.
130   * `foreignReference`: The name of the related column if a foreign key is defined via `foreignTable`.
131   * `onDelete`: Determines the action to trigger when a record in a related table is deleted. When set to `setnull`, the foreign key column is set to `null`. When set to `cascade`, the record is deleted. If the database engine doesn't support the set behavior, the ORM emulates it.
132   * `fkPhpName`: Name of the related object seen from the current object. Propel uses this name to generate filters and accessors (see the 'Relation Names' section below)
133   * `fkRefPhpName`: Name of the current object seen from the related object.
134
135 ### Empty Column Definition
136    
137 If you define nothing (`~` in YAML is equivalent to `null` in PHP), symfony will guess the best attributes according to the column name and a few conventions.
138
139     [yml]
140     propel:
141       blog_read:
142         id:         ~
143         blog_id:    ~
144         created_at: ~
145         updated_at: ~
146        
147     # symfony fills the blanks using the following rules
148     propel:
149       blog_read:
150         # Empty columns named id are considered primary keys
151         id:         { type: integer, required: true, primaryKey: true, autoIncrement: true }
152         # Empty columns named XXX_id are considered foreign keys
153         blog_id:    { type: integer, foreignTable: blog, foreignReference: id }
154         # Empty columns named created_at, updated at, created_on and updated_on
155         # are considered dates and automatically take the timestamp type
156         created_at: { type: timestamp }
157         updated_at: { type: timestamp }
158
159 For foreign keys, symfony will look for a table having the same `phpName` as the beginning of the column name, and if one is found, it will take this table name as the `foreignTable`.
160
161 Foreign Keys
162 ------------
163
164 As an alternative to the `foreignTable` and `foreignReference` column attributes, you can add foreign keys under the `_foreignKeys:` key in a table. The schema in the next listing creates a foreign key on the `user_id` column, matching the `id` column in the `blog_user` table.
165
166     [yml]
167     propel:
168       blog_article:
169         id:      ~
170         title:   varchar(50)
171         user_id: { type: integer }
172         _foreignKeys:
173           -
174             foreignTable: blog_user
175             onDelete:     cascade
176             references:
177               - { local: user_id, foreign: id }
178
179 The alternative syntax is useful for multiple-reference foreign keys and to give foreign keys a name:
180
181     [yml]
182         _foreignKeys:
183           my_foreign_key:
184             foreignTable:  db_user
185             onDelete:      cascade
186             references:
187               - { local: user_id, foreign: id }
188               - { local: post_id, foreign: id }
189
190 Indexes
191 -------
192
193 As an alternative to the `index` column attribute, you can add indexes under the `_indexes:` key in a table. If you want to define unique indexes, you must use the `_uniques:` header instead. For columns that require a size, because they are text columns, the size of the index is specified the same way as the length of the column using parentheses.
194
195     [yml]
196     propel:
197       blog_article:
198         id:               ~
199         title:            varchar(50)
200         created_at:
201         _indexes:
202           my_index:       [title(10), user_id]
203         _uniques:
204           my_other_index: [created_at]
205
206 The alternative syntax is useful only for indexes built on more than one column.
207
208 Many-to-Many relationships
209 --------------------------
210
211 Cross-reference tables, used for many-to-many relationships, must declare with an `isCrossRef` attribute set to `true`:
212
213     [yml]
214     propel:
215       blog_article:
216         # columns definition
217      
218       blog_author:
219         # columns definition
220      
221       blog_article_author:
222         _attributes: { phpName: ArticleAuthor, isCrossRef: true }
223         article_id:  { type: integer, foreignTable: blog_article, foreignReference: id, onDelete: cascade }
224         author_id:   { type: integer, foreignTable: blog_author, foreignReference: id, onDelete: cascade }
225
226 Declaring a table as a cross reference table leads Propel to generate more methods in the Model and Query classes, including:
227
228     [php]
229     Article::getAuthors()
230     Article::countAuthors()
231     ArticleQuery::filterByAuthor($author)
232     Author::getArticles()
233     Author::countArticles()
234     AuthorQuery::filterByArticle($article)
235    
236 I18n Tables
237 -----------
238
239 Symfony supports content internationalization in related tables. This means that when you have content subject to internationalization, it is stored in two separate tables: one with the invariable columns and another with the internationalized columns.
240
241 In a `schema.yml` file, all that logic is implied when you name a table `foobar_i18n`. For instance, the following schema is automatically completed with columns and table attributes to make the internationalized content mechanism work:
242
243     [yml]
244     propel:
245       db_group:
246         id:          ~
247         created_at:  ~
248
249       db_group_i18n:
250         name:        varchar(50)
251
252 The resulting schema is:
253
254     [yml]
255     propel:
256       db_group:
257         _attributes: { isI18N: true, i18nTable: db_group_i18n }
258         id:         ~
259         created_at: ~
260
261       db_group_i18n:
262         id:       { type: integer, required: true, primaryKey: true,foreignTable: db_group, foreignReference: id, onDelete: cascade }
263         culture:  { isCulture: true, type: varchar(7), required: true,primaryKey: true }
264         name:     varchar(50)
265
266 Note that you can use the second syntax to be able to see the columns in your YAML configuration file.
267
268 Propel Behaviors
269 ----------------
270
271 Enable native Propel behaviors in your tables by setting the `_propel_behaviors` key. For instance, to turn on `soft_delete` on an `Article` table, write the following schema:
272
273     [yaml]
274     propel:
275       article:
276         _attributes: { phpName: Article }
277         id:          ~
278         title:       varchar(150)
279         body:        longvarchar
280         _propel_behaviors:
281           soft_delete:
282
283 Here is the list of Propel core behaviors available in this plugin:
284
285 - [timestampable](http://www.propelorm.org/wiki/Documentation/1.5/Behaviors/timestampable): Keep track of the creation and modification date of each record.
286 - [sluggable](http://www.propelorm.org/wiki/Documentation/1.5/Behaviors/sluggable): Each row gets a unique slug that you can use to make smart URIs
287 - [soft_delete]([http://www.propelorm.org/wiki/Documentation/1.5/Behaviors/soft_delete): Keep the deleted rows hidden, so that you can recover them.
288 - [nested_set](http://www.propelorm.org/wiki/Documentation/1.5/Behaviors/nested_set): Handle hierarchichal data with ease; the nested sets algorithm needs only one query to parse a tree in any way.
289 - [sortable](http://www.propelorm.org/wiki/Documentation/1.5/Behaviors/sortable): Give rows in a table the ability to be moved up and down of a list, and to retrieve sorted results.
290 - [concrete_inheritance](http://www.propelorm.org/wiki/Documentation/1.5/Inheritance#ConcreteTableInheritance): Copy the structure of a model class to another; also copy the data back to the parent class, for efficient queries.
291 - [query_cache](http://www.propelorm.org/wiki/Documentation/1.5/Behaviors/query_cache): Speed up often used queries by skipping the query analysis process. Propel will still query the database for results, only faster.
292 - [alternative_coding_standards](http://www.propelorm.org/xiki/Documentation/1.5/Behaviors/alternative_coding_standards): Use symfony's coding standards in Propel's generated classes.
293 - [auto_add_pk](http://www.propelorm.org/wiki/Documentation/1.5/Behaviors/auto_add_pk): Classes that don't have a primary key get one.
294
295 You can register more than one behavior and set the parameters of each behaviors:
296
297     [yaml]
298     propel:
299       article:
300         _attributes: { phpName: Article }
301         id:          ~
302         title:       varchar(150)
303         body:        longvarchar
304         deleted_on:  timestamp
305         _propel_behaviors:
306           soft_delete: { deleted_column: deleted_on }
307           sluggable:
308           timestampable:
309
310 You can also register a behavior for all your models right in the `propel.ini`. `sfPropel15Plugin` already enables the `symfony` and `symfony_i18n` behaviors to support symfony's behavior system and model localization features, but you can easily add your owns:
311
312     [ini]
313     propel.behavior.default = symfony,symfony_i18n,alternative_coding_standards,auto_add_pk
314
315 **Tip**: Beware not to mix up native propel behaviors, documented in the Propel core, with symfony behaviors for Propel. Native propel behaviors are faster and more powerful, because they are executed at buildtime and not at runtime. Symfony behaviors for Propel, that usually require an additional plugin, are registered under the `_behaviors` key.
316
317 Single Table Inheritance
318 ------------------------
319
320 To enable single table inheritance in a table, define a type column, and add the `_inheritance` key, as follows:
321
322     [yaml]
323     propel:
324       person:
325         _attributes: { phpName: Person }
326         id:          ~
327         name:        varchar(100)
328         type:        varchar(20)
329         _inheritance:
330           column:    type
331           classes:
332             type_1:  Employee
333             type_2:  Manager
334
335 The keys used in the `classes` hash define the value given to the inheritance column in the database, while the value determine the actual class names.
336
337 Such a schema will generate both a Model and a Query class for `Employee` and `Manager`, in addition to the ones generated for `Person`:
338
339     model/
340       Person.php
341       PersonPeer.php
342       PersonQuery.php
343       Employee.php
344       EmployeeQuery.php
345       Manager.php
346       ManagerQuery.php
347      
348 A `PersonQuery` returns mixed results, of class `Person`, `Employee`, and `Manager`, while a `ManagerQuery` returns only objects of class `Manager`:
349
350     [php]
351     $person = new Person();
352     $person->setName('John');
353     $person->save();
354     $manager = new Manager();
355     $manager->setName('Jack');
356     $manager->save();
357     echo PersonQuery::create()->count();  // 2
358     echo ManagerQuery::create()->count(); // 1
359
360 Relation Names
361 --------------
362
363 When you define a foreign key, Propel creates a relationship. Both the objects involved in the relationship see it with a different name. By default, the relation name is the phpName of the related object. For instance, for a `user_id` foreign key in a `book` table:
364
365     [yaml]
366     propel:
367       user:
368         _attributes: { phpName: User }
369         id:          ~
370         first_name:  varchar(100)
371         last_name:   varchar(100)
372       book:
373         _attributes: { phpName: Book }
374         id:          ~
375         title:       varchar(150)
376         body:        longvarchar
377         user_id:     { type: integer, foreignTable: user, foreignReference: id, onDelete: cascade }
378
379 Here, Propel creates a `User` relation on the `Book` object, and a `Book` relation on the `User` object. These relations are used to forge the foreign object getters and setters in the Model object, as well as the foreign object filters in the Query object:
380
381     [php]
382     $user = $book->getUser();
383     $user = UserQuery::create()
384       ->filterByBook($book)
385       ->findOne();
386     $books = $user->getBooks();
387     $books = BookQuery::create()
388       ->filterByUser($user)
389       ->find();
390
391 You may want to customize the relation names to qualify the relationship. In the previous example, when related to an `Article`, a `User` would better be called an `Author`. Symmetrically, from the `User` point of view, a `Book` should be named a `Work`. Use the `fkPhpName` and `fkRefPhpName` column attributes to choose custom relation names:
392
393     [yaml]
394     propel:
395       article:
396         _attributes: { phpName: Article }
397         id:          ~
398         title:       varchar(150)
399         body:        longvarchar
400         user_id:     { fkPhpName: Author, fkRefPhpName: Work, type: integer, foreignTable: user, foreignReference: id, onDelete: cascade }
401
402 Now the generated code looks like this:
403
404     [php]
405     $user = $book->getAuthor();
406     $user = UserQuery::create()
407       ->filterByWork($book)
408       ->findOne();
409     $books = $user->getWorks();
410     $books = BookQuery::create()
411       ->filterByAuthor($user)
412       ->find();
413
414 The ability to name both sides of a relationship becomes very handy when you have to deal with several foreign keys to the same table.
415
416 Custom BaseObject
417 -----------------
418
419 By default, the generated Model objects extend BaseObject. You can customize this parent class on a per table basis by overriding the `baseClass` attribute:
420
421     [yaml]
422     propel:
423       person:
424         _attributes: { phpName: Person, baseClass: myBaseObject }
425         id:          ~
426         name:        varchar(100)
427         type:        varchar(20)
428
429 A `build-model` will then produce:
430
431     [php]
432     class Person extends BasePerson
433     abstract class BasePerson extends myBaseObject
Note: See TracBrowser for help on using the browser.