Summary
Declaring a BerlinDB schema today requires authors to remember — and correctly spell out — every attribute for every common column pattern. A status column is always varchar(20) with transition, cache_key, sortable, in, and not_in. A UUID column is always varchar(100) with a specific set of constraints. A meta table is always the same four columns. None of this needs to be re-typed every time.
A three-layer Preset system would let schema authors express intent rather than implementation:
// Today
array(
'name' => 'status',
'type' => 'varchar',
'length' => '20',
'default' => 'active',
'cache_key' => true,
'transition' => true,
'sortable' => true,
'in' => true,
'not_in' => true,
),
// With presets
ColumnPreset::status( 'active' ),
Layer 1: ColumnPreset
Static factory methods returning validated column definition arrays, fully compatible with the existing Schema $columns format. No changes to Column, Schema, or Query required.
Core presets
| Method |
Recipe |
primary( $name = 'id' ) |
bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, pk, cache_key |
uuid() |
varchar(100), existing uuid behaviour |
created( $name = 'date_created' ) |
datetime, created flag, zero datetime default |
modified( $name = 'date_modified' ) |
datetime, modified flag, ON UPDATE CURRENT_TIMESTAMP |
status( $default, $name = 'status' ) |
varchar(20), transition, cache_key, sortable, in/not_in |
title( $name = 'title' ) |
varchar(200), searchable, sortable |
slug( $name = 'slug' ) |
varchar(200), searchable, cache_key |
content( $name = 'content' ) |
longtext |
count( $name = 'count' ) |
bigint(20) UNSIGNED, sortable, in/not_in |
foreign_key( $name ) |
bigint(20) UNSIGNED, relationships hook |
meta_key() |
varchar(255), searchable |
meta_value() |
longtext, allow_null |
All presets accept overrides — any column attribute can be merged on top of the preset defaults for custom needs.
Layer 2: SchemaPreset
Pre-built column groups for schemas that are always structurally the same.
MetaSchema
WordPress meta tables are identical across every object type. MetaSchema codifies the standard four-column layout; the only variation is the object column name:
class PostMetaSchema extends MetaSchema {
protected $object_column = 'post_id';
}
Internally this wires up ColumnPreset::primary('meta_id'), a foreign key column, ColumnPreset::meta_key(), and ColumnPreset::meta_value() along with the standard indexes.
Column group mixins
Composable groups of columns that can be folded into any schema:
TimestampColumns — created + modified datetime pair
SoftDeleteColumns — deleted_at datetime column
Layer 3: TablePreset / Base Table classes
For standard table types with well-known schemas, a base Table subclass eliminates the boilerplate of schema, versioning, and table options. The right form here is a class hierarchy rather than a static factory, since Table carries runtime state.
MetaTable
class PostMetaTable extends MetaTable {
protected $object_column = 'post_id';
protected $version = '1.0.0';
}
MetaTable wires up the MetaSchema, standard table prefix conventions, and a default upgrade path. Every plugin that needs post/user/comment/term/custom-object metadata would use this as a starting point.
Composition
The three layers compose naturally:
TablePreset (MetaTable)
└── uses SchemaPreset (MetaSchema)
└── uses ColumnPreset (primary, foreign_key, meta_key, meta_value)
A plugin author who just needs a standard meta table writes three lines. One who needs a custom schema with timestamps folds in TimestampColumns. One who needs full control still uses raw column arrays — presets are additive, not mandatory.
Non-goals
Related issues
Summary
Declaring a BerlinDB schema today requires authors to remember — and correctly spell out — every attribute for every common column pattern. A status column is always
varchar(20)withtransition,cache_key,sortable,in, andnot_in. A UUID column is alwaysvarchar(100)with a specific set of constraints. A meta table is always the same four columns. None of this needs to be re-typed every time.A three-layer Preset system would let schema authors express intent rather than implementation:
Layer 1:
ColumnPresetStatic factory methods returning validated column definition arrays, fully compatible with the existing Schema
$columnsformat. No changes toColumn,Schema, orQueryrequired.Core presets
primary( $name = 'id' )bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, pk, cache_keyuuid()varchar(100), existing uuid behaviourcreated( $name = 'date_created' )datetime, created flag, zero datetime defaultmodified( $name = 'date_modified' )datetime, modified flag,ON UPDATE CURRENT_TIMESTAMPstatus( $default, $name = 'status' )varchar(20), transition, cache_key, sortable, in/not_intitle( $name = 'title' )varchar(200), searchable, sortableslug( $name = 'slug' )varchar(200), searchable, cache_keycontent( $name = 'content' )longtextcount( $name = 'count' )bigint(20) UNSIGNED, sortable, in/not_inforeign_key( $name )bigint(20) UNSIGNED, relationships hookmeta_key()varchar(255), searchablemeta_value()longtext, allow_nullAll presets accept overrides — any column attribute can be merged on top of the preset defaults for custom needs.
Layer 2:
SchemaPresetPre-built column groups for schemas that are always structurally the same.
MetaSchemaWordPress meta tables are identical across every object type.
MetaSchemacodifies the standard four-column layout; the only variation is the object column name:Internally this wires up
ColumnPreset::primary('meta_id'), a foreign key column,ColumnPreset::meta_key(), andColumnPreset::meta_value()along with the standard indexes.Column group mixins
Composable groups of columns that can be folded into any schema:
TimestampColumns—created+modifieddatetime pairSoftDeleteColumns—deleted_atdatetime columnLayer 3:
TablePreset/ Base Table classesFor standard table types with well-known schemas, a base
Tablesubclass eliminates the boilerplate of schema, versioning, and table options. The right form here is a class hierarchy rather than a static factory, sinceTablecarries runtime state.MetaTableMetaTablewires up theMetaSchema, standard table prefix conventions, and a default upgrade path. Every plugin that needs post/user/comment/term/custom-object metadata would use this as a starting point.Composition
The three layers compose naturally:
A plugin author who just needs a standard meta table writes three lines. One who needs a custom schema with timestamps folds in
TimestampColumns. One who needs full control still uses raw column arrays — presets are additive, not mandatory.Non-goals
Related issues
foreign_keypreset)