<commit_before>++ Introduction

The purpose of schema files is to allow you to manage your model definitions directly from a yaml file rather then editing php code. The yaml schema file is parsed and used to generate all your model definitions/classes.

++ Example Schema File

'tableName' and 'className' are optional. If not specified they will be set by the key of the yaml block

schema.yml
<code type="yml">
---
User: 
  columns: 
    id: 
      notnull: true
      primary: true
      autoincrement: true
      type: integer
      length: 4
      name: id
    username: 
      type: string
      length: 255
  relations:
    Groups:
      class: Group
      refClass: UserGroup
      local: user_id
      foreign: group_id
      type: many
UserGroup:
  columns:
    user_id:
      type: integer
      length: 4
      primary: true
    group_id:
      type: integer
      length: 4
      primary: true
  relations:
    User:
      local: user_id
      foreign: id
    Group:
      local: group_id
      foreign: id
Group: 
  columns: 
    id: 
      notnull: true
      primary: true
      autoincrement: true
      type: integer
      length: 4
      name: id
    name: 
      type: string
      length: 255
  relations:
    Users:
      class: User
      refClass: UserGroup
      local: group_id
      foreign: user_id
      type: many
</code>

And now we want to use some Doctrine code to parse that schema yml file and generate our models from it

<code type="php">
// This code will generate the models for schema.yml at /path/to/generate/models
$import = new Doctrine_Import_Schema();
$import->importSchema('schema.yml', 'yml', '/path/to/generate/models');
</code>

This is the directory structure that would be generated at /path/to/generate/models

<code>
- Group.class.php
- User.class.php
- UserGroup.class.php
- generated
  - BaseGroup.class.php
  - BaseUser.class.php
  - BaseUserGroup.class.php
</code>

And finally here is the code for each of the generated models

<code type="php">

// Group.class.php

/**
 * This class has been auto-generated by the Doctrine ORM Framework
 */
class Group extends BaseGroup
{
}

// User.class.php

/**
 * This class has been auto-generated by the Doctrine ORM Framework
 */
class User extends BaseUser
{
}

// UserGroup.class.php

/**
 * This class has been auto-generated by the Doctrine ORM Framework
 */
class UserGroup extends BaseUserGroup
{
}

// BaseGroup.class.php

/**
 * This class has been auto-generated by the Doctrine ORM Framework
 */
abstract class BaseGroup extends sfDoctrineRecord
{

		public function setTableDefinition()
		{
        $this->setTableName('group');
        $this->hasColumn('id', 'integer', 4, array('notnull' => true,
                                                   'primary' => true,
                                                   'autoincrement' => true));
        $this->hasColumn('name', 'string', 255);
		}

		public function setUp()
		{
        $this->hasMany('User as Users', array('refClass' => 'UserGroup',
                                              'local' => 'group_id',
                                              'foreign' => 'user_id'));
		}
}

// BaseUser.class.php

/**
 * This class has been auto-generated by the Doctrine ORM Framework
 */
abstract class BaseUser extends sfDoctrineRecord
{

		public function setTableDefinition()
		{
        $this->setTableName('user_table');
        $this->hasColumn('id', 'integer', 4, array('notnull' => true,
                                                   'primary' => true,
                                                   'autoincrement' => true));
        $this->hasColumn('username', 'string', 255);
		}

		public function setUp()
		{
        $this->hasMany('Group as Groups', array('refClass' => 'UserGroup',
                                                'local' => 'user_id',
                                                'foreign' => 'group_id'));
		}
}

// BaseUserGroup.class.php

/**
 * This class has been auto-generated by the Doctrine ORM Framework
 */
abstract class BaseUserGroup extends sfDoctrineRecord
{

		public function setTableDefinition()
		{
        $this->setTableName('user_group');
        $this->hasColumn('user_id', 'integer', 4, array('primary' => true));
        $this->hasColumn('group_id', 'integer', 4, array('primary' => true));
		}

		public function setUp()
		{
        $this->hasOne('User', array('local' => 'user_id',
                                    'foreign' => 'id'));
        $this->hasOne('Group', array('local' => 'group_id',
                                     'foreign' => 'id'));
		}
}
</code>

++ Additional Schema Options

It isn't necessary to define both sides of a relationship in the schema.yml file as doctrine will attempt to autocomplete the relationships for you. If you choose to define only one side of the relationship, there are two yaml options you can pass to help doctrine decide how to complete the opposite end of the relationship. For example.

schema.yml
<code type="yml">
---
Table1:
  tableName: table_1
  relations: 
    Table2Alias:
      class: Table2
      local: foreign_key
      type: one
      foreignAlias: Table1Alias
      foreignType: one
  columns:
    column_1: { type: string, length: 128 }
    foreign_key: { type: integer, length: 4 }<commit_msg>Updated manual for "Implemented generation of indexes and their definitions from schema files".<commit_after>++ Introduction

The purpose of schema files is to allow you to manage your model definitions directly from a yaml file rather then editing php code. The yaml schema file is parsed and used to generate all your model definitions/classes.

++ Example Schema File

'tableName' and 'className' are optional. If not specified they will be set by the key of the yaml block

schema.yml
<code type="yml">
---
User: 
  columns: 
    id: 
      notnull: true
      primary: true
      autoincrement: true
      type: integer
      length: 4
      name: id
    username: 
      type: string
      length: 255
  relations:
    Groups:
      class: Group
      refClass: UserGroup
      local: user_id
      foreign: group_id
      type: many
