-
Notifications
You must be signed in to change notification settings - Fork 27
Setting Up Your First Table
John James Jacoby edited this page May 27, 2026
·
2 revisions
A queryable BerlinDB table usually has four small classes:
- A
Schemaclass that defines columns and indexes. - A
Rowclass that shapes returned records. - A
Queryclass that reads and writes records. - A
Tableclass that creates, upgrades, and manages the physical database table.
The example below creates a widgets table for a plugin with the prefix acme.
namespace Acme\Database;
use BerlinDB\Database\Kern\Schema;
class WidgetSchema extends Schema {
protected $columns = array(
array(
'name' => 'id',
'type' => 'bigint',
'length' => 20,
'unsigned' => true,
'primary' => true,
'extra' => 'auto_increment',
'in' => true,
'not_in' => true,
'cache_key' => true,
'sortable' => true,
),
array(
'name' => 'uuid',
'type' => 'varchar',
'length' => 100,
'uuid' => true,
'cache_key' => true,
),
array(
'name' => 'name',
'type' => 'varchar',
'length' => 191,
'default' => '',
'searchable' => true,
'sortable' => true,
),
array(
'name' => 'status',
'type' => 'varchar',
'length' => 20,
'default' => 'active',
'in' => true,
'not_in' => true,
),
array(
'name' => 'created',
'type' => 'datetime',
'created' => true,
'date_query' => true,
'sortable' => true,
),
array(
'name' => 'modified',
'type' => 'datetime',
'modified' => true,
'date_query' => true,
'sortable' => true,
),
);
protected $indexes = array(
array(
'name' => 'status',
'type' => 'key',
'columns' => array( 'status' ),
),
array(
'name' => 'uuid',
'type' => 'unique',
'columns' => array( 'uuid' ),
),
);
}namespace Acme\Database;
use BerlinDB\Database\Kern\Row;
class Widget extends Row {
protected $primary_column = 'id';
protected $casts = array(
'id' => 'intval',
);
}The row object is where application-facing compatibility belongs. If a database column is renamed later, the row object can preserve old property names or formatting without leaking schema churn into the rest of the plugin.
namespace Acme\Database;
use BerlinDB\Database\Kern\Query;
class WidgetQuery extends Query {
protected $table_name = 'widgets';
protected $table_alias = 'w';
protected $table_schema = WidgetSchema::class;
protected $item_name = 'widget';
protected $item_name_plural = 'widgets';
protected $item_shape = Widget::class;
protected $cache_group = 'acme_widgets';
}Use the query class in application code:
$query = new WidgetQuery();
$widget_id = $query->add_item(
array(
'name' => 'Example Widget',
'status' => 'active',
)
);
$widget = $query->get_item( $widget_id );namespace Acme\Database;
use BerlinDB\Database\Kern\Table;
class WidgetsTable extends Table {
protected $name = 'widgets';
protected $description = 'Acme widgets';
protected $prefix = 'acme';
protected $version = '1.0.0';
protected $db_version_key = 'acme_widgets_db_version';
protected $schema = WidgetSchema::class;
}Create or upgrade the table from plugin bootstrap code:
add_action(
'admin_init',
static function () {
$table = new Acme\Database\WidgetsTable();
$table->maybe_upgrade();
}
);During the PHPUnit test suite, BerlinDB detects the test environment and can force upgrades immediately.
-
Table::$nameis the unprefixed table name. -
Table::$prefixis your plugin or application prefix. - WordPress'
$wpdb->prefixis still prepended by the connection adapter. - In the example above, the final table name is usually
wp_acme_widgets.
Read Writing Queries for filtering, sorting, CRUD, and parser-backed query vars.