The database is used for storing majority of user entered data (except user uploaded files). Almost each database table has associated unit, that is responsible for reading/writing data from it.
Following is missing however:
- the unit isn't aware/responsible for the indexes added to associated table
- cross-table relations are not stored anywhere (even in database itself)
- adding new fields to database is not error-prone, because:
- developer needs to switch to DB application (Navicat, Sequel Pro, phpMyAdmin)
- developer needs to enter several values to configure new field (field name, field type, field value size, null/not null, default value)
- developer needs to go to "System Tools" section in Admin Console
- developer needs to type in unit name to see "Fields" array content
- developer needs to copy/paste relevant changed field declarations from there to the unit config in IDE
Solution
- describe database table columns in "
Fields
" array:- make "
db_type
" field option used to describe database type (e.g. "varchar(255)") required - add new optional "
db_extra
" field option of array type, where "auto_increment" and other db column options are defined
- make "
describe index structure in the new "
Indexes
" unit config option like so (the field specified in "IDField" of unit config is automatically assigned an "auto_increment" db extra and added as primary key):'Indexes' => array( 'IDX_INDEX_NAME' => array( 'columns' => array('DBColumn1', 'DBColumn2'), 'unique' => true, ), ),
- create the "in-portal db:sync" command, that will:
- create missing database tables
- change structure of existing tables to match one from unit config (but won't delete columns/tables, because of performance)
- integrate code, that creates multi-lingual columns (e.g. "l1_Name") into this command
- replace "Rebuild Multilingual Fields" action on "System Tools" page with "Rebuild Database Structure" action that would call above created command
- run above created command before SQL migrations during deploy
if table column has association with another database table, then define it via new "foreign_key" field option (won't be used for now) like so:
'Fields' => array( 'ItemResourceId' => array( 'type' => 'int', ..., 'default' => null, 'foreign_key' => 'l:ResourceId' ), ),