UserGroup:
  columns:
    user_id:
      type: integer
      length: 4
      primary: true
    group_id:
      type: integer
      length: 4
      primary: true
  relations:
    User:
      local: user_id
      foreign: id
    Group:
      local: group_id
      foreign: id
Group: 
  columns: 
    id: 
      notnull: true
      primary: true
      autoincrement: true
      type: integer
      length: 4
      name: id
    name: 
      type: string
      length: 255
  relations:
    Users:
      class: User
      refClass: UserGroup
      local: group_id
      foreign: user_id
      type: many
</code>

And now we want to use some Doctrine code to parse that schema yml file and generate our models from it

<code type="php">
// This code will generate the models for schema.yml at /path/to/generate/models
$import = new Doctrine_Import_Schema();
$import->importSchema('schema.yml', 'yml', '/path/to/generate/models');
</code>

This is the directory structure that would be generated at /path/to/generate/models

<code>
- Group.class.php
- User.class.php
- UserGroup.class.php
- generated
  - BaseGroup.class.php
  - BaseUser.class.php
  - BaseUserGroup.class.php
</code>

And finally here is the code for each of the generated models

<code type="php">

// Group.class.php

/**
 * This class has been auto-generated by the Doctrine ORM Framework
 */
class Group extends BaseGroup
{
}

// User.class.php

/**
 * This class has been auto-generated by the Doctrine ORM Framework
 */
class User extends BaseUser
{
}

// UserGroup.class.php

/**
 * This class has been auto-generated by the Doctrine ORM Framework
 */
class UserGroup extends BaseUserGroup
{
}

// BaseGroup.class.php

/**
 * This class has been auto-generated by the Doctrine ORM Framework
 */
abstract class BaseGroup extends sfDoctrineRecord
{

		public function setTableDefinition()
		{
        $this->setTableName('group');
        $this->hasColumn('id', 'integer', 4, array('notnull' => true,
                                                   'primary' => true,
                                                   'autoincrement' => true));
        $this->hasColumn('name', 'string', 255);
		}

		public function setUp()
		{
        $this->hasMany('User as Users', array('refClass' => 'UserGroup',
                                              'local' => 'group_id',
                                              'foreign' => 'user_id'));
		}
}

// BaseUser.class.php

/**
 * This class has been auto-generated by the Doctrine ORM Framework
 */
abstract class BaseUser extends sfDoctrineRecord
{

		public function setTableDefinition()
		{
        $this->setTableName('user_table');
        $this->hasColumn('id', 'integer', 4, array('notnull' => true,
                                                   'primary' => true,
                                                   'autoincrement' => true));
        $this->hasColumn('username', 'string', 255);
		}

		public function setUp()
		{
        $this->hasMany('Group as Groups', array('refClass' => 'UserGroup',
                                                'local' => 'user_id',
                                                'foreign' => 'group_id'));
		}
}

// BaseUserGroup.class.php

/**
 * This class has been auto-generated by the Doctrine ORM Framework
 */
abstract class BaseUserGroup extends sfDoctrineRecord
{

		public function setTableDefinition()
		{
        $this->setTableName('user_group');
        $this->hasColumn('user_id', 'integer', 4, array('primary' => true));
        $this->hasColumn('group_id', 'integer', 4, array('primary' => true));
		}

		public function setUp()
		{
        $this->hasOne('User', array('local' => 'user_id',
                                    'foreign' => 'id'));
        $this->hasOne('Group', array('local' => 'group_id',
                                     'foreign' => 'id'));
		}
}
</code>

++ Indexes

Please see chapter [doc basic-schema-mapping :index :name] for more information about indexes and their options.

schema.yml
<code type="yml">
---
UserProfile:
  tableName: user_profile
  columns:
    user_id: { type: integer, length: 4, primary: true, autoincrement: true }
    first_name: { type: string, length: 20 }
    last_name: { type: string, length: 20 }
  indexes:
    name_index:
      fields:
        first_name:
          sorting: ASC
          length: 10
          primary: true
        last_name: ~
      type: unique
</code>

This is the PHP line of code that is auto-generated inside setTableDefinition() inside your base model class.

Note: Don't mind the extra trailing commas. This is normal and they should not affect anything negatively.

<code type="php">
<?php

class BaseUserProfile extends Doctrine_Record
{

	public function setTableDefinition()
	{
        // code

		$this->index('name_index', array('fields' => array('first_name' => array( 'sorting' => 'ASC', 'length' => '10', 'primary' => true, ), 'last_name' => array( ), ), 'type' => 'unique'));
	}
}

?>
</code>

++ Additional Schema Options

It isn't necessary to define both sides of a relationship in the schema.yml file as doctrine will attempt to autocomplete the relationships for you. If you choose to define only one side of the relationship, there are two yaml options you can pass to help doctrine decide how to complete the opposite end of the relationship. For example.

schema.yml
<code type="yml">
---
Table1:
  tableName: table_1
  relations: 
    Table2Alias:
      class: Table2
      local: foreign_key
      type: one
      foreignAlias: Table1Alias
      foreignType: one
  columns:
    column_1: { type: string, length: 128 }
    foreign_key: { type: integer, length: 4 }
{'fraction_non_alphanumeric': 0.10566421132842266, 'fraction_numerical': 0.005842011684023368, 'mean_word_length': 2.2684006640841172, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 98, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 36, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4993355', 'n_tokens_mistral': 3407, 'n_tokens_neox': 3216, 'n_words': 1124}